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