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.04.01 at 02:39:59 AM CEST 
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-04-01T02:39:59+02: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-04-01T02:39:59+02: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-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    }