View Javadoc

1   //
2   // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-2 
3   // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
4   // Any modifications to this file will be lost upon recompilation of the source schema. 
5   // Generated on: 2012.03.14 at 10:22:27 AM CET 
6   //
7   
8   
9   package org.jomc.model;
10  
11  import java.util.ArrayList;
12  import java.util.Iterator;
13  import java.util.List;
14  import javax.annotation.Generated;
15  import javax.xml.bind.annotation.XmlAccessType;
16  import javax.xml.bind.annotation.XmlAccessorType;
17  import javax.xml.bind.annotation.XmlElement;
18  import javax.xml.bind.annotation.XmlType;
19  
20  
21  /**
22   * List of modules.
23   * 
24   * <p>Java class for Modules complex type.
25   * 
26   * <p>The following schema fragment specifies the expected content contained within this class.
27   * 
28   * <pre>
29   * &lt;complexType name="Modules">
30   *   &lt;complexContent>
31   *     &lt;extension base="{http://jomc.org/model}ModelObject">
32   *       &lt;sequence>
33   *         &lt;element ref="{http://jomc.org/model}module" maxOccurs="unbounded" minOccurs="0"/>
34   *       &lt;/sequence>
35   *     &lt;/extension>
36   *   &lt;/complexContent>
37   * &lt;/complexType>
38   * </pre>
39   * 
40   * 
41   */
42  @XmlAccessorType(XmlAccessType.FIELD)
43  @XmlType(name = "Modules", namespace = "http://jomc.org/model", propOrder = {
44      "module"
45  })
46  @Generated(value = "com.sun.tools.xjc.Driver", date = "2012-03-14T10:22:27+01:00", comments = "JAXB RI vhudson-jaxb-ri-2.1-2")
47  public class Modules
48      extends ModelObject
49      implements Cloneable
50  {
51  
52      @XmlElement(namespace = "http://jomc.org/model")
53      @Generated(value = "com.sun.tools.xjc.Driver", date = "2012-03-14T10:22:27+01:00", comments = "JAXB RI vhudson-jaxb-ri-2.1-2")
54      protected List<Module> module;
55  
56      /**
57       * Creates a new {@code Modules} instance.
58       * 
59       */
60      public Modules() {
61          // CC-XJC Version 2.0 Build 2011-09-16T18:27:24+0000
62          super();
63      }
64  
65      /**
66       * Creates a new {@code Modules} instance by deeply copying a given {@code Modules} instance.
67       * 
68       * 
69       * @param o
70       *     The instance to copy.
71       * @throws NullPointerException
72       *     if {@code o} is {@code null}.
73       */
74      public Modules(final Modules o) {
75          // CC-XJC Version 2.0 Build 2011-09-16T18:27:24+0000
76          super(o);
77          if (o == null) {
78              throw new NullPointerException("Cannot create a copy of 'Modules' from 'null'.");
79          }
80          // 'Module' collection.
81          if (o.module!= null) {
82              copyModule(o.getModule(), this.getModule());
83          }
84      }
85  
86      /**
87       * Gets the value of the module property.
88       * 
89       * <p>
90       * This accessor method returns a reference to the live list,
91       * not a snapshot. Therefore any modification you make to the
92       * returned list will be present inside the JAXB object.
93       * This is why there is not a <CODE>set</CODE> method for the module property.
94       * 
95       * <p>
96       * For example, to add a new item, do as follows:
97       * <pre>
98       *    getModule().add(newItem);
99       * </pre>
100      * 
101      * 
102      * <p>
103      * Objects of the following type(s) are allowed in the list
104      * {@link Module }
105      * 
106      * 
107      */
108     @Generated(value = "com.sun.tools.xjc.Driver", date = "2012-03-14T10:22:27+01:00", comments = "JAXB RI vhudson-jaxb-ri-2.1-2")
109     public List<Module> getModule() {
110         if (module == null) {
111             module = new ArrayList<Module>();
112         }
113         return this.module;
114     }
115 
116     /**
117      * Copies all values of property {@code Module} deeply.
118      * 
119      * @param source
120      *     The source to copy from.
121      * @param target
122      *     The target to copy {@code source} to.
123      * @throws NullPointerException
124      *     if {@code target} is {@code null}.
125      */
126     @SuppressWarnings("unchecked")
127     @Generated(value = "com.sun.tools.xjc.Driver", date = "2012-03-14T10:22:27+01:00", comments = "JAXB RI vhudson-jaxb-ri-2.1-2")
128     private static void copyModule(final List<Module> source, final List<Module> target) {
129         // CC-XJC Version 2.0 Build 2011-09-16T18:27:24+0000
130         if ((source!= null)&&(!source.isEmpty())) {
131             for (final Iterator<?> it = source.iterator(); it.hasNext(); ) {
132                 final Object next = it.next();
133                 if (next instanceof Module) {
134                     // CClassInfo: org.jomc.model.Module
135                     target.add(((Module) next).clone());
136                     continue;
137                 }
138                 // Please report this at https://apps.sourceforge.net/mantisbt/ccxjc/
139                 throw new AssertionError((("Unexpected instance '"+ next)+"' for property 'Module' of class 'org.jomc.model.Modules'."));
140             }
141         }
142     }
143 
144     /**
145      * Creates and returns a deep copy of this object.
146      * 
147      * 
148      * @return
149      *     A deep copy of this object.
150      */
151     @Override
152     @Generated(value = "com.sun.tools.xjc.Driver", date = "2012-03-14T10:22:27+01:00", comments = "JAXB RI vhudson-jaxb-ri-2.1-2")
153     public Modules clone() {
154         {
155             // CC-XJC Version 2.0 Build 2011-09-16T18:27:24+0000
156             final Modules clone = ((Modules) super.clone());
157             // 'Module' collection.
158             if (this.module!= null) {
159                 clone.module = null;
160                 copyModule(this.getModule(), clone.getModule());
161             }
162             return clone;
163         }
164     }
165     
166     /**
167      * Constant for the default name of the classpath module.
168      * @see #getDefaultClasspathModuleName()
169      */
170     @javax.xml.bind.annotation.XmlTransient
171     private static final String DEFAULT_CLASSPATH_MODULE_NAME = "Java Classpath";
172 
173     /** Default classpath module name. */
174     @javax.xml.bind.annotation.XmlTransient
175     private static volatile String defaultClasspathModuleName;
176 
177     /** Empty {@code Class} array. */
178     @javax.xml.bind.annotation.XmlTransient
179     private static final Class<?>[] NO_CLASSES =
180     {
181     };
182 
183     /**
184      * Comparator comparing dependency names lexicographically.
185      * @since 1.2
186      */
187     @javax.xml.bind.annotation.XmlTransient
188     private static final java.util.Comparator<Dependency> DEPENDENCY_NAME_COMPARATOR =
189         new java.util.Comparator<Dependency>()
190         {
191 
192             public int compare( final Dependency o1, final Dependency o2 )
193             {
194                 return o1.getName().compareTo( o2.getName() );
195             }
196 
197         };
198 
199     /**
200      * Comparator comparing message names lexicographically.
201      * @since 1.2
202      */
203     @javax.xml.bind.annotation.XmlTransient
204     private static final java.util.Comparator<Message> MESSAGE_NAME_COMPARATOR =
205         new java.util.Comparator<Message>()
206         {
207 
208             public int compare( final Message o1, final Message o2 )
209             {
210                 return o1.getName().compareTo( o2.getName() );
211             }
212 
213         };
214 
215     /**
216      * Comparator comparing property names lexicographically.
217      * @since 1.2
218      */
219     @javax.xml.bind.annotation.XmlTransient
220     private static final java.util.Comparator<Property> PROPERTY_NAME_COMPARATOR =
221         new java.util.Comparator<Property>()
222         {
223 
224             public int compare( final Property o1, final Property o2 )
225             {
226                 return o1.getName().compareTo( o2.getName() );
227             }
228 
229         };
230 
231     /**
232      * Comparator comparing specification identifiers lexicographically.
233      * @since 1.2
234      */
235     @javax.xml.bind.annotation.XmlTransient
236     private static final java.util.Comparator<Specification> SPECIFICATION_IDENTIFIER_COMPARATOR =
237         new java.util.Comparator<Specification>()
238         {
239 
240             public int compare( final Specification o1, final Specification o2 )
241             {
242                 return o1.getIdentifier().compareTo( o2.getIdentifier() );
243             }
244 
245         };
246 
247     /**
248      * Comparator comparing specification reference identifiers lexicographically.
249      * @since 1.2
250      */
251     @javax.xml.bind.annotation.XmlTransient
252     private static final java.util.Comparator<SpecificationReference> SPECIFICATION_REFERENCE_IDENTIFIER_COMPARATOR =
253         new java.util.Comparator<SpecificationReference>()
254         {
255 
256             public int compare( final SpecificationReference o1, final SpecificationReference o2 )
257             {
258                 return o1.getIdentifier().compareTo( o2.getIdentifier() );
259             }
260 
261         };
262 
263     /** Maps objects to {@code Instance}s. */
264     @javax.xml.bind.annotation.XmlTransient private java.util.Map<Object, Instance> objects =
265         new org.jomc.util.WeakIdentityHashMap<Object, Instance>();
266 
267     /**
268      * Creates a new {@code Modules} instance taking a map backing the instance.
269      *
270      * @param objects The map backing the instance.
271      */
272     public Modules( final java.util.Map<Object, Instance> objects )
273     {
274         super();
275 
276         if ( objects == null )
277         {
278             throw new NullPointerException( "objects" );
279         }
280 
281         this.objects = objects;
282     }
283 
284     /**
285      * Creates a new {@code Modules} instance by deeply copying a given {@code Modules} instance taking a map backing
286      * the instance.
287      *
288      * @param o The instance to copy.
289      * @param objects The map backing the instance.
290      *
291      * @throws NullPointerException if {@code o} or {@code objects} is {@code null}.
292      */
293     public Modules( final Modules o, final java.util.Map<Object, Instance> objects )
294     {
295         super( o );
296         if ( o == null )
297         {
298             throw new NullPointerException( "Cannot create a copy of 'Modules' from 'null'." );
299         }
300         if ( objects == null )
301         {
302             throw new NullPointerException( "objects" );
303         }
304 
305         copyModule( o.getModule(), getModule() );
306         this.objects = objects;
307     }
308 
309     /**
310      * Gets the default classpath module name.
311      * <p>The default classpath module name is controlled by system property
312      * {@code org.jomc.model.Modules.defaultClasspathModuleName} holding the default classpath module name. If that
313      * property is not set, the {@code Java Classpath} default is returned.</p>
314      *
315      * @return The default classpath module name.
316      *
317      * @see #getClasspathModule(java.lang.String, java.lang.ClassLoader)
318      */
319     public static String getDefaultClasspathModuleName()
320     {
321         if ( defaultClasspathModuleName == null )
322         {
323             defaultClasspathModuleName = System.getProperty( "org.jomc.model.Modules.defaultClasspathModuleName",
324                                                              DEFAULT_CLASSPATH_MODULE_NAME );
325 
326         }
327 
328         return defaultClasspathModuleName;
329     }
330 
331     /**
332      * Sets the default classpath module name.
333      *
334      * @param value The new default classpath module name or {@code null},
335      */
336     public static void setDefaultClasspathModuleName( final String value )
337     {
338         defaultClasspathModuleName = value;
339     }
340 
341     /**
342      * Gets a module holding model objects resolved by inspecting a given class loader.
343      * <p>This method searches this list of modules for unresolved references and tries to resolve each unresolved
344      * reference by inspecting the given class loader.</p>
345      *
346      * @param moduleName The name of the module to return.
347      * @param classLoader The class loader to use for resolving entities or {@code null}, to resolve entities using the
348      * bootstrap class loader.
349      *
350      * @return A module holding model objects resolved by inspecting the given class loader or {@code null}, if nothing
351      * is resolved.
352      *
353      * @throws NullPointerException if {@code moduleName} is {@code null}.
354      *
355      * @see #getDefaultClasspathModuleName()
356      * @see #getModule()
357      */
358     public Module getClasspathModule( final String moduleName, final ClassLoader classLoader )
359     {
360         if ( moduleName == null )
361         {
362             throw new NullPointerException( "moduleName" );
363         }
364 
365         final Module classpathModule = new Module();
366         classpathModule.setVersion( System.getProperty( "java.specification.version" ) );
367         classpathModule.setName( moduleName );
368 
369         this.resolveClasspath( classpathModule, classLoader );
370 
371         final boolean resolved = ( classpathModule.getSpecifications() != null
372                                    && !classpathModule.getSpecifications().getSpecification().isEmpty() )
373                                  || ( classpathModule.getImplementations() != null
374                                       && !classpathModule.getImplementations().getImplementation().isEmpty() );
375 
376         return resolved ? classpathModule : null;
377     }
378 
379     /**
380      * Gets a module for a given name from the list of modules.
381      *
382      * @param name The name of the module to return.
383      *
384      * @return The first matching module or {@code null}, if no such module is found.
385      *
386      * @throws NullPointerException if {@code name} is {@code null}.
387      *
388      * @see #getModule()
389      * @see Module#getName()
390      */
391     public Module getModule( final String name )
392     {
393         if ( name == null )
394         {
395             throw new NullPointerException( "name" );
396         }
397 
398         for ( int i = 0, s0 = this.getModule().size(); i < s0; i++ )
399         {
400             final Module m = this.getModule().get( i );
401 
402             if ( m.getName().equals( name ) )
403             {
404                 return m;
405             }
406         }
407 
408         return null;
409     }
410 
411     /**
412      * Gets all specifications of the list of modules.
413      *
414      * @return All specifications or {@code null}, if no specifications are found.
415      *
416      * @see #getModule()
417      */
418     public Specifications getSpecifications()
419     {
420         final Specifications specifications = new Specifications();
421 
422         for ( int i = 0, s0 = this.getModule().size(); i < s0; i++ )
423         {
424             final Module m = this.getModule().get( i );
425 
426             if ( m.getSpecifications() != null )
427             {
428                 specifications.getSpecification().addAll( m.getSpecifications().getSpecification() );
429             }
430         }
431 
432         return specifications.getSpecification().isEmpty() ? null : specifications;
433     }
434 
435     /**
436      * Gets all implementations of the list of modules.
437      *
438      * @return All implementations or {@code null}, if no implementations are found.
439      *
440      * @see #getModule()
441      */
442     public Implementations getImplementations()
443     {
444         final Implementations implementations = new Implementations();
445 
446         for ( int i = 0, s0 = this.getModule().size(); i < s0; i++ )
447         {
448             final Module m = this.getModule().get( i );
449 
450             if ( m.getImplementations() != null )
451             {
452                 implementations.getImplementation().addAll( m.getImplementations().getImplementation() );
453             }
454         }
455 
456         return implementations.getImplementation().isEmpty() ? null : implementations;
457     }
458 
459     /**
460      * Gets the module declaring a given specification from the list of modules.
461      *
462      * @param specification The identifier of the specification whose declaring module to return.
463      *
464      * @return The first matching module or {@code null}, if no such module is found.
465      *
466      * @throws NullPointerException if {@code specification} is {@code null}.
467      *
468      * @see #getModule()
469      * @see Module#getSpecifications()
470      * @see Specifications#getSpecification( java.lang.String )
471      */
472     public Module getModuleOfSpecification( final String specification )
473     {
474         if ( specification == null )
475         {
476             throw new NullPointerException( "specification" );
477         }
478 
479         for ( int i = 0, s0 = this.getModule().size(); i < s0; i++ )
480         {
481             final Module m = this.getModule().get( i );
482 
483             if ( m.getSpecifications() != null && m.getSpecifications().getSpecification( specification ) != null )
484             {
485                 return m;
486             }
487         }
488 
489         return null;
490     }
491 
492     /**
493      * Gets the module declaring a given implementation from the list of modules.
494      *
495      * @param implementation The identifier of the implementation whose declaring module to return.
496      *
497      * @return The first matching module or {@code null}, if no such module is found.
498      *
499      * @throws NullPointerException if {@code implementation} is {@code null}.
500      *
501      * @see #getModule()
502      * @see Module#getImplementations()
503      * @see Implementations#getImplementation( java.lang.String )
504      */
505     public Module getModuleOfImplementation( final String implementation )
506     {
507         if ( implementation == null )
508         {
509             throw new NullPointerException( "implementation" );
510         }
511 
512         for ( int i = 0, s0 = this.getModule().size(); i < s0; i++ )
513         {
514             final Module m = this.getModule().get( i );
515 
516             if ( m.getImplementations() != null && m.getImplementations().getImplementation( implementation ) != null )
517             {
518                 return m;
519             }
520         }
521 
522         return null;
523     }
524 
525     /**
526      * Gets a specification for a given identifier from the list of modules.
527      *
528      * @param specification The identifier of the specification to return.
529      *
530      * @return The first matching specification or {@code null}, if no such specification is found.
531      *
532      * @throws NullPointerException if {@code specification} is {@code null}.
533      *
534      * @see #getModule()
535      * @see Module#getSpecifications()
536      * @see Specifications#getSpecification( java.lang.String )
537      */
538     public Specification getSpecification( final String specification )
539     {
540         if ( specification == null )
541         {
542             throw new NullPointerException( "specification" );
543         }
544 
545         for ( int i = 0, s0 = this.getModule().size(); i < s0; i++ )
546         {
547             final Module m = this.getModule().get( i );
548 
549             if ( m.getSpecifications() != null )
550             {
551                 final Specification s = m.getSpecifications().getSpecification( specification );
552 
553                 if ( s != null )
554                 {
555                     return s;
556                 }
557             }
558         }
559 
560         return null;
561     }
562 
563     /**
564      * Gets a specification for a given class from the list of modules.
565      *
566      * @param specification The class of the specification to return.
567      *
568      * @return The first matching specification or {@code null}, if no such specification is found.
569      *
570      * @throws NullPointerException if {@code specification} is {@code null}.
571      *
572      * @see #getModule()
573      * @see Module#getSpecifications()
574      * @see Specifications#getSpecification( java.lang.Class )
575      */
576     public Specification getSpecification( final Class<?> specification )
577     {
578         if ( specification == null )
579         {
580             throw new NullPointerException( "specification" );
581         }
582 
583         for ( int i = 0, s0 = this.getModule().size(); i < s0; i++ )
584         {
585             final Module m = this.getModule().get( i );
586 
587             if ( m.getSpecifications() != null )
588             {
589                 final Specification s = m.getSpecifications().getSpecification( specification );
590 
591                 if ( s != null )
592                 {
593                     return s;
594                 }
595             }
596         }
597 
598         return null;
599     }
600 
601     /**
602      * Gets all specifications an implementation implements from the list of modules.
603      *
604      * @param implementation The identifier of the implementation to get all implemented specifications of.
605      *
606      * @return All specifications implemented by the first matching implementation or {@code null}, if no such
607      * implementation is found or if the first matching implementation does not implement any specification.
608      *
609      * @throws NullPointerException if {@code implementation} is {@code null}.
610      *
611      * @see #getModule()
612      * @see #getImplementation( java.lang.String )
613      * @see Implementation#getImplementations()
614      * @see Implementations#getReference()
615      * @see Implementation#getSpecifications()
616      */
617     public Specifications getSpecifications( final String implementation )
618     {
619         if ( implementation == null )
620         {
621             throw new NullPointerException( "implementation" );
622         }
623 
624         final Specifications specs = new Specifications();
625         final Implementation impl = this.getImplementation( implementation );
626         this.collectModelObjects( impl, null, null, null, specs, null, new java.util.HashSet<String>(), true );
627         this.collectClassDeclarationModelObjects( impl, null, null, null, specs, null );
628         java.util.Collections.sort( specs.getSpecification(), SPECIFICATION_IDENTIFIER_COMPARATOR );
629         java.util.Collections.sort( specs.getReference(), SPECIFICATION_REFERENCE_IDENTIFIER_COMPARATOR );
630         return specs.getSpecification().isEmpty() && specs.getReference().isEmpty() ? null : specs;
631     }
632 
633     /**
634      * Gets an implementation for a given identifier from the list of modules.
635      *
636      * @param implementation The identifier of the implementation to return.
637      *
638      * @return The first matching implementation or {@code null}, if no such implementation is found.
639      *
640      * @throws NullPointerException if {@code implementation} is {@code null}.
641      *
642      * @see #getModule()
643      * @see Module#getImplementations()
644      * @see Implementations#getImplementation( java.lang.String )
645      */
646     public Implementation getImplementation( final String implementation )
647     {
648         if ( implementation == null )
649         {
650             throw new NullPointerException( "implementation" );
651         }
652 
653         for ( int i = 0, s0 = this.getModule().size(); i < s0; i++ )
654         {
655             final Module m = this.getModule().get( i );
656 
657             if ( m.getImplementations() != null )
658             {
659                 final Implementation current = m.getImplementations().getImplementation( implementation );
660 
661                 if ( current != null )
662                 {
663                     return current;
664                 }
665             }
666         }
667 
668         return null;
669     }
670 
671     /**
672      * Gets an implementation for a given class from the list of modules.
673      *
674      * @param implementation The class of the implementation to return.
675      *
676      * @return The first matching implementation or {@code null}, if no such implementation is found.
677      *
678      * @throws NullPointerException if {@code implementation} is {@code null}.
679      *
680      * @see #getModule()
681      * @see Module#getImplementations()
682      * @see Implementations#getImplementation( java.lang.Class )
683      */
684     public Implementation getImplementation( final Class<?> implementation )
685     {
686         if ( implementation == null )
687         {
688             throw new NullPointerException( "implementation" );
689         }
690 
691         for ( int i = 0, s0 = this.getModule().size(); i < s0; i++ )
692         {
693             final Module m = this.getModule().get( i );
694 
695             if ( m.getImplementations() != null )
696             {
697                 final Implementation current = m.getImplementations().getImplementation( implementation );
698 
699                 if ( current != null )
700                 {
701                     return current;
702                 }
703             }
704         }
705 
706         return null;
707     }
708 
709     /**
710      * Gets an implementation for a given object from the list of modules.
711      *
712      * @param object The object of the implementation to return.
713      *
714      * @return The first matching implementation or {@code null}, if no such implementation is found.
715      *
716      * @throws NullPointerException if {@code object} is {@code null}.
717      *
718      * @see #getModule()
719      * @see #getImplementation( java.lang.Class )
720      */
721     public Implementation getImplementation( final Object object )
722     {
723         return this.collectImplementation( object.getClass() );
724     }
725 
726     /**
727      * Gets an implementation for a given name implementing a given specification from the list of modules.
728      *
729      * @param specification The identifier of the specification to return an implementation of.
730      * @param name The name of the implementation to return.
731      *
732      * @return The first matching implementation or {@code null}, if no such implementation is found.
733      *
734      * @throws NullPointerException if {@code specification} or {@code name} is {@code null}.
735      *
736      * @see #getModule()
737      * @see #getImplementations( java.lang.String )
738      * @see Implementations#getImplementationByName( java.lang.String )
739      */
740     public Implementation getImplementation( final String specification, final String name )
741     {
742         if ( specification == null )
743         {
744             throw new NullPointerException( "specification" );
745         }
746         if ( name == null )
747         {
748             throw new NullPointerException( "name" );
749         }
750 
751         final Implementations implementations = this.getImplementations( specification );
752         if ( implementations != null )
753         {
754             return implementations.getImplementationByName( name );
755         }
756 
757         return null;
758     }
759 
760     /**
761      * Gets all dependencies of an implementation from the list of modules.
762      *
763      * @param implementation The identifier of the implementation to get all dependencies of.
764      *
765      * @return All dependencies of the first matching implementation or {@code null}, if no such implementation is
766      * found or if the first matching implementation does not have any dependencies.
767      *
768      * @throws NullPointerException if {@code implementation} is {@code null}.
769      *
770      * @see #getModule()
771      * @see #getImplementation( java.lang.String )
772      * @see Implementation#getImplementations()
773      * @see Implementations#getReference()
774      * @see Implementation#getDependencies()
775      */
776     public Dependencies getDependencies( final String implementation )
777     {
778         if ( implementation == null )
779         {
780             throw new NullPointerException( "implementation" );
781         }
782 
783         final Dependencies dependencies = new Dependencies();
784         final Implementation impl = this.getImplementation( implementation );
785         this.collectModelObjects( impl, dependencies, null, null, null, null, new java.util.HashSet<String>(), true );
786         this.collectClassDeclarationModelObjects( impl, dependencies, null, null, null, null );
787         java.util.Collections.sort( dependencies.getDependency(), DEPENDENCY_NAME_COMPARATOR );
788         return dependencies.getDependency().isEmpty() ? null : dependencies;
789     }
790 
791     /**
792      * Gets all properties of an implementation from the list of modules.
793      *
794      * @param implementation The identifier of the implementation to get all properties of.
795      *
796      * @return All properties of the first matching implementation or {@code null}, if no such implementation is found
797      * or if the first matching implementation does not have any properties.
798      *
799      * @throws NullPointerException if {@code implementation} is {@code null}.
800      *
801      * @see #getModule()
802      * @see #getImplementation( java.lang.String )
803      * @see Implementation#getImplementations()
804      * @see Implementations#getReference()
805      * @see Implementation#getProperties()
806      */
807     public Properties getProperties( final String implementation )
808     {
809         if ( implementation == null )
810         {
811             throw new NullPointerException( "implementation" );
812         }
813 
814         final Properties properties = new Properties();
815         final Specifications specifications = new Specifications();
816         final Implementation impl = this.getImplementation( implementation );
817         this.collectModelObjects(
818             impl, null, null, properties, specifications, null, new java.util.HashSet<String>(), true );
819 
820         this.collectClassDeclarationModelObjects( impl, null, null, properties, specifications, null );
821         this.collectSpecifiedModelObjects( specifications, properties );
822         java.util.Collections.sort( properties.getProperty(), PROPERTY_NAME_COMPARATOR );
823         return properties.getProperty().isEmpty() ? null : properties;
824     }
825 
826     /**
827      * Gets all properties specified for an implementation from the list of modules.
828      *
829      * @param implementation The identifier of the implementation to return specified properties of.
830      *
831      * @return All properties specified for the first matching implementation or {@code null}, if no such implementation
832      * is found or if the first matching implementation does not have any specified properties.
833      *
834      * @throws NullPointerException if {@code implementation} is {@code null}.
835      *
836      * @see #getModule()
837      * @see #getSpecifications( java.lang.String )
838      * @see Specification#getProperties()
839      */
840     public Properties getSpecifiedProperties( final String implementation )
841     {
842         if ( implementation == null )
843         {
844             throw new NullPointerException( "implementation" );
845         }
846 
847         final Properties properties = new Properties();
848         final Specifications specs = this.getSpecifications( implementation );
849 
850         if ( specs != null )
851         {
852             for ( int i = 0, s0 = specs.getSpecification().size(); i < s0; i++ )
853             {
854                 final Specification s = specs.getSpecification().get( i );
855 
856                 if ( s.getProperties() != null )
857                 {
858                     properties.getProperty().addAll( s.getProperties().getProperty() );
859                 }
860             }
861         }
862 
863         java.util.Collections.sort( properties.getProperty(), PROPERTY_NAME_COMPARATOR );
864         return properties.getProperty().isEmpty() ? null : properties;
865     }
866 
867     /**
868      * Gets all messages of an implementation from the list of modules.
869      *
870      * @param implementation The identifier of the implementation to get all messages of.
871      *
872      * @return All messages of the first matching implementation or {@code null}, if no such implementation is found
873      * or if the first matching implementation does not have any messages.
874      *
875      * @throws NullPointerException if {@code implementation} is {@code null}.
876      *
877      * @see #getModule()
878      * @see #getImplementation( java.lang.String )
879      * @see Implementation#getImplementations()
880      * @see Implementations#getReference()
881      * @see Implementation#getMessages()
882      */
883     public Messages getMessages( final String implementation )
884     {
885         if ( implementation == null )
886         {
887             throw new NullPointerException( "implementation" );
888         }
889 
890         final Messages msgs = new Messages();
891         final Implementation impl = this.getImplementation( implementation );
892         this.collectModelObjects( impl, null, msgs, null, null, null, new java.util.HashSet<String>(), true );
893         this.collectClassDeclarationModelObjects( impl, null, msgs, null, null, null );
894         java.util.Collections.sort( msgs.getMessage(), MESSAGE_NAME_COMPARATOR );
895         return msgs.getMessage().isEmpty() ? null : msgs;
896     }
897 
898     /**
899      * Gets any objects of an implementation from the list of modules.
900      *
901      * @param implementation The identifier of the implementation to get any objects of.
902      *
903      * @return Any objects of the first matching implementation or {@code null}, if no such implementation is found.
904      *
905      * @throws NullPointerException if {@code implementation} is {@code null}.
906      *
907      * @see #getModule()
908      * @see #getImplementation( java.lang.String )
909      * @see Implementation#getImplementations()
910      * @see Implementations#getReference()
911      * @see Implementation#getAny()
912      *
913      * @since 1.2
914      */
915     public List<Object> getAnyObjects( final String implementation )
916     {
917         if ( implementation == null )
918         {
919             throw new NullPointerException( "implementation" );
920         }
921 
922         final Implementation impl = this.getImplementation( implementation );
923         final java.util.List<Object> any = new java.util.LinkedList<Object>();
924         this.collectModelObjects( impl, null, null, null, null, any, new java.util.HashSet<String>(), true );
925         this.collectClassDeclarationModelObjects( impl, null, null, null, null, any );
926         return any;
927     }
928 
929     /**
930      * Gets all implementations implementing a given specification from the list of modules.
931      *
932      * @param specification The identifier of the specification to return all implementations of.
933      *
934      * @return All implementations implementing the first matching specification or {@code null}, if no such
935      * specification is found or if the first matching specification does not have any implementations.
936      *
937      * @throws NullPointerException if {@code specification} is {@code null}.
938      *
939      * @see #getModule()
940      * @see #getSpecifications( java.lang.String )
941      */
942     public Implementations getImplementations( final String specification )
943     {
944         if ( specification == null )
945         {
946             throw new NullPointerException( "specification" );
947         }
948 
949         final Implementations implementations = new Implementations();
950 
951         for ( int i = 0, s0 = this.getModule().size(); i < s0; i++ )
952         {
953             final Module m = this.getModule().get( i );
954 
955             if ( m.getImplementations() != null )
956             {
957                 for ( int j = 0, s1 = m.getImplementations().getImplementation().size(); j < s1; j++ )
958                 {
959                     final Implementation impl = m.getImplementations().getImplementation().get( j );
960                     final Specifications specs = this.getSpecifications( impl.getIdentifier() );
961 
962                     if ( specs != null && specs.getSpecification( specification ) != null )
963                     {
964                         implementations.getImplementation().add( impl );
965                     }
966                 }
967             }
968         }
969 
970         return implementations.getImplementation().size() > 0 ? implementations : null;
971     }
972 
973     /**
974      * Merges this list of modules to a single module.
975      *
976      * @param name The name of the module to return.
977      *
978      * @return A module holding all model objects from the list.
979      *
980      * @throws NullPointerException if {@code name} is {@code null}.
981      */
982     public Module getMergedModule( final String name )
983     {
984         if ( name == null )
985         {
986             throw new NullPointerException( "name" );
987         }
988 
989         final Modules copy = this.clone();
990         final Module mergedModule = new Module();
991         mergedModule.setName( name );
992 
993         for ( int i = 0, s0 = copy.getModule().size(); i < s0; i++ )
994         {
995             final Module m = copy.getModule().get( i );
996             final java.util.Set<String> referencedMessages = new java.util.HashSet<String>();
997             final java.util.Set<String> referencedProperties = new java.util.HashSet<String>();
998 
999             if ( m.getImplementations() != null )
1000             {
1001                 for ( int j = 0, s1 = m.getImplementations().getImplementation().size(); j < s1; j++ )
1002                 {
1003                     final Implementation impl = m.getImplementations().getImplementation().get( j );
1004                     if ( mergedModule.getImplementations() == null )
1005                     {
1006                         mergedModule.setImplementations( new Implementations() );
1007                     }
1008 
1009                     if ( impl.getMessages() != null && !impl.getMessages().getReference().isEmpty() )
1010                     {
1011                         for ( java.util.Iterator<MessageReference> it = impl.getMessages().getReference().iterator();
1012                               it.hasNext(); )
1013                         {
1014                             final String messageName = it.next().getName();
1015                             impl.getMessages().getMessage().add( m.getMessages().getMessage( messageName ) );
1016                             referencedMessages.add( messageName );
1017                             it.remove();
1018                         }
1019                     }
1020 
1021                     if ( impl.getProperties() != null && !impl.getProperties().getReference().isEmpty() )
1022                     {
1023                         for ( java.util.Iterator<PropertyReference> it = impl.getProperties().getReference().iterator();
1024                               it.hasNext(); )
1025                         {
1026                             final String propertyName = it.next().getName();
1027                             impl.getProperties().getProperty().add( m.getProperties().getProperty( propertyName ) );
1028                             referencedProperties.add( propertyName );
1029                             it.remove();
1030                         }
1031                     }
1032 
1033                     mergedModule.getImplementations().getImplementation().add( impl );
1034                 }
1035             }
1036 
1037             if ( m.getSpecifications() != null )
1038             {
1039                 if ( mergedModule.getSpecifications() == null )
1040                 {
1041                     mergedModule.setSpecifications( new Specifications() );
1042                 }
1043 
1044                 for ( int j = 0, s1 = m.getSpecifications().getSpecification().size(); j < s1; j++ )
1045                 {
1046                     final Specification s = m.getSpecifications().getSpecification().get( j );
1047 
1048                     if ( s.getProperties() != null && !s.getProperties().getReference().isEmpty() )
1049                     {
1050                         for ( java.util.Iterator<PropertyReference> it = s.getProperties().getReference().iterator();
1051                               it.hasNext(); )
1052                         {
1053                             final String propertyName = it.next().getName();
1054                             s.getProperties().getProperty().add( m.getProperties().getProperty( propertyName ) );
1055                             referencedProperties.add( propertyName );
1056                             it.remove();
1057                         }
1058                     }
1059 
1060                     mergedModule.getSpecifications().getSpecification().add( s );
1061                 }
1062             }
1063 
1064             for ( String messageName : referencedMessages )
1065             {
1066                 for ( java.util.Iterator<Message> it = m.getMessages().getMessage().iterator(); it.hasNext(); )
1067                 {
1068                     if ( messageName.equals( it.next().getName() ) )
1069                     {
1070                         it.remove();
1071                         break;
1072                     }
1073                 }
1074             }
1075 
1076             for ( String propertyName : referencedProperties )
1077             {
1078                 for ( java.util.Iterator<Property> it = m.getProperties().getProperty().iterator(); it.hasNext(); )
1079                 {
1080                     if ( propertyName.equals( it.next().getName() ) )
1081                     {
1082                         it.remove();
1083                         break;
1084                     }
1085                 }
1086             }
1087 
1088             if ( m.getProperties() != null && !m.getProperties().getProperty().isEmpty() )
1089             {
1090                 if ( mergedModule.getProperties() == null )
1091                 {
1092                     mergedModule.setProperties( new Properties() );
1093                 }
1094 
1095                 mergedModule.getProperties().getProperty().addAll( m.getProperties().getProperty() );
1096             }
1097 
1098             if ( m.getMessages() != null && !m.getMessages().getMessage().isEmpty() )
1099             {
1100                 if ( mergedModule.getMessages() == null )
1101                 {
1102                     mergedModule.setMessages( new Messages() );
1103                 }
1104 
1105                 mergedModule.getMessages().getMessage().addAll( m.getMessages().getMessage() );
1106             }
1107         }
1108 
1109         return mergedModule;
1110     }
1111 
1112     /**
1113      * Gets the instance of an object from the list of modules.
1114      *
1115      * @param object The object to get the instance of.
1116      *
1117      * @return The instance of {@code object} or {@code null}, if no such instance is found.
1118      *
1119      * @throws NullPointerException if {@code object} is {@code null}.
1120      *
1121      * @see #getModule()
1122      * @see #getImplementation( java.lang.Object )
1123      * @see #getInstance( java.lang.String )
1124      * @see #createObject(org.jomc.model.Instance instance, java.lang.ClassLoader classLoader)
1125      */
1126     public Instance getInstance( final Object object )
1127     {
1128         if ( object == null )
1129         {
1130             throw new NullPointerException( "object" );
1131         }
1132 
1133         synchronized ( this.objects )
1134         {
1135             Instance instance = this.objects.get( object );
1136 
1137             if ( instance == null )
1138             {
1139                 final Implementation i = this.getImplementation( object );
1140 
1141                 if ( i != null )
1142                 {
1143                     instance = this.getInstance( i.getIdentifier() );
1144                     if ( instance != null )
1145                     {
1146                         this.objects.put( object, instance );
1147                     }
1148                 }
1149             }
1150 
1151             return instance;
1152         }
1153     }
1154 
1155     /**
1156      * Gets an instance for an implementation from the list of modules.
1157      *
1158      * @param implementation The identifier of the implementation to get an instance for.
1159      *
1160      * @return A new instance for the first matching implementation or {@code null}, if no such implementation is found.
1161      *
1162      * @throws NullPointerException if {@code implementation} is {@code null}.
1163      *
1164      * @see #getModule()
1165      * @see #getImplementation( java.lang.String )
1166      * @see #getDependencies(java.lang.String)
1167      * @see #getProperties(java.lang.String)
1168      * @see #getMessages(java.lang.String)
1169      * @see #getSpecifications(java.lang.String)
1170      * @see #getAnyObjects(java.lang.String)
1171      */
1172     public Instance getInstance( final String implementation )
1173     {
1174         if ( implementation == null )
1175         {
1176             throw new NullPointerException( "implementation" );
1177         }
1178 
1179         final Implementation i = this.getImplementation( implementation );
1180 
1181         if ( i != null && i.getClazz() != null )
1182         {
1183             final Instance instance = new Instance();
1184             instance.setIdentifier( i.getIdentifier() );
1185             instance.setName( i.getName() );
1186             instance.setClazz( i.getClazz() );
1187             instance.setStateless( i.isStateless() );
1188             instance.setDependencies( this.getDependencies( implementation ) );
1189             instance.setProperties( this.getProperties( implementation ) );
1190             instance.setMessages( this.getMessages( implementation ) );
1191             instance.setSpecifications( this.getSpecifications( implementation ) );
1192             instance.getAny().addAll( this.getAnyObjects( implementation ) );
1193             return instance;
1194         }
1195 
1196         return null;
1197     }
1198 
1199     /**
1200      * Gets an instance for an implementation from the list of modules overridden with a given dependency.
1201      *
1202      * @param implementation The identifier of the implementation to get an instance for.
1203      * @param dependency The dependency to use for overriding model objects of the instance.
1204      *
1205      * @return An instance for the first matching implementation with any model objects overridden using
1206      * {@code dependency} or {@code null}, if no such implementation is found.
1207      *
1208      * @throws NullPointerException if {@code implementation} or {@code dependency} is {@code null}.
1209      *
1210      * @see #getModule()
1211      * @see #getInstance( java.lang.String )
1212      */
1213     public Instance getInstance( final String implementation, final Dependency dependency )
1214     {
1215         if ( implementation == null )
1216         {
1217             throw new NullPointerException( "implementation" );
1218         }
1219         if ( dependency == null )
1220         {
1221             throw new NullPointerException( "dependency" );
1222         }
1223 
1224         Instance instance = this.getInstance( implementation );
1225 
1226         if ( instance != null )
1227         {
1228             final Specification dependencySpecification = this.getSpecification( dependency.getIdentifier() );
1229 
1230             if ( dependencySpecification != null && dependencySpecification.getScope() == null )
1231             {
1232                 if ( dependency.getDependencies() != null && !dependency.getDependencies().getDependency().isEmpty() )
1233                 {
1234                     final Dependencies dependencies = new Dependencies();
1235                     dependencies.getDependency().addAll( dependency.getDependencies().getDependency() );
1236 
1237                     if ( instance.getDependencies() != null )
1238                     {
1239                         for ( int i = 0, s0 = instance.getDependencies().getDependency().size(); i < s0; i++ )
1240                         {
1241                             final Dependency d = instance.getDependencies().getDependency().get( i );
1242                             final Dependency td = dependencies.getDependency( d.getName() );
1243 
1244                             if ( td == null )
1245                             {
1246                                 dependencies.getDependency().add( d );
1247                             }
1248                             else
1249                             {
1250                                 this.collectDependencies( d, td );
1251                             }
1252                         }
1253                     }
1254 
1255                     instance.setDependencies( dependencies );
1256                 }
1257 
1258                 if ( dependency.getMessages() != null && !dependency.getMessages().getMessage().isEmpty() )
1259                 {
1260                     final Messages messages = new Messages();
1261                     messages.getMessage().addAll( dependency.getMessages().getMessage() );
1262 
1263                     if ( instance.getMessages() != null )
1264                     {
1265                         for ( int i = 0, s0 = instance.getMessages().getMessage().size(); i < s0; i++ )
1266                         {
1267                             final Message m = instance.getMessages().getMessage().get( i );
1268 
1269                             if ( messages.getMessage( m.getName() ) == null )
1270                             {
1271                                 messages.getMessage().add( m );
1272                             }
1273                         }
1274                     }
1275 
1276                     instance.setMessages( messages );
1277                 }
1278 
1279                 if ( dependency.getProperties() != null && !dependency.getProperties().getProperty().isEmpty() )
1280                 {
1281                     final Properties properties = new Properties();
1282                     properties.getProperty().addAll( dependency.getProperties().getProperty() );
1283 
1284                     if ( instance.getProperties() != null )
1285                     {
1286                         for ( int i = 0, s0 = instance.getProperties().getProperty().size(); i < s0; i++ )
1287                         {
1288                             final Property p = instance.getProperties().getProperty().get( i );
1289 
1290                             if ( properties.getProperty( p.getName() ) == null )
1291                             {
1292                                 properties.getProperty().add( p );
1293                             }
1294                         }
1295                     }
1296 
1297                     instance.setProperties( properties );
1298                 }
1299             }
1300         }
1301 
1302         return instance;
1303     }
1304 
1305     /**
1306      * Creates an object of a given instance from the list of modules.
1307      *
1308      * @param instance The instance to create an object of.
1309      * @param classLoader The class loader to use for creating the object or {@code null}, to use the bootstrap class
1310      * loader.
1311      *
1312      * @return A new object of {@code instance}.
1313      *
1314      * @throws NullPointerException if {@code instance}  is {@code null},
1315      * @throws InstantiationException if creating an object fails.
1316      *
1317      * @see #getModule()
1318      * @see Instance#getJavaClass(java.lang.ClassLoader)
1319      * @see Instance#getJavaConstructor(java.lang.ClassLoader)
1320      * @see Instance#getJavaFactoryMethodName()
1321      * @see Instance#getJavaFactoryMethod(java.lang.ClassLoader)
1322      * @see Instance#isJavaClassAssignable(java.lang.ClassLoader)
1323      */
1324     public Object createObject( final Instance instance, final ClassLoader classLoader ) throws InstantiationException
1325     {
1326         if ( instance == null )
1327         {
1328             throw new NullPointerException( "instance" );
1329         }
1330 
1331         Object object = null;
1332 
1333         try
1334         {
1335             final Class<?> clazz = instance.getJavaClass( classLoader );
1336             final java.lang.reflect.Constructor<?> ctor = instance.getJavaConstructor( classLoader );
1337 
1338             if ( ctor != null && instance.isJavaClassAssignable( classLoader ) )
1339             {
1340                 synchronized ( this.objects )
1341                 {
1342                     object = clazz.newInstance();
1343                     this.objects.put( object, instance );
1344                 }
1345             }
1346             else
1347             {
1348                 java.lang.reflect.Method factoryMethod = instance.getJavaFactoryMethod( classLoader );
1349 
1350                 if ( factoryMethod != null )
1351                 {
1352                     if ( java.lang.reflect.Modifier.isStatic( factoryMethod.getModifiers() ) )
1353                     {
1354                         synchronized ( this.objects )
1355                         {
1356                             object = factoryMethod.invoke( null, (Object[]) null );
1357                             if ( object != null )
1358                             {
1359                                 this.objects.put( object, instance );
1360                             }
1361                         }
1362                     }
1363                     else if ( ctor != null )
1364                     {
1365                         synchronized ( this.objects )
1366                         {
1367                             final Object o = ctor.newInstance();
1368                             this.objects.put( o, instance );
1369 
1370                             try
1371                             {
1372                                 object = factoryMethod.invoke( o, (Object[]) null );
1373                             }
1374                             finally
1375                             {
1376                                 this.objects.remove( o );
1377                             }
1378 
1379                             if ( object != null )
1380                             {
1381                                 this.objects.put( object, instance );
1382                             }
1383                         }
1384                     }
1385                 }
1386             }
1387 
1388             if ( object == null )
1389             {
1390                 throw new InstantiationException( getMessage(
1391                     instance.getJavaFactoryMethodName() != null
1392                     ? "failedCreatingObjectWithMethod" : "failedCreatingObject",
1393                     instance.getIdentifier(), clazz.getName(), instance.getJavaFactoryMethodName() ) );
1394 
1395             }
1396 
1397             return object;
1398         }
1399         catch ( final java.lang.reflect.InvocationTargetException e )
1400         {
1401             final Throwable target = e.getTargetException() != null ? e.getTargetException() : e;
1402             throw (InstantiationException) new InstantiationException(
1403                 getMessage( "exceptionCreatingObject", instance.getIdentifier() ) ).initCause( target );
1404 
1405         }
1406         catch ( final IllegalAccessException e )
1407         {
1408             throw (InstantiationException) new InstantiationException(
1409                 getMessage( "exceptionCreatingObject", instance.getIdentifier() ) ).initCause( e );
1410 
1411         }
1412         catch ( final ClassNotFoundException e )
1413         {
1414             throw (InstantiationException) new InstantiationException(
1415                 getMessage( "exceptionCreatingObject", instance.getIdentifier() ) ).initCause( e );
1416 
1417         }
1418     }
1419 
1420     /** @since 1.2 */
1421     private void collectModelObjects( final Implementation implementation, final Dependencies dependencies,
1422                                       final Messages messages, final Properties properties,
1423                                       final Specifications specifications, final List<Object> any,
1424                                       final java.util.Set<String> seen, final boolean includeDeclared )
1425     {
1426         if ( implementation != null && !seen.contains( implementation.getIdentifier() ) )
1427         {
1428             seen.add( implementation.getIdentifier() );
1429 
1430             if ( includeDeclared )
1431             {
1432                 if ( dependencies != null && implementation.getDependencies() != null )
1433                 {
1434                     for ( int i = 0, s0 = implementation.getDependencies().getDependency().size(); i < s0; i++ )
1435                     {
1436                         final Dependency d = implementation.getDependencies().getDependency().get( i );
1437                         final Dependency dependency = dependencies.getDependency( d.getName() );
1438 
1439                         if ( dependency == null )
1440                         {
1441                             dependencies.getDependency().add( d );
1442                         }
1443                         else
1444                         {
1445                             this.collectDependencies( d, dependency );
1446                         }
1447                     }
1448                 }
1449 
1450                 if ( messages != null && implementation.getMessages() != null )
1451                 {
1452                     for ( int i = 0, s0 = implementation.getMessages().getMessage().size(); i < s0; i++ )
1453                     {
1454                         final Message msg = implementation.getMessages().getMessage().get( i );
1455 
1456                         if ( messages.getMessage( msg.getName() ) == null )
1457                         {
1458                             messages.getMessage().add( msg );
1459                         }
1460                     }
1461 
1462                     if ( !implementation.getMessages().getReference().isEmpty() )
1463                     {
1464                         final Module m = this.getModuleOfImplementation( implementation.getIdentifier() );
1465 
1466                         if ( m != null )
1467                         {
1468                             for ( int i = 0, s0 = implementation.getMessages().getReference().size(); i < s0; i++ )
1469                             {
1470                                 final MessageReference ref = implementation.getMessages().getReference().get( i );
1471 
1472                                 if ( messages.getMessage( ref.getName() ) == null )
1473                                 {
1474                                     Message referenced = m.getMessages().getMessage( ref.getName() );
1475                                     if ( referenced != null )
1476                                     {
1477                                         referenced = referenced.clone();
1478                                         referenced.setDeprecated( ref.isDeprecated() );
1479                                         referenced.setFinal( ref.isFinal() );
1480                                         referenced.setOverride( ref.isOverride() );
1481                                         messages.getMessage().add( referenced );
1482                                     }
1483                                 }
1484                             }
1485                         }
1486                     }
1487                 }
1488 
1489                 if ( properties != null && implementation.getProperties() != null )
1490                 {
1491                     for ( int i = 0, s0 = implementation.getProperties().getProperty().size(); i < s0; i++ )
1492                     {
1493                         final Property p = implementation.getProperties().getProperty().get( i );
1494 
1495                         if ( properties.getProperty( p.getName() ) == null )
1496                         {
1497                             properties.getProperty().add( p );
1498                         }
1499                     }
1500 
1501                     if ( !implementation.getProperties().getReference().isEmpty() )
1502                     {
1503                         final Module m = this.getModuleOfImplementation( implementation.getIdentifier() );
1504 
1505                         if ( m != null )
1506                         {
1507                             for ( int i = 0, s0 = implementation.getProperties().getReference().size(); i < s0; i++ )
1508                             {
1509                                 final PropertyReference ref = implementation.getProperties().getReference().get( i );
1510 
1511                                 if ( properties.getProperty( ref.getName() ) == null )
1512                                 {
1513                                     Property referenced = m.getProperties().getProperty( ref.getName() );
1514                                     if ( referenced != null )
1515                                     {
1516                                         referenced = referenced.clone();
1517                                         referenced.setDeprecated( ref.isDeprecated() );
1518                                         referenced.setFinal( ref.isFinal() );
1519                                         referenced.setOverride( ref.isOverride() );
1520                                         properties.getProperty().add( referenced );
1521                                     }
1522                                 }
1523                             }
1524                         }
1525                     }
1526                 }
1527 
1528                 if ( specifications != null && implementation.getSpecifications() != null )
1529                 {
1530                     for ( int i = 0, s0 = implementation.getSpecifications().getReference().size(); i < s0; i++ )
1531                     {
1532                         final SpecificationReference r = implementation.getSpecifications().getReference().get( i );
1533 
1534                         if ( specifications.getReference( r.getIdentifier() ) == null )
1535                         {
1536                             specifications.getReference().add( r );
1537 
1538                             final Specification s = this.getSpecification( r.getIdentifier() );
1539                             if ( s != null && specifications.getSpecification( s.getIdentifier() ) == null )
1540                             {
1541                                 specifications.getSpecification().add( s );
1542                             }
1543                         }
1544                     }
1545                 }
1546 
1547                 if ( any != null && !implementation.getAny().isEmpty() )
1548                 {
1549                     for ( int i = 0, s0 = implementation.getAny().size(); i < s0; i++ )
1550                     {
1551                         final Object o = implementation.getAny().get( i );
1552 
1553                         if ( o instanceof org.w3c.dom.Element )
1554                         {
1555                             if ( this.getElement( any, (org.w3c.dom.Element) o ) == null )
1556                             {
1557                                 any.add( o );
1558                             }
1559 
1560                             continue;
1561                         }
1562 
1563                         if ( o instanceof javax.xml.bind.JAXBElement<?> )
1564                         {
1565                             if ( this.getElement( any, (javax.xml.bind.JAXBElement<?>) o ) == null )
1566                             {
1567                                 any.add( o );
1568                             }
1569 
1570                             continue;
1571                         }
1572 
1573                         any.add( o );
1574                     }
1575                 }
1576             }
1577 
1578             if ( implementation.getImplementations() != null )
1579             {
1580                 for ( int i = 0, s0 = implementation.getImplementations().getReference().size(); i < s0; i++ )
1581                 {
1582                     final ImplementationReference r = implementation.getImplementations().getReference().get( i );
1583                     this.collectModelObjects( this.getImplementation( r.getIdentifier() ), dependencies, messages,
1584                                               properties, specifications, any, seen, true );
1585 
1586                 }
1587             }
1588         }
1589     }
1590 
1591     /** @since 1.2 */
1592     private void collectClassDeclarationModelObjects( final Implementation implementation,
1593                                                       final Dependencies dependencies, final Messages messages,
1594                                                       final Properties properties, final Specifications specifications,
1595                                                       final List<Object> any )
1596     {
1597         Implementation declaration = null;
1598 
1599         if ( implementation != null && implementation.getClazz() != null && !implementation.isClassDeclaration() )
1600         {
1601             for ( int i = 0, s0 = this.getModule().size(); i < s0; i++ )
1602             {
1603                 final Module m = this.getModule().get( i );
1604 
1605                 if ( m.getImplementations() != null )
1606                 {
1607                     for ( int j = 0, s1 = m.getImplementations().getImplementation().size(); j < s1; j++ )
1608                     {
1609                         final Implementation current = m.getImplementations().getImplementation().get( j );
1610 
1611                         if ( current.getClazz() != null && current.getClazz().equals( implementation.getClazz() )
1612                              && current.isClassDeclaration() )
1613                         {
1614                             declaration = current;
1615                             break;
1616                         }
1617                     }
1618                 }
1619             }
1620         }
1621 
1622         if ( declaration != null )
1623         {
1624             this.collectModelObjects( declaration, dependencies, messages, properties, specifications, any,
1625                                       new java.util.HashSet<String>(), true );
1626 
1627         }
1628     }
1629 
1630     /** @since 1.2 */
1631     private void collectSpecifiedModelObjects( final Specifications specifications, final Properties properties )
1632     {
1633         for ( int i = 0, s0 = specifications.getSpecification().size(); i < s0; i++ )
1634         {
1635             final Specification s = specifications.getSpecification().get( i );
1636 
1637             if ( s.getProperties() != null )
1638             {
1639                 for ( int j = 0, s1 = s.getProperties().getProperty().size(); j < s1; j++ )
1640                 {
1641                     final Property p = s.getProperties().getProperty().get( j );
1642 
1643                     if ( properties.getProperty( p.getName() ) == null )
1644                     {
1645                         properties.getProperty().add( p );
1646                     }
1647                 }
1648             }
1649         }
1650     }
1651 
1652     private void collectDependencies( final Dependency source, final Dependency target )
1653     {
1654         if ( source.getMessages() != null )
1655         {
1656             if ( target.getMessages() == null )
1657             {
1658                 target.setMessages( new Messages() );
1659             }
1660 
1661             for ( int i = 0, s0 = source.getMessages().getMessage().size(); i < s0; i++ )
1662             {
1663                 final Message m = source.getMessages().getMessage().get( i );
1664 
1665                 if ( target.getMessages().getMessage( m.getName() ) == null )
1666                 {
1667                     target.getMessages().getMessage().add( m );
1668                 }
1669             }
1670         }
1671 
1672         if ( source.getProperties() != null )
1673         {
1674             if ( target.getProperties() == null )
1675             {
1676                 target.setProperties( new Properties() );
1677             }
1678 
1679             for ( int i = 0, s0 = source.getProperties().getProperty().size(); i < s0; i++ )
1680             {
1681                 final Property p = source.getProperties().getProperty().get( i );
1682 
1683                 if ( target.getProperties().getProperty( p.getName() ) == null )
1684                 {
1685                     target.getProperties().getProperty().add( p );
1686                 }
1687             }
1688         }
1689 
1690         if ( source.getDependencies() != null )
1691         {
1692             if ( target.getDependencies() == null )
1693             {
1694                 target.setDependencies( new Dependencies() );
1695             }
1696 
1697             for ( int i = 0, s0 = source.getDependencies().getDependency().size(); i < s0; i++ )
1698             {
1699                 final Dependency sd = source.getDependencies().getDependency().get( i );
1700                 final Dependency td = target.getDependencies().getDependency( sd.getName() );
1701 
1702                 if ( td == null )
1703                 {
1704                     target.getDependencies().getDependency().add( sd );
1705                 }
1706                 else
1707                 {
1708                     this.collectDependencies( sd, td );
1709                 }
1710             }
1711         }
1712     }
1713 
1714     private Implementation collectImplementation( final Class<?> clazz )
1715     {
1716         Implementation i = this.getImplementation( clazz );
1717         if ( i == null && clazz.getSuperclass() != null )
1718         {
1719             i = this.collectImplementation( clazz.getSuperclass() );
1720         }
1721 
1722         return i;
1723     }
1724 
1725     private org.w3c.dom.Element getElement( final List<Object> list, final org.w3c.dom.Element e )
1726     {
1727         for ( int i = 0, s0 = list.size(); i < s0; i++ )
1728         {
1729             final Object o = list.get( i );
1730 
1731             if ( o instanceof org.w3c.dom.Element )
1732             {
1733                 final org.w3c.dom.Element current = (org.w3c.dom.Element) o;
1734                 if ( ( e.getNamespaceURI() == null
1735                        ? current.getNamespaceURI() == null
1736                        : e.getNamespaceURI().equals( current.getNamespaceURI() ) )
1737                      && ( e.getLocalName() == null
1738                           ? current.getLocalName() == null
1739                           : e.getLocalName().equals( current.getLocalName() ) ) )
1740                 {
1741                     return current;
1742                 }
1743             }
1744         }
1745 
1746         return null;
1747     }
1748 
1749     private javax.xml.bind.JAXBElement<?> getElement( final List<Object> list, final javax.xml.bind.JAXBElement<?> e )
1750     {
1751         for ( int i = 0, s0 = list.size(); i < s0; i++ )
1752         {
1753             final Object o = list.get( i );
1754 
1755             if ( o instanceof javax.xml.bind.JAXBElement<?> )
1756             {
1757                 final javax.xml.bind.JAXBElement<?> current = (javax.xml.bind.JAXBElement<?>) o;
1758                 if ( e.getName().equals( current.getName() ) )
1759                 {
1760                     return current;
1761                 }
1762             }
1763         }
1764 
1765         return null;
1766     }
1767 
1768     private void resolveClasspath( final Module cpModule, final ClassLoader classLoader )
1769     {
1770         for ( int i = 0, s0 = this.getModule().size(); i < s0; i++ )
1771         {
1772             final Module m = this.getModule().get( i );
1773 
1774             if ( m.getSpecifications() != null )
1775             {
1776                 this.resolveClasspath( m.getSpecifications(), cpModule, classLoader );
1777             }
1778 
1779             if ( m.getImplementations() != null )
1780             {
1781                 this.resolveClasspath( m.getImplementations(), cpModule, classLoader );
1782             }
1783         }
1784     }
1785 
1786     private void resolveClasspath( final SpecificationReference ref, final Module cpModule,
1787                                    final ClassLoader classLoader )
1788     {
1789         if ( this.getSpecification( ref.getIdentifier() ) == null )
1790         {
1791             this.resolveClasspath( ref.getIdentifier(), cpModule, classLoader );
1792         }
1793     }
1794 
1795     private void resolveClasspath( final Specifications specifications, final Module cpModule,
1796                                    final ClassLoader classLoader )
1797     {
1798         for ( int i = 0, s0 = specifications.getSpecification().size(); i < s0; i++ )
1799         {
1800             final Specification s = specifications.getSpecification().get( i );
1801 
1802             if ( s.getClazz() != null )
1803             {
1804                 this.resolveClasspath( s, cpModule, classLoader );
1805             }
1806         }
1807         for ( int i = 0, s0 = specifications.getReference().size(); i < s0; i++ )
1808         {
1809             final SpecificationReference ref = specifications.getReference().get( i );
1810             this.resolveClasspath( ref, cpModule, classLoader );
1811         }
1812     }
1813 
1814     private void resolveClasspath( final Implementations implementations, final Module cpModule,
1815                                    final ClassLoader classLoader )
1816     {
1817         for ( int i = 0, s0 = implementations.getImplementation().size(); i < s0; i++ )
1818         {
1819             final Implementation implementation = implementations.getImplementation().get( i );
1820 
1821             if ( implementation.getSpecifications() != null )
1822             {
1823                 this.resolveClasspath( implementation.getSpecifications(), cpModule, classLoader );
1824             }
1825 
1826             if ( implementation.getDependencies() != null )
1827             {
1828                 this.resolveClasspath( implementation.getDependencies(), cpModule, classLoader );
1829             }
1830         }
1831     }
1832 
1833     private void resolveClasspath( final Dependencies dependencies, final Module cpModule,
1834                                    final ClassLoader classLoader )
1835     {
1836         for ( int i = 0, s0 = dependencies.getDependency().size(); i < s0; i++ )
1837         {
1838             final Dependency dependency = dependencies.getDependency().get( i );
1839             this.resolveClasspath( dependency, cpModule, classLoader );
1840 
1841             if ( dependency.getDependencies() != null )
1842             {
1843                 this.resolveClasspath( dependency.getDependencies(), cpModule, classLoader );
1844             }
1845         }
1846     }
1847 
1848     private boolean resolveClasspath( final String identifier, final Module cpModule, final ClassLoader classLoader )
1849     {
1850         boolean classpathSpecification = false;
1851         Specification specification = cpModule.getSpecifications() == null
1852                                       ? null : cpModule.getSpecifications().getSpecification( identifier );
1853 
1854         if ( specification == null )
1855         {
1856             try
1857             {
1858                 final Class<?> classpathSpec = Class.forName( identifier, false, classLoader );
1859                 if ( java.lang.reflect.Modifier.isPublic( classpathSpec.getModifiers() ) )
1860                 {
1861                     classpathSpecification = true;
1862                     String vendor = null;
1863                     String version = null;
1864 
1865                     if ( classpathSpec.getPackage() != null )
1866                     {
1867                         vendor = classpathSpec.getPackage().getSpecificationVendor();
1868                         version = classpathSpec.getPackage().getSpecificationVersion();
1869                     }
1870 
1871                     specification = new Specification();
1872                     specification.setIdentifier( identifier );
1873                     specification.setClazz( classpathSpec.getName() );
1874                     specification.setMultiplicity( Multiplicity.MANY );
1875                     specification.setVendor( vendor );
1876                     specification.setVersion( version );
1877 
1878                     if ( cpModule.getSpecifications() == null )
1879                     {
1880                         cpModule.setSpecifications( new Specifications() );
1881                     }
1882 
1883                     cpModule.getSpecifications().getSpecification().add( specification );
1884 
1885                     this.resolveClasspath( specification, cpModule, classLoader );
1886                 }
1887             }
1888             catch ( final ClassNotFoundException e )
1889             {
1890                 classpathSpecification = false;
1891             }
1892         }
1893 
1894         return classpathSpecification;
1895     }
1896 
1897     private boolean resolveClasspath( final Specification specification, final Module cpModule,
1898                                       final ClassLoader classLoader )
1899     {
1900         boolean classpathImplementation = false;
1901         Implementation implementation =
1902             cpModule.getImplementations() == null ? null
1903             : cpModule.getImplementations().getImplementation( specification.getIdentifier() );
1904 
1905         if ( implementation == null )
1906         {
1907             implementation = this.getImplementation( specification.getIdentifier() );
1908         }
1909 
1910         if ( implementation == null )
1911         {
1912             String name = null;
1913 
1914             try
1915             {
1916                 final Class<?> classpathImpl = Class.forName( specification.getClazz(), false, classLoader );
1917 
1918                 if ( java.lang.reflect.Modifier.isPublic( classpathImpl.getModifiers() ) )
1919                 {
1920                     if ( !java.lang.reflect.Modifier.isAbstract( classpathImpl.getModifiers() ) )
1921                     {
1922                         try
1923                         {
1924                             classpathImpl.getConstructor( NO_CLASSES );
1925                             name = "init";
1926                             classpathImplementation = true;
1927                         }
1928                         catch ( final NoSuchMethodException e )
1929                         {
1930                             classpathImplementation = false;
1931                         }
1932                     }
1933 
1934                     if ( !classpathImplementation )
1935                     {
1936                         final char[] c = classpathImpl.getName().substring(
1937                             classpathImpl.getPackage().getName().length() + 1 ).toCharArray();
1938 
1939                         name = String.valueOf( c );
1940                         c[0] = Character.toUpperCase( c[0] );
1941 
1942                         if ( this.checkFactoryMethod( classpathImpl, classpathImpl, "getDefault" ) )
1943                         {
1944                             name = "default";
1945                             classpathImplementation = true;
1946                         }
1947                         else if ( this.checkFactoryMethod( classpathImpl, classpathImpl, "getInstance" ) )
1948                         {
1949                             name = "instance";
1950                             classpathImplementation = true;
1951                         }
1952                         else if ( this.checkFactoryMethod( classpathImpl, classpathImpl, "get" + String.valueOf( c ) ) )
1953                         {
1954                             classpathImplementation = true;
1955                         }
1956 
1957                     }
1958 
1959                     if ( classpathImplementation
1960                          && this.getImplementation( specification.getIdentifier(), name ) == null )
1961                     {
1962                         String vendor = null;
1963                         String version = null;
1964                         if ( classpathImpl.getPackage() != null )
1965                         {
1966                             vendor = classpathImpl.getPackage().getImplementationVendor();
1967                             version = classpathImpl.getPackage().getImplementationVersion();
1968                         }
1969 
1970                         implementation = new Implementation();
1971                         implementation.setVendor( vendor );
1972                         implementation.setFinal( true );
1973                         implementation.setName( name );
1974                         implementation.setIdentifier( specification.getIdentifier() );
1975                         implementation.setClazz( classpathImpl.getName() );
1976                         implementation.setVersion( version );
1977 
1978                         final Specifications implemented = new Specifications();
1979                         final SpecificationReference ref = new SpecificationReference();
1980                         ref.setIdentifier( specification.getIdentifier() );
1981                         ref.setVersion( specification.getVersion() );
1982                         implemented.getReference().add( ref );
1983                         implementation.setSpecifications( implemented );
1984 
1985                         if ( cpModule.getImplementations() == null )
1986                         {
1987                             cpModule.setImplementations( new Implementations() );
1988                         }
1989 
1990                         cpModule.getImplementations().getImplementation().add( implementation );
1991                     }
1992                 }
1993             }
1994             catch ( final ClassNotFoundException e )
1995             {
1996                 classpathImplementation = false;
1997             }
1998         }
1999 
2000         return classpathImplementation;
2001     }
2002 
2003     private boolean checkFactoryMethod( final Class<?> clazz, final Class<?> type, final String methodName )
2004     {
2005         boolean factoryMethod = false;
2006 
2007         try
2008         {
2009             final java.lang.reflect.Method m = clazz.getMethod( methodName, (Class[]) null );
2010             factoryMethod = java.lang.reflect.Modifier.isStatic( m.getModifiers() )
2011                             && type.isAssignableFrom( m.getReturnType() );
2012 
2013         }
2014         catch ( final NoSuchMethodException e )
2015         {
2016             factoryMethod = false;
2017         }
2018 
2019         return factoryMethod;
2020     }
2021 
2022     private static String getMessage( final String key, final Object... args )
2023     {
2024         return java.text.MessageFormat.format( java.util.ResourceBundle.getBundle(
2025             Modules.class.getName().replace( '.', '/' ), java.util.Locale.getDefault() ).
2026             getString( key ), args );
2027 
2028     }
2029       
2030 }