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.04.01 at 02:39:59 AM CEST 
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-04-01T02:39:59+02: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-04-01T02:39:59+02: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-04-01T02:39:59+02: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-04-01T02:39:59+02: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-04-01T02:39:59+02: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                 object = clazz.newInstance();
1341 
1342                 synchronized ( this.objects )
1343                 {
1344                     this.objects.put( object, instance );
1345                 }
1346             }
1347             else
1348             {
1349                 java.lang.reflect.Method factoryMethod = instance.getJavaFactoryMethod( classLoader );
1350 
1351                 if ( factoryMethod != null )
1352                 {
1353                     if ( java.lang.reflect.Modifier.isStatic( factoryMethod.getModifiers() ) )
1354                     {
1355                         object = factoryMethod.invoke( null, (Object[]) null );
1356 
1357                         if ( object != null )
1358                         {
1359                             synchronized ( this.objects )
1360                             {
1361                                 this.objects.put( object, instance );
1362                             }
1363                         }
1364                     }
1365                     else if ( ctor != null )
1366                     {
1367                         final Object o = ctor.newInstance();
1368 
1369                         synchronized ( this.objects )
1370                         {
1371                             this.objects.put( o, instance );
1372                         }
1373 
1374                         try
1375                         {
1376                             object = factoryMethod.invoke( o, (Object[]) null );
1377                         }
1378                         finally
1379                         {
1380                             synchronized ( this.objects )
1381                             {
1382                                 this.objects.remove( o );
1383 
1384                                 if ( object != null )
1385                                 {
1386                                     this.objects.put( object, instance );
1387                                 }
1388                             }
1389                         }
1390                     }
1391                 }
1392             }
1393 
1394             if ( object == null )
1395             {
1396                 throw new InstantiationException( getMessage(
1397                     instance.getJavaFactoryMethodName() != null
1398                     ? "failedCreatingObjectWithMethod" : "failedCreatingObject",
1399                     instance.getIdentifier(), clazz.getName(), instance.getJavaFactoryMethodName() ) );
1400 
1401             }
1402 
1403             return object;
1404         }
1405         catch ( final java.lang.reflect.InvocationTargetException e )
1406         {
1407             final Throwable target = e.getTargetException() != null ? e.getTargetException() : e;
1408             throw (InstantiationException) new InstantiationException(
1409                 getMessage( "exceptionCreatingObject", instance.getIdentifier() ) ).initCause( target );
1410 
1411         }
1412         catch ( final IllegalAccessException e )
1413         {
1414             throw (InstantiationException) new InstantiationException(
1415                 getMessage( "exceptionCreatingObject", instance.getIdentifier() ) ).initCause( e );
1416 
1417         }
1418         catch ( final ClassNotFoundException e )
1419         {
1420             throw (InstantiationException) new InstantiationException(
1421                 getMessage( "exceptionCreatingObject", instance.getIdentifier() ) ).initCause( e );
1422 
1423         }
1424     }
1425 
1426     /** @since 1.2 */
1427     private void collectModelObjects( final Implementation implementation, final Dependencies dependencies,
1428                                       final Messages messages, final Properties properties,
1429                                       final Specifications specifications, final List<Object> any,
1430                                       final java.util.Set<String> seen, final boolean includeDeclared )
1431     {
1432         if ( implementation != null && !seen.contains( implementation.getIdentifier() ) )
1433         {
1434             seen.add( implementation.getIdentifier() );
1435 
1436             if ( includeDeclared )
1437             {
1438                 if ( dependencies != null && implementation.getDependencies() != null )
1439                 {
1440                     for ( int i = 0, s0 = implementation.getDependencies().getDependency().size(); i < s0; i++ )
1441                     {
1442                         final Dependency d = implementation.getDependencies().getDependency().get( i );
1443                         final Dependency dependency = dependencies.getDependency( d.getName() );
1444 
1445                         if ( dependency == null )
1446                         {
1447                             dependencies.getDependency().add( d );
1448                         }
1449                         else
1450                         {
1451                             this.collectDependencies( d, dependency );
1452                         }
1453                     }
1454                 }
1455 
1456                 if ( messages != null && implementation.getMessages() != null )
1457                 {
1458                     for ( int i = 0, s0 = implementation.getMessages().getMessage().size(); i < s0; i++ )
1459                     {
1460                         final Message msg = implementation.getMessages().getMessage().get( i );
1461 
1462                         if ( messages.getMessage( msg.getName() ) == null )
1463                         {
1464                             messages.getMessage().add( msg );
1465                         }
1466                     }
1467 
1468                     if ( !implementation.getMessages().getReference().isEmpty() )
1469                     {
1470                         final Module m = this.getModuleOfImplementation( implementation.getIdentifier() );
1471 
1472                         if ( m != null )
1473                         {
1474                             for ( int i = 0, s0 = implementation.getMessages().getReference().size(); i < s0; i++ )
1475                             {
1476                                 final MessageReference ref = implementation.getMessages().getReference().get( i );
1477 
1478                                 if ( messages.getMessage( ref.getName() ) == null )
1479                                 {
1480                                     Message referenced = m.getMessages().getMessage( ref.getName() );
1481                                     if ( referenced != null )
1482                                     {
1483                                         referenced = referenced.clone();
1484                                         referenced.setDeprecated( ref.isDeprecated() );
1485                                         referenced.setFinal( ref.isFinal() );
1486                                         referenced.setOverride( ref.isOverride() );
1487                                         messages.getMessage().add( referenced );
1488                                     }
1489                                 }
1490                             }
1491                         }
1492                     }
1493                 }
1494 
1495                 if ( properties != null && implementation.getProperties() != null )
1496                 {
1497                     for ( int i = 0, s0 = implementation.getProperties().getProperty().size(); i < s0; i++ )
1498                     {
1499                         final Property p = implementation.getProperties().getProperty().get( i );
1500 
1501                         if ( properties.getProperty( p.getName() ) == null )
1502                         {
1503                             properties.getProperty().add( p );
1504                         }
1505                     }
1506 
1507                     if ( !implementation.getProperties().getReference().isEmpty() )
1508                     {
1509                         final Module m = this.getModuleOfImplementation( implementation.getIdentifier() );
1510 
1511                         if ( m != null )
1512                         {
1513                             for ( int i = 0, s0 = implementation.getProperties().getReference().size(); i < s0; i++ )
1514                             {
1515                                 final PropertyReference ref = implementation.getProperties().getReference().get( i );
1516 
1517                                 if ( properties.getProperty( ref.getName() ) == null )
1518                                 {
1519                                     Property referenced = m.getProperties().getProperty( ref.getName() );
1520                                     if ( referenced != null )
1521                                     {
1522                                         referenced = referenced.clone();
1523                                         referenced.setDeprecated( ref.isDeprecated() );
1524                                         referenced.setFinal( ref.isFinal() );
1525                                         referenced.setOverride( ref.isOverride() );
1526                                         properties.getProperty().add( referenced );
1527                                     }
1528                                 }
1529                             }
1530                         }
1531                     }
1532                 }
1533 
1534                 if ( specifications != null && implementation.getSpecifications() != null )
1535                 {
1536                     for ( int i = 0, s0 = implementation.getSpecifications().getReference().size(); i < s0; i++ )
1537                     {
1538                         final SpecificationReference r = implementation.getSpecifications().getReference().get( i );
1539 
1540                         if ( specifications.getReference( r.getIdentifier() ) == null )
1541                         {
1542                             specifications.getReference().add( r );
1543 
1544                             final Specification s = this.getSpecification( r.getIdentifier() );
1545                             if ( s != null && specifications.getSpecification( s.getIdentifier() ) == null )
1546                             {
1547                                 specifications.getSpecification().add( s );
1548                             }
1549                         }
1550                     }
1551                 }
1552 
1553                 if ( any != null && !implementation.getAny().isEmpty() )
1554                 {
1555                     for ( int i = 0, s0 = implementation.getAny().size(); i < s0; i++ )
1556                     {
1557                         final Object o = implementation.getAny().get( i );
1558 
1559                         if ( o instanceof org.w3c.dom.Element )
1560                         {
1561                             if ( this.getElement( any, (org.w3c.dom.Element) o ) == null )
1562                             {
1563                                 any.add( o );
1564                             }
1565 
1566                             continue;
1567                         }
1568 
1569                         if ( o instanceof javax.xml.bind.JAXBElement<?> )
1570                         {
1571                             if ( this.getElement( any, (javax.xml.bind.JAXBElement<?>) o ) == null )
1572                             {
1573                                 any.add( o );
1574                             }
1575 
1576                             continue;
1577                         }
1578 
1579                         any.add( o );
1580                     }
1581                 }
1582             }
1583 
1584             if ( implementation.getImplementations() != null )
1585             {
1586                 for ( int i = 0, s0 = implementation.getImplementations().getReference().size(); i < s0; i++ )
1587                 {
1588                     final ImplementationReference r = implementation.getImplementations().getReference().get( i );
1589                     this.collectModelObjects( this.getImplementation( r.getIdentifier() ), dependencies, messages,
1590                                               properties, specifications, any, seen, true );
1591 
1592                 }
1593             }
1594         }
1595     }
1596 
1597     /** @since 1.2 */
1598     private void collectClassDeclarationModelObjects( final Implementation implementation,
1599                                                       final Dependencies dependencies, final Messages messages,
1600                                                       final Properties properties, final Specifications specifications,
1601                                                       final List<Object> any )
1602     {
1603         Implementation declaration = null;
1604 
1605         if ( implementation != null && implementation.getClazz() != null && !implementation.isClassDeclaration() )
1606         {
1607             for ( int i = 0, s0 = this.getModule().size(); i < s0; i++ )
1608             {
1609                 final Module m = this.getModule().get( i );
1610 
1611                 if ( m.getImplementations() != null )
1612                 {
1613                     for ( int j = 0, s1 = m.getImplementations().getImplementation().size(); j < s1; j++ )
1614                     {
1615                         final Implementation current = m.getImplementations().getImplementation().get( j );
1616 
1617                         if ( current.getClazz() != null && current.getClazz().equals( implementation.getClazz() )
1618                              && current.isClassDeclaration() )
1619                         {
1620                             declaration = current;
1621                             break;
1622                         }
1623                     }
1624                 }
1625             }
1626         }
1627 
1628         if ( declaration != null )
1629         {
1630             this.collectModelObjects( declaration, dependencies, messages, properties, specifications, any,
1631                                       new java.util.HashSet<String>(), true );
1632 
1633         }
1634     }
1635 
1636     /** @since 1.2 */
1637     private void collectSpecifiedModelObjects( final Specifications specifications, final Properties properties )
1638     {
1639         for ( int i = 0, s0 = specifications.getSpecification().size(); i < s0; i++ )
1640         {
1641             final Specification s = specifications.getSpecification().get( i );
1642 
1643             if ( s.getProperties() != null )
1644             {
1645                 for ( int j = 0, s1 = s.getProperties().getProperty().size(); j < s1; j++ )
1646                 {
1647                     final Property p = s.getProperties().getProperty().get( j );
1648 
1649                     if ( properties.getProperty( p.getName() ) == null )
1650                     {
1651                         properties.getProperty().add( p );
1652                     }
1653                 }
1654             }
1655         }
1656     }
1657 
1658     private void collectDependencies( final Dependency source, final Dependency target )
1659     {
1660         if ( source.getMessages() != null )
1661         {
1662             if ( target.getMessages() == null )
1663             {
1664                 target.setMessages( new Messages() );
1665             }
1666 
1667             for ( int i = 0, s0 = source.getMessages().getMessage().size(); i < s0; i++ )
1668             {
1669                 final Message m = source.getMessages().getMessage().get( i );
1670 
1671                 if ( target.getMessages().getMessage( m.getName() ) == null )
1672                 {
1673                     target.getMessages().getMessage().add( m );
1674                 }
1675             }
1676         }
1677 
1678         if ( source.getProperties() != null )
1679         {
1680             if ( target.getProperties() == null )
1681             {
1682                 target.setProperties( new Properties() );
1683             }
1684 
1685             for ( int i = 0, s0 = source.getProperties().getProperty().size(); i < s0; i++ )
1686             {
1687                 final Property p = source.getProperties().getProperty().get( i );
1688 
1689                 if ( target.getProperties().getProperty( p.getName() ) == null )
1690                 {
1691                     target.getProperties().getProperty().add( p );
1692                 }
1693             }
1694         }
1695 
1696         if ( source.getDependencies() != null )
1697         {
1698             if ( target.getDependencies() == null )
1699             {
1700                 target.setDependencies( new Dependencies() );
1701             }
1702 
1703             for ( int i = 0, s0 = source.getDependencies().getDependency().size(); i < s0; i++ )
1704             {
1705                 final Dependency sd = source.getDependencies().getDependency().get( i );
1706                 final Dependency td = target.getDependencies().getDependency( sd.getName() );
1707 
1708                 if ( td == null )
1709                 {
1710                     target.getDependencies().getDependency().add( sd );
1711                 }
1712                 else
1713                 {
1714                     this.collectDependencies( sd, td );
1715                 }
1716             }
1717         }
1718     }
1719 
1720     private Implementation collectImplementation( final Class<?> clazz )
1721     {
1722         Implementation i = this.getImplementation( clazz );
1723         if ( i == null && clazz.getSuperclass() != null )
1724         {
1725             i = this.collectImplementation( clazz.getSuperclass() );
1726         }
1727 
1728         return i;
1729     }
1730 
1731     private org.w3c.dom.Element getElement( final List<Object> list, final org.w3c.dom.Element e )
1732     {
1733         for ( int i = 0, s0 = list.size(); i < s0; i++ )
1734         {
1735             final Object o = list.get( i );
1736 
1737             if ( o instanceof org.w3c.dom.Element )
1738             {
1739                 final org.w3c.dom.Element current = (org.w3c.dom.Element) o;
1740                 if ( ( e.getNamespaceURI() == null
1741                        ? current.getNamespaceURI() == null
1742                        : e.getNamespaceURI().equals( current.getNamespaceURI() ) )
1743                      && ( e.getLocalName() == null
1744                           ? current.getLocalName() == null
1745                           : e.getLocalName().equals( current.getLocalName() ) ) )
1746                 {
1747                     return current;
1748                 }
1749             }
1750         }
1751 
1752         return null;
1753     }
1754 
1755     private javax.xml.bind.JAXBElement<?> getElement( final List<Object> list, final javax.xml.bind.JAXBElement<?> e )
1756     {
1757         for ( int i = 0, s0 = list.size(); i < s0; i++ )
1758         {
1759             final Object o = list.get( i );
1760 
1761             if ( o instanceof javax.xml.bind.JAXBElement<?> )
1762             {
1763                 final javax.xml.bind.JAXBElement<?> current = (javax.xml.bind.JAXBElement<?>) o;
1764                 if ( e.getName().equals( current.getName() ) )
1765                 {
1766                     return current;
1767                 }
1768             }
1769         }
1770 
1771         return null;
1772     }
1773 
1774     private void resolveClasspath( final Module cpModule, final ClassLoader classLoader )
1775     {
1776         for ( int i = 0, s0 = this.getModule().size(); i < s0; i++ )
1777         {
1778             final Module m = this.getModule().get( i );
1779 
1780             if ( m.getSpecifications() != null )
1781             {
1782                 this.resolveClasspath( m.getSpecifications(), cpModule, classLoader );
1783             }
1784 
1785             if ( m.getImplementations() != null )
1786             {
1787                 this.resolveClasspath( m.getImplementations(), cpModule, classLoader );
1788             }
1789         }
1790     }
1791 
1792     private void resolveClasspath( final SpecificationReference ref, final Module cpModule,
1793                                    final ClassLoader classLoader )
1794     {
1795         if ( this.getSpecification( ref.getIdentifier() ) == null )
1796         {
1797             this.resolveClasspath( ref.getIdentifier(), cpModule, classLoader );
1798         }
1799     }
1800 
1801     private void resolveClasspath( final Specifications specifications, final Module cpModule,
1802                                    final ClassLoader classLoader )
1803     {
1804         for ( int i = 0, s0 = specifications.getSpecification().size(); i < s0; i++ )
1805         {
1806             final Specification s = specifications.getSpecification().get( i );
1807 
1808             if ( s.getClazz() != null )
1809             {
1810                 this.resolveClasspath( s, cpModule, classLoader );
1811             }
1812         }
1813         for ( int i = 0, s0 = specifications.getReference().size(); i < s0; i++ )
1814         {
1815             final SpecificationReference ref = specifications.getReference().get( i );
1816             this.resolveClasspath( ref, cpModule, classLoader );
1817         }
1818     }
1819 
1820     private void resolveClasspath( final Implementations implementations, final Module cpModule,
1821                                    final ClassLoader classLoader )
1822     {
1823         for ( int i = 0, s0 = implementations.getImplementation().size(); i < s0; i++ )
1824         {
1825             final Implementation implementation = implementations.getImplementation().get( i );
1826 
1827             if ( implementation.getSpecifications() != null )
1828             {
1829                 this.resolveClasspath( implementation.getSpecifications(), cpModule, classLoader );
1830             }
1831 
1832             if ( implementation.getDependencies() != null )
1833             {
1834                 this.resolveClasspath( implementation.getDependencies(), cpModule, classLoader );
1835             }
1836         }
1837     }
1838 
1839     private void resolveClasspath( final Dependencies dependencies, final Module cpModule,
1840                                    final ClassLoader classLoader )
1841     {
1842         for ( int i = 0, s0 = dependencies.getDependency().size(); i < s0; i++ )
1843         {
1844             final Dependency dependency = dependencies.getDependency().get( i );
1845             this.resolveClasspath( dependency, cpModule, classLoader );
1846 
1847             if ( dependency.getDependencies() != null )
1848             {
1849                 this.resolveClasspath( dependency.getDependencies(), cpModule, classLoader );
1850             }
1851         }
1852     }
1853 
1854     private boolean resolveClasspath( final String identifier, final Module cpModule, final ClassLoader classLoader )
1855     {
1856         boolean classpathSpecification = false;
1857         Specification specification = cpModule.getSpecifications() == null
1858                                       ? null : cpModule.getSpecifications().getSpecification( identifier );
1859 
1860         if ( specification == null )
1861         {
1862             try
1863             {
1864                 final Class<?> classpathSpec = Class.forName( identifier, false, classLoader );
1865                 if ( java.lang.reflect.Modifier.isPublic( classpathSpec.getModifiers() ) )
1866                 {
1867                     classpathSpecification = true;
1868                     String vendor = null;
1869                     String version = null;
1870 
1871                     if ( classpathSpec.getPackage() != null )
1872                     {
1873                         vendor = classpathSpec.getPackage().getSpecificationVendor();
1874                         version = classpathSpec.getPackage().getSpecificationVersion();
1875                     }
1876 
1877                     specification = new Specification();
1878                     specification.setIdentifier( identifier );
1879                     specification.setClazz( classpathSpec.getName() );
1880                     specification.setMultiplicity( Multiplicity.MANY );
1881                     specification.setVendor( vendor );
1882                     specification.setVersion( version );
1883 
1884                     if ( cpModule.getSpecifications() == null )
1885                     {
1886                         cpModule.setSpecifications( new Specifications() );
1887                     }
1888 
1889                     cpModule.getSpecifications().getSpecification().add( specification );
1890 
1891                     this.resolveClasspath( specification, cpModule, classLoader );
1892                 }
1893             }
1894             catch ( final ClassNotFoundException e )
1895             {
1896                 classpathSpecification = false;
1897             }
1898         }
1899 
1900         return classpathSpecification;
1901     }
1902 
1903     private boolean resolveClasspath( final Specification specification, final Module cpModule,
1904                                       final ClassLoader classLoader )
1905     {
1906         boolean classpathImplementation = false;
1907         Implementation implementation =
1908             cpModule.getImplementations() == null ? null
1909             : cpModule.getImplementations().getImplementation( specification.getIdentifier() );
1910 
1911         if ( implementation == null )
1912         {
1913             implementation = this.getImplementation( specification.getIdentifier() );
1914         }
1915 
1916         if ( implementation == null )
1917         {
1918             String name = null;
1919 
1920             try
1921             {
1922                 final Class<?> classpathImpl = Class.forName( specification.getClazz(), false, classLoader );
1923 
1924                 if ( java.lang.reflect.Modifier.isPublic( classpathImpl.getModifiers() ) )
1925                 {
1926                     if ( !java.lang.reflect.Modifier.isAbstract( classpathImpl.getModifiers() ) )
1927                     {
1928                         try
1929                         {
1930                             classpathImpl.getConstructor( NO_CLASSES );
1931                             name = "init";
1932                             classpathImplementation = true;
1933                         }
1934                         catch ( final NoSuchMethodException e )
1935                         {
1936                             classpathImplementation = false;
1937                         }
1938                     }
1939 
1940                     if ( !classpathImplementation )
1941                     {
1942                         final char[] c = classpathImpl.getName().substring(
1943                             classpathImpl.getPackage().getName().length() + 1 ).toCharArray();
1944 
1945                         name = String.valueOf( c );
1946                         c[0] = Character.toUpperCase( c[0] );
1947 
1948                         if ( this.checkFactoryMethod( classpathImpl, classpathImpl, "getDefault" ) )
1949                         {
1950                             name = "default";
1951                             classpathImplementation = true;
1952                         }
1953                         else if ( this.checkFactoryMethod( classpathImpl, classpathImpl, "getInstance" ) )
1954                         {
1955                             name = "instance";
1956                             classpathImplementation = true;
1957                         }
1958                         else if ( this.checkFactoryMethod( classpathImpl, classpathImpl, "get" + String.valueOf( c ) ) )
1959                         {
1960                             classpathImplementation = true;
1961                         }
1962 
1963                     }
1964 
1965                     if ( classpathImplementation
1966                          && this.getImplementation( specification.getIdentifier(), name ) == null )
1967                     {
1968                         String vendor = null;
1969                         String version = null;
1970                         if ( classpathImpl.getPackage() != null )
1971                         {
1972                             vendor = classpathImpl.getPackage().getImplementationVendor();
1973                             version = classpathImpl.getPackage().getImplementationVersion();
1974                         }
1975 
1976                         implementation = new Implementation();
1977                         implementation.setVendor( vendor );
1978                         implementation.setFinal( true );
1979                         implementation.setName( name );
1980                         implementation.setIdentifier( specification.getIdentifier() );
1981                         implementation.setClazz( classpathImpl.getName() );
1982                         implementation.setVersion( version );
1983 
1984                         final Specifications implemented = new Specifications();
1985                         final SpecificationReference ref = new SpecificationReference();
1986                         ref.setIdentifier( specification.getIdentifier() );
1987                         ref.setVersion( specification.getVersion() );
1988                         implemented.getReference().add( ref );
1989                         implementation.setSpecifications( implemented );
1990 
1991                         if ( cpModule.getImplementations() == null )
1992                         {
1993                             cpModule.setImplementations( new Implementations() );
1994                         }
1995 
1996                         cpModule.getImplementations().getImplementation().add( implementation );
1997                     }
1998                 }
1999             }
2000             catch ( final ClassNotFoundException e )
2001             {
2002                 classpathImplementation = false;
2003             }
2004         }
2005 
2006         return classpathImplementation;
2007     }
2008 
2009     private boolean checkFactoryMethod( final Class<?> clazz, final Class<?> type, final String methodName )
2010     {
2011         boolean factoryMethod = false;
2012 
2013         try
2014         {
2015             final java.lang.reflect.Method m = clazz.getMethod( methodName, (Class[]) null );
2016             factoryMethod = java.lang.reflect.Modifier.isStatic( m.getModifiers() )
2017                             && type.isAssignableFrom( m.getReturnType() );
2018 
2019         }
2020         catch ( final NoSuchMethodException e )
2021         {
2022             factoryMethod = false;
2023         }
2024 
2025         return factoryMethod;
2026     }
2027 
2028     private static String getMessage( final String key, final Object... args )
2029     {
2030         return java.text.MessageFormat.format( java.util.ResourceBundle.getBundle(
2031             Modules.class.getName().replace( '.', '/' ), java.util.Locale.getDefault() ).
2032             getString( key ), args );
2033 
2034     }
2035       
2036 }