View Javadoc
1   /*
2    * (c) Copyright 2006-2020 by rapiddweller GmbH & Volker Bergmann. All rights reserved.
3    *
4    * Redistribution and use in source and binary forms, with or without
5    * modification, is permitted under the terms of the
6    * GNU General Public License.
7    *
8    * For redistributing this software or a derivative work under a license other
9    * than the GPL-compatible Free Software License as defined by the Free
10   * Software Foundation or approved by OSI, you must first obtain a commercial
11   * license to this software product from rapiddweller GmbH & Volker Bergmann.
12   *
13   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14   * WITHOUT A WARRANTY OF ANY KIND. ALL EXPRESS OR IMPLIED CONDITIONS,
15   * REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF
16   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE
17   * HEREBY EXCLUDED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24   * POSSIBILITY OF SUCH DAMAGE.
25   */
26  
27  package com.rapiddweller.model.data;
28  
29  import com.rapiddweller.benerator.engine.expression.ScriptExpression;
30  import com.rapiddweller.common.operation.AndOperation;
31  import com.rapiddweller.common.operation.OrOperation;
32  import com.rapiddweller.script.Expression;
33  import com.rapiddweller.script.expression.ConstantExpression;
34  import com.rapiddweller.script.expression.TypeConvertingExpression;
35  
36  /**
37   * Describes generation of (several) entities of a type by uniqueness,
38   * nullability and count characteristics.<br/><br/>
39   * Created: 03.03.2008 07:55:45
40   *
41   * @author Volker Bergmann
42   * @since 0.5.0
43   */
44  public class InstanceDescriptor extends FeatureDescriptor {
45  
46    /**
47     * The constant TYPE.
48     */
49    public static final String TYPE = "type";
50  
51    /**
52     * The constant UNIQUE.
53     */
54    public static final String UNIQUE = "unique";
55    /**
56     * The constant NULLABLE.
57     */
58    public static final String NULLABLE = "nullable";
59    /**
60     * The constant MIN_COUNT.
61     */
62    public static final String MIN_COUNT = "minCount";
63    /**
64     * The constant MAX_COUNT.
65     */
66    public static final String MAX_COUNT = "maxCount";
67    /**
68     * The constant CONTAINER.
69     */
70    public static final String CONTAINER = "container";
71  
72    /**
73     * The constant COUNT_GRANULARITY.
74     */
75    public static final String COUNT_GRANULARITY = "countGranularity";
76    /**
77     * The constant COUNT_DISTRIBUTION.
78     */
79    public static final String COUNT_DISTRIBUTION = "countDistribution";
80    /**
81     * The constant COUNT.
82     */
83    public static final String COUNT = "count";
84    /**
85     * The constant NULL_QUOTA.
86     */
87    public static final String NULL_QUOTA = "nullQuota";
88    /**
89     * The constant MODE.
90     */
91    public static final String MODE = "mode";
92  
93  
94    private InstanceDescriptor parent;
95    private TypeDescriptor localType;
96  
97    // constructors ----------------------------------------------------------------------------------------------------
98  
99    /**
100    * Instantiates a new Instance descriptor.
101    *
102    * @param name     the name
103    * @param provider the provider
104    */
105   public InstanceDescriptor(String name, DescriptorProvider provider) {
106     this(name, provider, null, null);
107   }
108 
109   /**
110    * Instantiates a new Instance descriptor.
111    *
112    * @param name     the name
113    * @param provider the provider
114    * @param typeName the type name
115    */
116   public InstanceDescriptor(String name, DescriptorProvider provider,
117                             String typeName) {
118     this(name, provider, typeName, null);
119   }
120 
121   /**
122    * Instantiates a new Instance descriptor.
123    *
124    * @param name      the name
125    * @param provider  the provider
126    * @param localType the local type
127    */
128   public InstanceDescriptor(String name, DescriptorProvider provider,
129                             TypeDescriptor localType) {
130     this(name, provider, null, localType);
131   }
132 
133   /**
134    * Instantiates a new Instance descriptor.
135    *
136    * @param name      the name
137    * @param provider  the provider
138    * @param typeName  the type name
139    * @param localType the local type
140    */
141   protected InstanceDescriptor(String name, DescriptorProvider provider,
142                                String typeName, TypeDescriptor localType) {
143     super(name, provider);
144     this.localType = localType;
145 
146     addConstraint(TYPE, String.class, null);
147     setType(typeName);
148 
149     // constraints
150     addConstraint(UNIQUE, Boolean.class, new OrOperation());
151     addConstraint(NULLABLE, Boolean.class, new AndOperation());
152     addConstraint(MIN_COUNT, Expression.class, null);
153     addConstraint(MAX_COUNT, Expression.class, null);
154     addConstraint(CONTAINER, String.class, null);
155 
156     // configs
157     addConfig(COUNT, Expression.class);
158     addConfig(COUNT_GRANULARITY, Expression.class);
159     addConfig(COUNT_DISTRIBUTION, String.class);
160     addConfig(NULL_QUOTA, Double.class);
161     addConfig(MODE, Mode.class);
162   }
163 
164   // properties ------------------------------------------------------------------------------------------------------
165 
166   /**
167    * Sets parent.
168    *
169    * @param parent the parent
170    */
171   public void setParent(InstanceDescriptor parent) {
172     this.parent = parent;
173   }
174 
175   @Override
176   public String getName() {
177     String result = super.getName();
178     return (result != null ? result : getType());
179   }
180 
181   /**
182    * Gets type.
183    *
184    * @return the type
185    */
186   public String getType() {
187     String type = (String) getDetailValue(TYPE);
188     return (type == null && parent != null ? parent.getType() : type);
189   }
190 
191   /**
192    * Sets type.
193    *
194    * @param type the type
195    */
196   public void setType(String type) {
197     setDetailValue(TYPE, type);
198   }
199 
200   /**
201    * Gets type descriptor.
202    *
203    * @return the type descriptor
204    */
205   public TypeDescriptor getTypeDescriptor() {
206     if (getLocalType() != null) {
207       return getLocalType();
208     }
209     TypeDescriptor type = null;
210     if (getType() != null) {
211       type = getDataModel().getTypeDescriptor(getType());
212     }
213     return type;
214   }
215 
216   /**
217    * Gets local type.
218    *
219    * @return the local type
220    */
221   public TypeDescriptor getLocalType() {
222     if (localType == null && parent != null &&
223         parent.getLocalType() != null) {
224       localType = getLocalType(
225           parent.getLocalType() instanceof ComplexTypeDescriptor);
226     }
227     return localType;
228   }
229 
230   /**
231    * Sets local type.
232    *
233    * @param localType the local type
234    */
235   public void setLocalType(TypeDescriptor localType) {
236     this.localType = localType;
237     if (localType != null) {
238       setType(null);
239     }
240   }
241 
242   /**
243    * Gets local type.
244    *
245    * @param complexType the complex type
246    * @return the local type
247    */
248   public TypeDescriptor getLocalType(boolean complexType) {
249     if (localType != null) {
250       return localType;
251     }
252     if (complexType) {
253       localType =
254           new ComplexTypeDescriptor(getName(), provider, getType());
255     } else {
256       localType =
257           new SimpleTypeDescriptor(getName(), provider, getType());
258     }
259     setType(null);
260     return localType;
261   }
262 
263   /**
264    * Is unique boolean.
265    *
266    * @return the boolean
267    */
268   public Boolean isUnique() {
269     return (Boolean) getDetailValue(UNIQUE);
270   }
271 
272   /**
273    * Sets unique.
274    *
275    * @param unique the unique
276    */
277   public void setUnique(Boolean unique) {
278     setDetailValue(UNIQUE, unique);
279   }
280 
281   /**
282    * Gets uniqueness.
283    *
284    * @return the uniqueness
285    */
286   public Uniqueness getUniqueness() {
287     Boolean unique = isUnique();
288     return (unique != null ?
289         (unique ? Uniqueness.SIMPLE : Uniqueness.NONE) : null);
290   }
291 
292   /**
293    * Is nullable boolean.
294    *
295    * @return the boolean
296    */
297   public Boolean isNullable() {
298     Boolean value = (Boolean) super.getDetailValue(NULLABLE);
299     if (value == null && parent != null) {
300       FeatureDetail<?> detail = parent.getConfiguredDetail(NULLABLE);
301       if (detail.getValue() != null && !(Boolean) detail.getValue()) {
302         value = (Boolean) detail.getValue();
303       }
304     }
305     return value;
306   }
307 
308   /**
309    * Sets nullable.
310    *
311    * @param nullable the nullable
312    */
313   public void setNullable(Boolean nullable) {
314     setDetailValue(NULLABLE, nullable);
315   }
316 
317   /**
318    * Gets min count.
319    *
320    * @return the min count
321    */
322   @SuppressWarnings("unchecked")
323   public Expression<Long> getMinCount() {
324     return (Expression<Long>) getDetailValue(MIN_COUNT);
325   }
326 
327   /**
328    * Sets min count.
329    *
330    * @param minCount the min count
331    */
332   public void setMinCount(Expression<Long> minCount) {
333     setDetailValue(MIN_COUNT, minCount);
334   }
335 
336   /**
337    * Gets max count.
338    *
339    * @return the max count
340    */
341   @SuppressWarnings("unchecked")
342   public Expression<Long> getMaxCount() {
343     return (Expression<Long>) getDetailValue(MAX_COUNT);
344   }
345 
346   /**
347    * Sets max count.
348    *
349    * @param maxCount the max count
350    */
351   public void setMaxCount(Expression<Long> maxCount) {
352     setDetailValue(MAX_COUNT, maxCount);
353   }
354 
355   /**
356    * Gets container.
357    *
358    * @return the container
359    */
360   public String getContainer() {
361     return (String) getDetailValue(CONTAINER);
362   }
363 
364   /**
365    * Sets container.
366    *
367    * @param container the container
368    */
369   public void setContainer(String container) {
370     setDetailValue(CONTAINER, container);
371   }
372 
373   /**
374    * Gets count.
375    *
376    * @return the count
377    */
378   @SuppressWarnings("unchecked")
379   public Expression<Long> getCount() {
380     return (Expression<Long>) getDetailValue(COUNT);
381   }
382 
383   /**
384    * Sets count.
385    *
386    * @param count the count
387    */
388   public void setCount(Expression<Long> count) {
389     setDetailValue(COUNT, count);
390   }
391 
392   /**
393    * Gets count distribution.
394    *
395    * @return the count distribution
396    */
397   public String getCountDistribution() {
398     return (String) getDetailValue(COUNT_DISTRIBUTION);
399   }
400 
401   /**
402    * Sets count distribution.
403    *
404    * @param distribution the distribution
405    */
406   public void setCountDistribution(String distribution) {
407     setDetailValue(COUNT_DISTRIBUTION, distribution);
408   }
409 
410   /**
411    * Gets count granularity.
412    *
413    * @return the count granularity
414    */
415   @SuppressWarnings("unchecked")
416   public Expression<Long> getCountGranularity() {
417     return (Expression<Long>) getDetailValue(COUNT_GRANULARITY);
418   }
419 
420   /**
421    * Sets count granularity.
422    *
423    * @param distribution the distribution
424    */
425   public void setCountGranularity(Expression<Long> distribution) {
426     setDetailValue(COUNT_GRANULARITY, distribution);
427   }
428 
429   /**
430    * Gets null quota.
431    *
432    * @return the null quota
433    */
434   public Double getNullQuota() {
435     return (Double) getDetailValue(NULL_QUOTA);
436   }
437 
438   /**
439    * Sets null quota.
440    *
441    * @param nullQuota the null quota
442    */
443   public void setNullQuota(Double nullQuota) {
444     setDetailValue(NULL_QUOTA, nullQuota);
445   }
446 
447   /**
448    * Gets mode.
449    *
450    * @return the mode
451    */
452   public Mode getMode() {
453     return (Mode) getDetailValue(MODE);
454   }
455 
456   /**
457    * Sets mode.
458    *
459    * @param mode the mode
460    */
461   public void setMode(Mode mode) {
462     setDetailValue(MODE, mode);
463   }
464 
465   @Override
466   public Object getDetailValue(String name) {
467     Object value = super.getDetailValue(name);
468     if (value == null && parent != null && parent.supportsDetail(name)) {
469       FeatureDetail<?> detail = parent.getConfiguredDetail(name);
470       if (detail.isConstraint()) {
471         value = detail.getValue();
472       }
473     }
474     return value;
475   }
476 
477   @Override
478   public void setDetailValue(String detailName, Object detailValue) {
479     if (COUNT.equals(detailName) || MIN_COUNT.equals(detailName) ||
480         MAX_COUNT.equals(detailName) ||
481         COUNT_GRANULARITY.equals(detailName)) {
482       FeatureDetail<Object> detail = getConfiguredDetail(detailName);
483       if (detail == null) {
484         throw new UnsupportedOperationException(
485             getClass().getSimpleName() +
486                 " does not support detail type: " + detailName);
487       }
488       if (detailValue instanceof Expression) {
489         detail.setValue(new TypeConvertingExpression<>(
490             (Expression<?>) detailValue, Long.class));
491       } else if (detailValue == null) {
492         detail.setValue(null);
493       } else if (detailValue instanceof String) {
494         detail.setValue(new TypeConvertingExpression<>(
495             new ScriptExpression<>((String) detailValue),
496             Long.class));
497       } else {
498         detail.setValue(new TypeConvertingExpression<>(
499             new ConstantExpression<>(detailValue), Long.class));
500       }
501     } else {
502       super.setDetailValue(detailName, detailValue);
503     }
504   }
505 
506   // convenience 'with...' methods -----------------------------------------------------------------------------------
507 
508   /**
509    * With count instance descriptor.
510    *
511    * @param count the count
512    * @return the instance descriptor
513    */
514   public InstanceDescriptor withCount(long count) {
515     setCount(new ConstantExpression<>(count));
516     return this;
517   }
518 
519   /**
520    * With min count instance descriptor.
521    *
522    * @param minCount the min count
523    * @return the instance descriptor
524    */
525   public InstanceDescriptor withMinCount(long minCount) {
526     setMinCount(new ConstantExpression<>(minCount));
527     return this;
528   }
529 
530   /**
531    * With max count instance descriptor.
532    *
533    * @param maxCount the max count
534    * @return the instance descriptor
535    */
536   public InstanceDescriptor withMaxCount(long maxCount) {
537     setMaxCount(new ConstantExpression<>(maxCount));
538     return this;
539   }
540 
541   /**
542    * With null quota instance descriptor.
543    *
544    * @param nullQuota the null quota
545    * @return the instance descriptor
546    */
547   public InstanceDescriptor withNullQuota(double nullQuota) {
548     setNullQuota(nullQuota);
549     return this;
550   }
551 
552   /**
553    * With unique instance descriptor.
554    *
555    * @param unique the unique
556    * @return the instance descriptor
557    */
558   public InstanceDescriptor withUnique(boolean unique) {
559     setUnique(unique);
560     return this;
561   }
562 
563   /**
564    * Overwrites parent boolean.
565    *
566    * @return the boolean
567    */
568   public boolean overwritesParent() {
569     return parent != null;
570   }
571 
572   @Override
573   public String toString() {
574     return getName() + "[details=" + renderDetails() + ", type=" +
575         getTypeDescriptor() + "]";
576   }
577 
578 }