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.common.ArrayBuilder;
30  import com.rapiddweller.common.CollectionUtil;
31  import com.rapiddweller.common.StringUtil;
32  import com.rapiddweller.common.collection.ListBasedSet;
33  import com.rapiddweller.common.collection.NamedValueList;
34  
35  import java.util.ArrayList;
36  import java.util.Collection;
37  import java.util.List;
38  import java.util.Objects;
39  import java.util.Set;
40  
41  /**
42   * Describes a type that aggregates {@link ComponentDescriptor}s.<br/>
43   * <br/>
44   * Created: 03.03.2008 10:56:16
45   *
46   * @author Volker Bergmann
47   * @since 0.5.0
48   */
49  public class ComplexTypeDescriptor extends TypeDescriptor
50      implements VariableHolder {
51  
52    /**
53     * The constant __SIMPLE_CONTENT.
54     */
55    public static final String __SIMPLE_CONTENT = "__SIMPLE_CONTENT";
56  
57    private NamedValueList<InstanceDescriptor> parts;
58  
59    // constructors ----------------------------------------------------------------------------------------------------
60  
61    /**
62     * Instantiates a new Complex type descriptor.
63     *
64     * @param name     the name
65     * @param provider the provider
66     */
67    public ComplexTypeDescriptor(String name, DescriptorProvider provider) {
68      this(name, provider, (String) null);
69    }
70  
71    /**
72     * Instantiates a new Complex type descriptor.
73     *
74     * @param name     the name
75     * @param provider the provider
76     * @param parent   the parent
77     */
78    public ComplexTypeDescriptor(String name, DescriptorProvider provider,
79                                 ComplexTypeDescriptor parent) {
80      super(name, provider, parent);
81      init();
82    }
83  
84    /**
85     * Instantiates a new Complex type descriptor.
86     *
87     * @param name       the name
88     * @param provider   the provider
89     * @param parentName the parent name
90     */
91    public ComplexTypeDescriptor(String name, DescriptorProvider provider,
92                                 String parentName) {
93      super(name, provider, parentName);
94      init();
95    }
96  
97    // component handling ----------------------------------------------------------------------------------------------
98  
99    /**
100    * Add part.
101    *
102    * @param part the part
103    */
104   public void addPart(InstanceDescriptor part) {
105     if (part instanceof ComponentDescriptor) {
106       addComponent((ComponentDescriptor) part);
107     } else {
108       addVariable((VariableDescriptor) part);
109     }
110   }
111 
112   /**
113    * Add component.
114    *
115    * @param descriptor the descriptor
116    */
117   public void addComponent(ComponentDescriptor descriptor) {
118     String componentName = descriptor.getName();
119     if (parent != null &&
120         ((ComplexTypeDescriptor) parent).getComponent(componentName) !=
121             null) {
122       descriptor.setParent(((ComplexTypeDescriptor) parent)
123           .getComponent(componentName));
124     }
125     parts.add(componentName, descriptor);
126   }
127 
128   /**
129    * Sets component.
130    *
131    * @param component the component
132    */
133   public void setComponent(ComponentDescriptor component) {
134     String componentName = component.getName();
135     if (parent != null &&
136         ((ComplexTypeDescriptor) parent).getComponent(componentName) !=
137             null) {
138       component.setParent(((ComplexTypeDescriptor) parent)
139           .getComponent(componentName));
140     }
141     parts.set(componentName, component);
142   }
143 
144   /**
145    * Gets component.
146    *
147    * @param name the name
148    * @return the component
149    */
150   public ComponentDescriptor getComponent(String name) {
151     for (InstanceDescriptor part : parts.values()) {
152       if (StringUtil.equalsIgnoreCase(part.getName(), name) &&
153           part instanceof ComponentDescriptor) {
154         return (ComponentDescriptor) part;
155       }
156     }
157     if (getParent() != null) {
158       return ((ComplexTypeDescriptor) getParent()).getComponent(name);
159     }
160     return null;
161   }
162 
163   /**
164    * Gets parts.
165    *
166    * @return the parts
167    */
168   public List<InstanceDescriptor> getParts() {
169     NamedValueList<InstanceDescriptor> result =
170         NamedValueList.createCaseInsensitiveList();
171 
172     for (InstanceDescriptor ccd : parts.values()) {
173       result.add(ccd.getName(), ccd);
174     }
175     if (getParent() != null) {
176       List<InstanceDescriptor> parentParts =
177           ((ComplexTypeDescriptor) getParent()).getParts();
178       for (InstanceDescriptor pcd : parentParts) {
179         String name = pcd.getName();
180         if (pcd instanceof ComponentDescriptor &&
181             !parts.containsName(name)) {
182           InstanceDescriptor ccd = parts.someValueOfName(name);
183           result.add(name, Objects.requireNonNullElse(ccd, pcd));
184         }
185       }
186     }
187     return result.values();
188   }
189 
190   /**
191    * Gets components.
192    *
193    * @return the components
194    */
195   public List<ComponentDescriptor> getComponents() {
196     List<ComponentDescriptor> result = new ArrayList<>();
197     for (InstanceDescriptor instance : getParts()) {
198       if (instance instanceof ComponentDescriptor) {
199         result.add((ComponentDescriptor) instance);
200       }
201     }
202     return result;
203   }
204 
205   /**
206    * Gets declared parts.
207    *
208    * @return the declared parts
209    */
210   public Collection<InstanceDescriptor> getDeclaredParts() {
211     Set<InstanceDescriptor> declaredDescriptors =
212         new ListBasedSet<>(parts.size());
213     declaredDescriptors.addAll(parts.values());
214     return declaredDescriptors;
215   }
216 
217   /**
218    * Is declared component boolean.
219    *
220    * @param componentName the component name
221    * @return the boolean
222    */
223   public boolean isDeclaredComponent(String componentName) {
224     return parts.containsName(componentName);
225   }
226 
227   /**
228    * Get id component names string [ ].
229    *
230    * @return the string [ ]
231    */
232   public String[] getIdComponentNames() {
233     ArrayBuilder<String> builder = new ArrayBuilder<>(String.class);
234     for (ComponentDescriptor descriptor : getComponents()) {
235       if (descriptor instanceof IdDescriptor) {
236         builder.add(descriptor.getName());
237       }
238     }
239     return builder.toArray();
240   }
241 
242   /**
243    * Gets reference components.
244    *
245    * @return the reference components
246    */
247   public List<ReferenceDescriptor> getReferenceComponents() {
248     return CollectionUtil.extractItemsOfExactType(ReferenceDescriptor.class,
249         getComponents());
250   }
251 
252   @Override
253   public void addVariable(VariableDescriptor variable) {
254     parts.add(variable.getName(), variable);
255   }
256 
257   // construction helper methods -------------------------------------------------------------------------------------
258 
259   /**
260    * With component complex type descriptor.
261    *
262    * @param componentDescriptor the component descriptor
263    * @return the complex type descriptor
264    */
265   public ComplexTypeDescriptor withComponent(
266       ComponentDescriptor componentDescriptor) {
267     addComponent(componentDescriptor);
268     return this;
269   }
270 
271   @Override
272   protected void init() {
273     super.init();
274     this.parts = new NamedValueList<>(NamedValueList.INSENSITIVE);
275   }
276 
277   // java.lang.Object overrides --------------------------------------------------------------------------------------
278 
279   @Override
280   public String toString() {
281     if (parts.size() == 0) {
282       return super.toString();
283     }
284     //return new CompositeFormatter(false, false).render(super.toString() + '{', new CompositeAdapter(), "}");
285     return getName() + getParts();
286   }
287 
288 }