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