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 org.codehaus.modello.ModelloRuntimeException;
26  import org.codehaus.modello.metadata.ModelMetadata;
27  import org.codehaus.modello.plugin.model.ModelClassMetadata;
28  import org.codehaus.plexus.util.StringUtils;
29  
30  import java.util.ArrayList;
31  import java.util.HashMap;
32  import java.util.List;
33  import java.util.Map;
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
40      extends BaseElement
41  {
42      private String id;
43  
44      private List<ModelClass> classes = new ArrayList<ModelClass>();
45  
46      private List<ModelDefault> defaults = new ArrayList<ModelDefault>();
47  
48      private List<ModelInterface> interfaces = new ArrayList<ModelInterface>();
49  
50      private transient Map<String, List<ModelClass>> classMap = new HashMap<String, List<ModelClass>>();
51  
52      private transient Map<String, ModelDefault> defaultMap = new HashMap<String, ModelDefault>();
53  
54      private transient Map<String, List<ModelInterface>> interfaceMap = new HashMap<String, List<ModelInterface>>();
55  
56      private VersionDefinition versionDefinition;
57  
58      public Model()
59      {
60          super( true );
61      }
62  
63      public String getId()
64      {
65          return id;
66      }
67  
68      public void setId( String id )
69      {
70          this.id = id;
71      }
72  
73      public VersionDefinition getVersionDefinition()
74      {
75          return versionDefinition;
76      }
77  
78      public void setVersionDefinition( VersionDefinition versionDefinition )
79      {
80          this.versionDefinition = versionDefinition;
81      }
82  
83      public ModelMetadata getMetadata( String key )
84      {
85          return getMetadata( ModelMetadata.class, key );
86      }
87  
88      public String getRoot( Version version )
89      {
90          List<ModelClass> classes = getClasses( version );
91  
92          String className = null;
93  
94          for ( ModelClass currentClass : classes )
95          {
96              ModelClassMetadata metadata = null;
97  
98              try
99              {
100                 metadata = (ModelClassMetadata) currentClass.getMetadata( ModelClassMetadata.ID );
101             }
102             catch ( Exception e )
103             {
104             }
105 
106             if ( metadata != null && metadata.isRootElement() )
107             {
108                 if ( className == null )
109                 {
110                     className = currentClass.getName();
111                 }
112                 else
113                 {
114                     throw new ModelloRuntimeException(
115                         "There are more than one class as root element for this version " + version + "." );
116                 }
117             }
118         }
119 
120         if ( className == null )
121         {
122             throw new ModelloRuntimeException( "There aren't root element for version " + version + "." );
123         }
124 
125         return className;
126     }
127 
128     /**
129      * @deprecated This shouldn't be used, anything querying the model should read the
130      *             package of the class. Use getDefaultPackageName(..).
131      */
132     public String getPackageName( boolean withVersion, Version version )
133     {
134         return getDefaultPackageName( withVersion, version );
135     }
136 
137     public List<ModelClass> getAllClasses()
138     {
139         return classes;
140     }
141 
142     public List<ModelClass> getClasses( Version version )
143     {
144         List<ModelClass> classList = new ArrayList<ModelClass>();
145 
146         for ( ModelClass currentClass : classes )
147         {
148             if ( version.inside( currentClass.getVersionRange() ) )
149             {
150                 classList.add( currentClass );
151             }
152         }
153 
154         return classList;
155     }
156 
157     public ModelClass getClass( String type, Version version, boolean optionnal )
158     {
159         return getClass( type, new VersionRange( version ), optionnal );
160     }
161 
162     public ModelClass getClass( String type, Version version )
163     {
164         return getClass( type, new VersionRange( version ), false );
165     }
166 
167     public ModelClass getClass( String type, VersionRange versionRange, boolean optionnal )
168     {
169         ModelClass value = getModelClass( type, versionRange );
170 
171         if ( value != null )
172         {
173             return value;
174         }
175         if ( optionnal )
176         {
177             return null;
178         }
179         throw new ModelloRuntimeException(
180             "There is no class '" + type + "' in the version range '" + versionRange.toString() + "'." );
181     }
182 
183     public ModelClass getClass( String type, VersionRange versionRange )
184     {
185         ModelClass value = getModelClass( type, versionRange );
186 
187         if ( value != null )
188         {
189             return value;
190         }
191 
192         throw new ModelloRuntimeException(
193             "There is no class '" + type + "' in the version range '" + versionRange.toString() + "'." );
194     }
195 
196     public boolean hasClass( String type, Version version )
197     {
198         ModelClass value = getModelClass( type, new VersionRange( version ) );
199 
200         return value != null;
201     }
202 
203     private ModelClass getModelClass( String type, VersionRange versionRange )
204     {
205         List<ModelClass> classList = classMap.get( type );
206 
207         ModelClass value = null;
208         if ( classList != null )
209         {
210             for ( ModelClass modelClass : classList )
211             {
212                 if ( versionRange.getFromVersion().inside( modelClass.getVersionRange() )
213                     && versionRange.getToVersion().inside( modelClass.getVersionRange() ) )
214                 {
215                     value = modelClass;
216                 }
217             }
218         }
219         return value;
220     }
221 
222     public void addClass( ModelClass modelClass )
223     {
224         if ( classMap.containsKey( modelClass.getName() ) )
225         {
226             List<ModelClass> classList = classMap.get( modelClass.getName() );
227 
228             for ( ModelClass currentClass : classList )
229             {
230                 if ( VersionUtil.isInConflict( modelClass.getVersionRange(), currentClass.getVersionRange() ) )
231                 {
232                     throw new ModelloRuntimeException( "Duplicate class: " + modelClass.getName() + "." );
233                 }
234             }
235         }
236         else
237         {
238             List<ModelClass> classList = new ArrayList<ModelClass>();
239 
240             classMap.put( modelClass.getName(), classList );
241         }
242 
243         getAllClasses().add( modelClass );
244 
245         classMap.get( modelClass.getName() ).add( modelClass );
246     }
247 
248     // ----------------------------------------------------------------------
249     // Defaults
250     // ----------------------------------------------------------------------
251 
252     public List<ModelDefault> getDefaults()
253     {
254         return defaults;
255     }
256 
257     public ModelDefault getDefault( String key )
258     {
259         ModelDefault modelDefault = (ModelDefault) defaultMap.get( key );
260 
261         if ( modelDefault == null )
262         {
263             try
264             {
265                 modelDefault = ModelDefault.getDefault( key );
266             }
267             catch ( ModelValidationException mve )
268             {
269                 throw new ModelloRuntimeException( mve.getMessage(), mve );
270             }
271         }
272 
273         return modelDefault;
274     }
275 
276     public void addDefault( ModelDefault modelDefault )
277     {
278         if ( defaultMap.containsKey( modelDefault.getKey() ) )
279         {
280             throw new ModelloRuntimeException( "Duplicate default: " + modelDefault.getKey() + "." );
281         }
282 
283         getDefaults().add( modelDefault );
284 
285         defaultMap.put( modelDefault.getKey(), modelDefault );
286     }
287 
288     public String getDefaultPackageName( boolean withVersion, Version version )
289     {
290         String packageName = getDefault( ModelDefault.PACKAGE ).getValue();
291 
292         if ( withVersion )
293         {
294             packageName += "." + version.toString( "v", "_" );
295         }
296 
297         return packageName;
298     }
299 
300     // ----------------------------------------------------------------------
301     //
302     // ----------------------------------------------------------------------
303 
304     public List<ModelInterface> getAllInterfaces()
305     {
306         return interfaces;
307     }
308 
309     public List<ModelInterface> getInterfaces( Version version )
310     {
311         List<ModelInterface> interfaceList = new ArrayList<ModelInterface>();
312 
313         for ( ModelInterface currentInterface : interfaces )
314         {
315             if ( version.inside( currentInterface.getVersionRange() ) )
316             {
317                 interfaceList.add( currentInterface );
318             }
319         }
320 
321         return interfaceList;
322     }
323 
324     public ModelInterface getInterface( String type, Version version )
325     {
326         return getInterface( type, new VersionRange( version ) );
327     }
328 
329     public ModelInterface getInterface( String type, VersionRange versionRange )
330     {
331         ModelInterface value = getModelInterface( type, versionRange );
332 
333         if ( value != null )
334         {
335             return value;
336         }
337 
338         throw new ModelloRuntimeException(
339             "There is no interface '" + type + "' in the version range '" + versionRange.toString() + "'." );
340     }
341 
342     private ModelInterface getModelInterface( String type, VersionRange versionRange )
343     {
344         List<ModelInterface> interfaceList = interfaceMap.get( type );
345 
346         if ( interfaceList != null )
347         {
348             for ( ModelInterface modelInterface : interfaceList )
349             {
350                 if ( versionRange.getFromVersion().inside( modelInterface.getVersionRange() )
351                     && versionRange.getToVersion().inside( modelInterface.getVersionRange() ) )
352                 {
353                     return modelInterface;
354                 }
355             }
356         }
357 
358         return null;
359     }
360 
361     public void addInterface( ModelInterface modelInterface )
362     {
363         if ( interfaceMap.containsKey( modelInterface.getName() ) )
364         {
365             List<ModelInterface> interfaceList = interfaceMap.get( modelInterface.getName() );
366 
367             for ( ModelInterface currentInterface : interfaceList )
368             {
369                 if ( VersionUtil.isInConflict( modelInterface.getVersionRange(), currentInterface.getVersionRange() ) )
370                 {
371                     throw new ModelloRuntimeException( "Duplicate interface: " + modelInterface.getName() + "." );
372                 }
373             }
374         }
375         else
376         {
377             List<ModelInterface> interfaceList = new ArrayList<ModelInterface>();
378 
379             interfaceMap.put( modelInterface.getName(), interfaceList );
380         }
381 
382         getAllInterfaces().add( modelInterface );
383 
384         interfaceMap.get( modelInterface.getName() ).add( modelInterface );
385     }
386 
387     public ModelType getType( String type, Version version )
388     {
389         return getType( type, new VersionRange( version ) );
390     }
391 
392     public ModelType getType( String type, VersionRange versionRange )
393     {
394         ModelType value = getModelClass( type, versionRange );
395 
396         if ( value != null )
397         {
398             return value;
399         }
400 
401         value = getModelInterface( type, versionRange );
402 
403         if ( value != null )
404         {
405             return value;
406         }
407 
408         throw new ModelloRuntimeException(
409             "There is no class or interface '" + type + "' in the version range '" + versionRange.toString() + "'." );
410     }
411 
412     public void initialize()
413     {
414         for ( ModelClass modelClass : classes )
415         {
416             modelClass.initialize( this );
417         }
418 
419         for ( ModelInterface modelInterface : interfaces )
420         {
421             modelInterface.initialize( this );
422         }
423     }
424 
425     public void validateElement()
426     {
427     }
428 
429     public ModelClass getLocationTracker( Version version )
430     {
431         List<ModelClass> modelClasses = getClasses( version );
432 
433         ModelClass locationTracker = null;
434 
435         for ( ModelClass modelClass : modelClasses )
436         {
437             ModelClassMetadata metadata = (ModelClassMetadata) modelClass.getMetadata( ModelClassMetadata.ID );
438 
439             if ( metadata != null && StringUtils.isNotEmpty( metadata.getLocationTracker() ) )
440             {
441                 if ( locationTracker == null )
442                 {
443                     locationTracker = modelClass;
444                 }
445                 else
446                 {
447                     throw new ModelloRuntimeException(
448                         "There are multiple location tracker classes (" + locationTracker.getName() + " vs. "
449                             + modelClass.getName() + ") for this version " + version + "." );
450                 }
451             }
452         }
453 
454         return locationTracker;
455     }
456 
457     public ModelClass getSourceTracker( Version version )
458     {
459         List<ModelClass> modelClasses = getClasses( version );
460 
461         ModelClass sourceTracker = null;
462 
463         for ( ModelClass modelClass : modelClasses )
464         {
465             ModelClassMetadata metadata = (ModelClassMetadata) modelClass.getMetadata( ModelClassMetadata.ID );
466 
467             if ( metadata != null && StringUtils.isNotEmpty( metadata.getSourceTracker() ) )
468             {
469                 if ( sourceTracker == null )
470                 {
471                     sourceTracker = modelClass;
472                 }
473                 else
474                 {
475                     throw new ModelloRuntimeException(
476                         "There are multiple source tracker classes (" + sourceTracker.getName() + " vs. "
477                             + modelClass.getName() + ") for this version " + version + "." );
478                 }
479             }
480         }
481 
482         return sourceTracker;
483     }
484 
485 }