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