View Javadoc
1   package org.codehaus.modello.model;
2   
3   /*
4    * Copyright (c) 2004, Codehaus.org
5    *
6    * Permission is hereby granted, free of charge, to any person obtaining a copy of
7    * this software and associated documentation files (the "Software"), to deal in
8    * the Software without restriction, including without limitation the rights to
9    * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10   * of the Software, and to permit persons to whom the Software is furnished to do
11   * so, subject to the following conditions:
12   *
13   * The above copyright notice and this permission notice shall be included in all
14   * copies or substantial portions of the Software.
15   *
16   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22   * SOFTWARE.
23   */
24  
25  import java.util.ArrayList;
26  import java.util.HashMap;
27  import java.util.List;
28  import java.util.Map;
29  
30  import org.codehaus.modello.ModelloRuntimeException;
31  import org.codehaus.modello.metadata.ModelMetadata;
32  import org.codehaus.modello.plugin.model.ModelClassMetadata;
33  import org.codehaus.plexus.util.StringUtils;
34  
35  /**
36   * @author <a href="mailto:jason@modello.org">Jason van Zyl</a>
37   * @author <a href="mailto:evenisse@codehaus.org">Emmanuel Venisse</a>
38   */
39  public class Model extends BaseElement {
40      private String id;
41  
42      private List<ModelClass> classes = new ArrayList<>();
43  
44      private List<ModelDefault> defaults = new ArrayList<>();
45  
46      private List<ModelInterface> interfaces = new ArrayList<>();
47  
48      private transient Map<String, List<ModelClass>> classMap = new HashMap<>();
49  
50      private transient Map<String, ModelDefault> defaultMap = new HashMap<>();
51  
52      private transient Map<String, List<ModelInterface>> interfaceMap = new HashMap<>();
53  
54      private VersionDefinition versionDefinition;
55  
56      public Model() {
57          super(true);
58      }
59  
60      public String getId() {
61          return id;
62      }
63  
64      public void setId(String id) {
65          this.id = id;
66      }
67  
68      public VersionDefinition getVersionDefinition() {
69          return versionDefinition;
70      }
71  
72      public void setVersionDefinition(VersionDefinition versionDefinition) {
73          this.versionDefinition = versionDefinition;
74      }
75  
76      public ModelMetadata getMetadata(String key) {
77          return getMetadata(ModelMetadata.class, key);
78      }
79  
80      public String getRoot(Version version) {
81          List<ModelClass> classes = getClasses(version);
82  
83          String className = null;
84  
85          for (ModelClass currentClass : classes) {
86              ModelClassMetadata metadata = null;
87  
88              try {
89                  metadata = (ModelClassMetadata) currentClass.getMetadata(ModelClassMetadata.ID);
90              } catch (Exception e) {
91              }
92  
93              if (metadata != null && metadata.isRootElement()) {
94                  if (className == null) {
95                      className = currentClass.getName();
96                  } else {
97                      throw new ModelloRuntimeException(
98                              "There are more than one class as root element for this version " + version + ".");
99                  }
100             }
101         }
102 
103         if (className == null) {
104             throw new ModelloRuntimeException("There aren't root element for version " + version + ".");
105         }
106 
107         return className;
108     }
109 
110     /**
111      * @deprecated This shouldn't be used, anything querying the model should read the
112      *             package of the class. Use getDefaultPackageName(..).
113      * @param withVersion return the version
114      * @param version the version
115      * @return the package name
116      *
117      */
118     @Deprecated
119     public String getPackageName(boolean withVersion, Version version) {
120         return getDefaultPackageName(withVersion, version);
121     }
122 
123     public List<ModelClass> getAllClasses() {
124         return classes;
125     }
126 
127     public List<ModelClass> getClasses(Version version) {
128         List<ModelClass> classList = new ArrayList<>();
129 
130         for (ModelClass currentClass : classes) {
131             if (version.inside(currentClass.getVersionRange())) {
132                 classList.add(currentClass);
133             }
134         }
135 
136         return classList;
137     }
138 
139     public ModelClass getClass(String type, Version version, boolean optionnal) {
140         return getClass(type, new VersionRange(version), optionnal);
141     }
142 
143     public ModelClass getClass(String type, Version version) {
144         return getClass(type, new VersionRange(version), false);
145     }
146 
147     public ModelClass getClass(String type, VersionRange versionRange, boolean optionnal) {
148         ModelClass value = getModelClass(type, versionRange);
149 
150         if (value != null) {
151             return value;
152         }
153         if (optionnal) {
154             return null;
155         }
156         throw new ModelloRuntimeException(
157                 "There is no class '" + type + "' in the version range '" + versionRange.toString() + "'.");
158     }
159 
160     public ModelClass getClass(String type, VersionRange versionRange) {
161         ModelClass value = getModelClass(type, versionRange);
162 
163         if (value != null) {
164             return value;
165         }
166 
167         throw new ModelloRuntimeException(
168                 "There is no class '" + type + "' in the version range '" + versionRange.toString() + "'.");
169     }
170 
171     public boolean hasClass(String type, Version version) {
172         ModelClass value = getModelClass(type, new VersionRange(version));
173 
174         return value != null;
175     }
176 
177     private ModelClass getModelClass(String type, VersionRange versionRange) {
178         List<ModelClass> classList = classMap.get(type);
179 
180         ModelClass value = null;
181         if (classList != null) {
182             for (ModelClass modelClass : classList) {
183                 if (versionRange.getFromVersion().inside(modelClass.getVersionRange())
184                         && versionRange.getToVersion().inside(modelClass.getVersionRange())) {
185                     value = modelClass;
186                 }
187             }
188         }
189         return value;
190     }
191 
192     public void addClass(ModelClass modelClass) {
193         if (classMap.containsKey(modelClass.getName())) {
194             List<ModelClass> classList = classMap.get(modelClass.getName());
195 
196             for (ModelClass currentClass : classList) {
197                 if (VersionUtil.isInConflict(modelClass.getVersionRange(), currentClass.getVersionRange())) {
198                     throw new ModelloRuntimeException("Duplicate class: " + modelClass.getName() + ".");
199                 }
200             }
201         } else {
202             List<ModelClass> classList = new ArrayList<>();
203 
204             classMap.put(modelClass.getName(), classList);
205         }
206 
207         getAllClasses().add(modelClass);
208 
209         classMap.get(modelClass.getName()).add(modelClass);
210     }
211 
212     // ----------------------------------------------------------------------
213     // Defaults
214     // ----------------------------------------------------------------------
215 
216     public List<ModelDefault> getDefaults() {
217         return defaults;
218     }
219 
220     public ModelDefault getDefault(String key) {
221         ModelDefault modelDefault = (ModelDefault) defaultMap.get(key);
222 
223         if (modelDefault == null) {
224             try {
225                 modelDefault = ModelDefault.getDefault(key);
226             } catch (ModelValidationException mve) {
227                 throw new ModelloRuntimeException(mve.getMessage(), mve);
228             }
229         }
230 
231         return modelDefault;
232     }
233 
234     public void addDefault(ModelDefault modelDefault) {
235         if (defaultMap.containsKey(modelDefault.getKey())) {
236             throw new ModelloRuntimeException("Duplicate default: " + modelDefault.getKey() + ".");
237         }
238 
239         getDefaults().add(modelDefault);
240 
241         defaultMap.put(modelDefault.getKey(), modelDefault);
242     }
243 
244     public String getDefaultPackageName(boolean withVersion, Version version) {
245         String packageName = getDefault(ModelDefault.PACKAGE).getValue();
246 
247         if (withVersion) {
248             packageName += "." + version.toString("v", "_");
249         }
250 
251         return packageName;
252     }
253 
254     // ----------------------------------------------------------------------
255     //
256     // ----------------------------------------------------------------------
257 
258     public List<ModelInterface> getAllInterfaces() {
259         return interfaces;
260     }
261 
262     public List<ModelInterface> getInterfaces(Version version) {
263         List<ModelInterface> interfaceList = new ArrayList<>();
264 
265         for (ModelInterface currentInterface : interfaces) {
266             if (version.inside(currentInterface.getVersionRange())) {
267                 interfaceList.add(currentInterface);
268             }
269         }
270 
271         return interfaceList;
272     }
273 
274     public ModelInterface getInterface(String type, Version version) {
275         return getInterface(type, new VersionRange(version));
276     }
277 
278     public ModelInterface getInterface(String type, VersionRange versionRange) {
279         ModelInterface value = getModelInterface(type, versionRange);
280 
281         if (value != null) {
282             return value;
283         }
284 
285         throw new ModelloRuntimeException(
286                 "There is no interface '" + type + "' in the version range '" + versionRange.toString() + "'.");
287     }
288 
289     private ModelInterface getModelInterface(String type, VersionRange versionRange) {
290         List<ModelInterface> interfaceList = interfaceMap.get(type);
291 
292         if (interfaceList != null) {
293             for (ModelInterface modelInterface : interfaceList) {
294                 if (versionRange.getFromVersion().inside(modelInterface.getVersionRange())
295                         && versionRange.getToVersion().inside(modelInterface.getVersionRange())) {
296                     return modelInterface;
297                 }
298             }
299         }
300 
301         return null;
302     }
303 
304     public void addInterface(ModelInterface modelInterface) {
305         if (interfaceMap.containsKey(modelInterface.getName())) {
306             List<ModelInterface> interfaceList = interfaceMap.get(modelInterface.getName());
307 
308             for (ModelInterface currentInterface : interfaceList) {
309                 if (VersionUtil.isInConflict(modelInterface.getVersionRange(), currentInterface.getVersionRange())) {
310                     throw new ModelloRuntimeException("Duplicate interface: " + modelInterface.getName() + ".");
311                 }
312             }
313         } else {
314             List<ModelInterface> interfaceList = new ArrayList<>();
315 
316             interfaceMap.put(modelInterface.getName(), interfaceList);
317         }
318 
319         getAllInterfaces().add(modelInterface);
320 
321         interfaceMap.get(modelInterface.getName()).add(modelInterface);
322     }
323 
324     public ModelType getType(String type, Version version) {
325         return getType(type, new VersionRange(version));
326     }
327 
328     public ModelType getType(String type, VersionRange versionRange) {
329         ModelType value = getModelClass(type, versionRange);
330 
331         if (value != null) {
332             return value;
333         }
334 
335         value = getModelInterface(type, versionRange);
336 
337         if (value != null) {
338             return value;
339         }
340 
341         throw new ModelloRuntimeException("There is no class or interface '" + type + "' in the version range '"
342                 + versionRange.toString() + "'.");
343     }
344 
345     public void initialize() {
346         for (ModelClass modelClass : classes) {
347             modelClass.initialize(this);
348         }
349 
350         for (ModelInterface modelInterface : interfaces) {
351             modelInterface.initialize(this);
352         }
353     }
354 
355     public void validateElement() {}
356 
357     public ModelClass getLocationTracker(Version version) {
358         List<ModelClass> modelClasses = getClasses(version);
359 
360         ModelClass locationTracker = null;
361 
362         for (ModelClass modelClass : modelClasses) {
363             ModelClassMetadata metadata = (ModelClassMetadata) modelClass.getMetadata(ModelClassMetadata.ID);
364 
365             if (metadata != null && StringUtils.isNotEmpty(metadata.getLocationTracker())) {
366                 if (locationTracker == null) {
367                     locationTracker = modelClass;
368                 } else {
369                     throw new ModelloRuntimeException(
370                             "There are multiple location tracker classes (" + locationTracker.getName() + " vs. "
371                                     + modelClass.getName() + ") for this version " + version + ".");
372                 }
373             }
374         }
375 
376         return locationTracker;
377     }
378 
379     public ModelClass getSourceTracker(Version version) {
380         List<ModelClass> modelClasses = getClasses(version);
381 
382         ModelClass sourceTracker = null;
383 
384         for (ModelClass modelClass : modelClasses) {
385             ModelClassMetadata metadata = (ModelClassMetadata) modelClass.getMetadata(ModelClassMetadata.ID);
386 
387             if (metadata != null && StringUtils.isNotEmpty(metadata.getSourceTracker())) {
388                 if (sourceTracker == null) {
389                     sourceTracker = modelClass;
390                 } else {
391                     throw new ModelloRuntimeException(
392                             "There are multiple source tracker classes (" + sourceTracker.getName() + " vs. "
393                                     + modelClass.getName() + ") for this version " + version + ".");
394                 }
395             }
396         }
397 
398         return sourceTracker;
399     }
400 }