001    //
002    // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vhudson-jaxb-ri-2.1-2 
003    // See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
004    // Any modifications to this file will be lost upon recompilation of the source schema. 
005    // Generated on: 2012.03.14 at 10:22:27 AM CET 
006    //
007    
008    
009    package org.jomc.model;
010    
011    import java.util.ArrayList;
012    import java.util.Iterator;
013    import java.util.List;
014    import javax.annotation.Generated;
015    import javax.xml.bind.annotation.XmlAccessType;
016    import javax.xml.bind.annotation.XmlAccessorType;
017    import javax.xml.bind.annotation.XmlElement;
018    import javax.xml.bind.annotation.XmlType;
019    
020    
021    /**
022     * List of modules.
023     * 
024     * <p>Java class for Modules complex type.
025     * 
026     * <p>The following schema fragment specifies the expected content contained within this class.
027     * 
028     * <pre>
029     * &lt;complexType name="Modules">
030     *   &lt;complexContent>
031     *     &lt;extension base="{http://jomc.org/model}ModelObject">
032     *       &lt;sequence>
033     *         &lt;element ref="{http://jomc.org/model}module" maxOccurs="unbounded" minOccurs="0"/>
034     *       &lt;/sequence>
035     *     &lt;/extension>
036     *   &lt;/complexContent>
037     * &lt;/complexType>
038     * </pre>
039     * 
040     * 
041     */
042    @XmlAccessorType(XmlAccessType.FIELD)
043    @XmlType(name = "Modules", namespace = "http://jomc.org/model", propOrder = {
044        "module"
045    })
046    @Generated(value = "com.sun.tools.xjc.Driver", date = "2012-03-14T10:22:27+01:00", comments = "JAXB RI vhudson-jaxb-ri-2.1-2")
047    public class Modules
048        extends ModelObject
049        implements Cloneable
050    {
051    
052        @XmlElement(namespace = "http://jomc.org/model")
053        @Generated(value = "com.sun.tools.xjc.Driver", date = "2012-03-14T10:22:27+01:00", comments = "JAXB RI vhudson-jaxb-ri-2.1-2")
054        protected List<Module> module;
055    
056        /**
057         * Creates a new {@code Modules} instance.
058         * 
059         */
060        public Modules() {
061            // CC-XJC Version 2.0 Build 2011-09-16T18:27:24+0000
062            super();
063        }
064    
065        /**
066         * Creates a new {@code Modules} instance by deeply copying a given {@code Modules} instance.
067         * 
068         * 
069         * @param o
070         *     The instance to copy.
071         * @throws NullPointerException
072         *     if {@code o} is {@code null}.
073         */
074        public Modules(final Modules o) {
075            // CC-XJC Version 2.0 Build 2011-09-16T18:27:24+0000
076            super(o);
077            if (o == null) {
078                throw new NullPointerException("Cannot create a copy of 'Modules' from 'null'.");
079            }
080            // 'Module' collection.
081            if (o.module!= null) {
082                copyModule(o.getModule(), this.getModule());
083            }
084        }
085    
086        /**
087         * Gets the value of the module property.
088         * 
089         * <p>
090         * This accessor method returns a reference to the live list,
091         * not a snapshot. Therefore any modification you make to the
092         * returned list will be present inside the JAXB object.
093         * This is why there is not a <CODE>set</CODE> method for the module property.
094         * 
095         * <p>
096         * For example, to add a new item, do as follows:
097         * <pre>
098         *    getModule().add(newItem);
099         * </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    }