EMMA Coverage Report (generated Tue Jan 14 02:29:45 CET 2014)
[all classes][org.jdtaus.core.container.ri.client]

COVERAGE SUMMARY FOR SOURCE FILE [DefaultModel.java]

nameclass, %method, %block, %line, %
DefaultModel.java100% (4/4)83%  (38/46)74%  (3369/4572)75%  (644.3/862)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class DefaultModel$2100% (1/1)25%  (1/4)11%  (9/83)20%  (1/5)
error (TransformerException): void 0%   (0/1)0%   (0/25)0%   (0/1)
fatalError (TransformerException): void 0%   (0/1)0%   (0/25)0%   (0/1)
warning (TransformerException): void 0%   (0/1)0%   (0/24)0%   (0/2)
DefaultModel$2 (DefaultModel, URL): void 100% (1/1)100% (9/9)100% (1/1)
     
class DefaultModel$1100% (1/1)50%  (2/4)42%  (32/77)40%  (2/5)
fatalError (SAXParseException): void 0%   (0/1)0%   (0/23)0%   (0/1)
warning (SAXParseException): void 0%   (0/1)0%   (0/22)0%   (0/2)
DefaultModel$1 (DefaultModel, URL): void 100% (1/1)100% (9/9)100% (1/1)
error (SAXParseException): void 100% (1/1)100% (23/23)100% (1/1)
     
class DefaultModel100% (1/1)92%  (33/36)75%  (3314/4398)75%  (639.3/850)
addDefaultImplementation (Class, Specification): void 0%   (0/1)0%   (0/192)0%   (0/44)
addPlatformSpecification (String, boolean): boolean 0%   (0/1)0%   (0/167)0%   (0/45)
isPlatformSpecification (String): boolean 0%   (0/1)0%   (0/5)0%   (0/1)
updatePropertyValue (String, String, Property): void 100% (1/1)63%  (337/534)64%  (49/77)
transformDocuments (Map): Modules 100% (1/1)65%  (261/400)75%  (64.8/86)
assertOverwrittenProperties (): void 100% (1/1)66%  (76/115)68%  (15/22)
assertImplementedProperties (): void 100% (1/1)69%  (117/169)73%  (22/30)
assertSpecificationsAvailable (): void 100% (1/1)73%  (62/85)65%  (11/17)
transformMessage (String, String, String, Element): Message 100% (1/1)75%  (128/171)76%  (26.5/35)
assertCompatibility (): void 100% (1/1)76%  (134/176)71%  (24/34)
DefaultModel (): void 100% (1/1)77%  (121/157)70%  (28/40)
transformArgument (String, String, Element): Argument 100% (1/1)78%  (57/73)81%  (13/16)
readModules (): Modules 100% (1/1)82%  (79/96)83%  (20/24)
transformProperty (String, String, Element): Property 100% (1/1)83%  (69/83)92%  (12.9/14)
transformModule (String, String, Element, URL): Module 100% (1/1)84%  (193/230)86%  (33.5/39)
<static initializer> 100% (1/1)88%  (70/80)92%  (5.5/6)
transformSpecification (String, String, Element): Specification 100% (1/1)88%  (153/173)93%  (31.8/34)
linkParentImplementations (): void 100% (1/1)89%  (41/46)92%  (12/13)
transformDependency (String, String, String, Element): Dependency 100% (1/1)92%  (133/144)95%  (24.6/26)
linkImplementedSpecifications (): void 100% (1/1)94%  (79/84)99%  (17.8/18)
updateSpecificationReferences (): void 100% (1/1)95%  (89/94)99%  (18.8/19)
transformImplementation (String, String, Module, Element): Implementation 100% (1/1)97%  (296/304)98%  (51.1/52)
getSpecification (String, String): Specification 100% (1/1)98%  (62/63)100% (16.9/17)
getImplementation (String): Implementation 100% (1/1)100% (23/23)100% (6/6)
getModules (): Modules 100% (1/1)100% (3/3)100% (1/1)
getPlatformModule (): Module 100% (1/1)100% (42/42)100% (9/9)
linkDependencies (): void 100% (1/1)100% (56/56)100% (12/12)
transformArguments (String, String, Element): Arguments 100% (1/1)100% (70/70)100% (12/12)
transformDependencies (String, String, String, Element): Dependencies 100% (1/1)100% (69/69)100% (12/12)
transformImplementations (String, String, Module, Element): Implementations 100% (1/1)100% (69/69)100% (12/12)
transformMessages (String, String, Module, Element): Messages 100% (1/1)100% (107/107)100% (17/17)
transformModelObject (String, Element, ModelObject): void 100% (1/1)100% (37/37)100% (7/7)
transformProperties (String, String, Element): Properties 100% (1/1)100% (85/85)100% (16/16)
transformSpecificationReference (String, Element): Specification 100% (1/1)100% (22/22)100% (5/5)
transformSpecifications (String, String, Element): Specifications 100% (1/1)100% (108/108)100% (18/18)
transformText (String, Element): Text 100% (1/1)100% (66/66)100% (14/14)
     
class DefaultModel$3100% (1/1)100% (2/2)100% (14/14)100% (2/2)
DefaultModel$3 (DefaultModel): void 100% (1/1)100% (6/6)100% (1/1)
compare (Object, Object): int 100% (1/1)100% (8/8)100% (1/1)

1/*
2 *  jDTAUS Core RI Client Container
3 *  Copyright (C) 2005 Christian Schulte
4 *  <cs@schulte.it>
5 *
6 *  This library is free software; you can redistribute it and/or
7 *  modify it under the terms of the GNU Lesser General Public
8 *  License as published by the Free Software Foundation; either
9 *  version 2.1 of the License, or any later version.
10 *
11 *  This library is distributed in the hope that it will be useful,
12 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 *  Lesser General Public License for more details.
15 *
16 *  You should have received a copy of the GNU Lesser General Public
17 *  License along with this library; if not, write to the Free Software
18 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19 *
20 */
21package org.jdtaus.core.container.ri.client;
22 
23import java.beans.Beans;
24import java.io.IOException;
25import java.io.InputStream;
26import java.lang.reflect.Constructor;
27import java.lang.reflect.InvocationTargetException;
28import java.lang.reflect.Method;
29import java.lang.reflect.Modifier;
30import java.net.URI;
31import java.net.URISyntaxException;
32import java.net.URL;
33import java.text.MessageFormat;
34import java.text.ParseException;
35import java.util.Arrays;
36import java.util.Collection;
37import java.util.Collections;
38import java.util.Comparator;
39import java.util.Enumeration;
40import java.util.HashMap;
41import java.util.HashSet;
42import java.util.Iterator;
43import java.util.LinkedList;
44import java.util.List;
45import java.util.Locale;
46import java.util.Map;
47import java.util.Set;
48import java.util.TreeMap;
49import java.util.logging.Level;
50import java.util.logging.Logger;
51import javax.xml.parsers.DocumentBuilder;
52import javax.xml.parsers.DocumentBuilderFactory;
53import javax.xml.parsers.ParserConfigurationException;
54import javax.xml.transform.ErrorListener;
55import javax.xml.transform.Transformer;
56import javax.xml.transform.TransformerConfigurationException;
57import javax.xml.transform.TransformerException;
58import javax.xml.transform.TransformerFactory;
59import javax.xml.transform.dom.DOMResult;
60import javax.xml.transform.dom.DOMSource;
61import javax.xml.transform.stream.StreamSource;
62import org.jdtaus.core.container.Argument;
63import org.jdtaus.core.container.Arguments;
64import org.jdtaus.core.container.Dependencies;
65import org.jdtaus.core.container.Dependency;
66import org.jdtaus.core.container.DuplicateSpecificationException;
67import org.jdtaus.core.container.IllegalPropertyTypeException;
68import org.jdtaus.core.container.Implementation;
69import org.jdtaus.core.container.Implementations;
70import org.jdtaus.core.container.IncompatibleImplementationException;
71import org.jdtaus.core.container.Message;
72import org.jdtaus.core.container.Messages;
73import org.jdtaus.core.container.MissingImplementationException;
74import org.jdtaus.core.container.MissingPropertyException;
75import org.jdtaus.core.container.MissingSpecificationException;
76import org.jdtaus.core.container.Model;
77import org.jdtaus.core.container.ModelError;
78import org.jdtaus.core.container.ModelObject;
79import org.jdtaus.core.container.Module;
80import org.jdtaus.core.container.Modules;
81import org.jdtaus.core.container.Properties;
82import org.jdtaus.core.container.Property;
83import org.jdtaus.core.container.PropertyOverwriteConstraintException;
84import org.jdtaus.core.container.Specification;
85import org.jdtaus.core.container.Specifications;
86import org.jdtaus.core.container.Text;
87import org.jdtaus.core.container.ri.client.versioning.VersionParser;
88import org.w3c.dom.Document;
89import org.w3c.dom.Element;
90import org.w3c.dom.NodeList;
91import org.xml.sax.ErrorHandler;
92import org.xml.sax.SAXException;
93import org.xml.sax.SAXParseException;
94 
95/**
96 * {@code Model} reference implementation.
97 *
98 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
99 * @version $JDTAUS: DefaultModel.java 8853 2014-01-10 13:50:00Z schulte $
100 *
101 * @see <a href="http://xml.jdtaus.org/1.0.x/jdtaus-core/jdtaus-core-schemas/jdtaus-container-1.1.xsd">jdtaus-container-1.1.xsd</a>
102 */
103public class DefaultModel implements Model
104{
105    //--Constants---------------------------------------------------------------
106 
107    /** JAXP configuration key to the Schema implementation attribute. */
108    private static final String SCHEMA_LANGUAGE_KEY =
109        "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
110 
111    /** JAXP Schema implementation to use. */
112    private static final String SCHEMA_LANGUAGE =
113        "http://www.w3.org/2001/XMLSchema";
114 
115    /**
116     * jDTAUS {@code Model} namespace URI for the deprecated 1.0 and 1.1 model.
117     */
118    private static final String MODEL_NS =
119        "http://jdtaus.org/runtime/container/xml";
120 
121    /** {@code jDTAUS Container Model} namespace URI. */
122    private static final String CONTAINER_NS =
123        "http://jdtaus.org/core/model/container";
124 
125    /** {@code jDTAUS Container Model RI} namespace URI. */
126    private static final String MODULE_NS =
127        "http://jdtaus.org/core/model/container/module";
128 
129    /** Location of the document resources searched for by default. */
130    private static final String MODEL_LOCATION =
131        "META-INF/jdtaus/module.xml";
132 
133    /** Location of the transformation resources searched for by default. */
134    private static final String TRANSFORMATION_LOCATION =
135        "META-INF/jdtaus/container.xslt";
136 
137    /** Model versions supported by this implementation. */
138    private static final String[] SUPPORTED_MODEL_VERSIONS =
139    {
140        "1.0", "1.1", "1.2", "1.3", "1.4"
141    };
142 
143    /** String constructor arguments. */
144    private static final Class[] CTOR_ARGS_STRING =
145    {
146        String.class
147    };
148 
149    /** String constructor arguments. */
150    private static final Class[] CTOR_ARGS_CHAR =
151    {
152        char.class
153    };
154 
155    /** Constant for the name of the platform module. */
156    private static final String PLATFORM_MODULE_NAME = Model.class.getName();
157 
158    /** Constant for the version of the platform module. */
159    private static final String PLATFORM_MODULE_VERSION = "1.0";
160 
161    /** Constant for model version 1.1. */
162    private static final String V_1_1 = "1.1";
163 
164    /** Constant for model version 1.3. */
165    private static final String V_1_3 = "1.3";
166 
167    /** Constant for model version 1.4. */
168    private static final String V_1_4 = "1.4";
169 
170    /** Constant for the maximum supported model version. */
171    private static final String MODEL_VERSION = V_1_4;
172 
173    //---------------------------------------------------------------Constants--
174    //--Constructors------------------------------------------------------------
175 
176    /**
177     * Creates a new {@code DefaultModel} instance.
178     *
179     * @throws ModelError if no model can be read.
180     *
181     * @see #readModules()
182     */
183    public DefaultModel()
184    {
185        try
186        {
187            this.modules = this.readModules();
188            // Add the platform module.
189            final Module[] modulesWithPlatform =
190                new Module[ this.modules.size() + 1 ];
191 
192            System.arraycopy( this.modules.getModules(), 0, modulesWithPlatform,
193                              0, this.modules.size() );
194 
195            modulesWithPlatform[this.modules.size()] = this.getPlatformModule();
196            this.modules.setModules( modulesWithPlatform );
197 
198            this.linkParentImplementations();
199            this.assertSpecificationsAvailable();
200            this.updateSpecificationReferences();
201            this.linkImplementedSpecifications();
202            this.linkDependencies();
203            this.assertCompatibility();
204            this.assertOverwrittenProperties();
205            this.assertImplementedProperties();
206        }
207        catch ( final ParserConfigurationException e )
208        {
209            throw new ModelError( e );
210        }
211        catch ( final SAXException e )
212        {
213            throw new ModelError( e );
214        }
215        catch ( final IOException e )
216        {
217            throw new ModelError( e );
218        }
219        catch ( final ParseException e )
220        {
221            throw new ModelError( e );
222        }
223        catch ( final TransformerConfigurationException e )
224        {
225            throw new ModelError( e );
226        }
227        catch ( final TransformerException e )
228        {
229            throw new ModelError( e );
230        }
231        catch ( final URISyntaxException e )
232        {
233            throw new ModelError( e );
234        }
235        finally
236        {
237            this.specifications = null;
238            this.implementations = null;
239            this.dependencies = null;
240            this.impl2parent = null;
241            this.moduleMap = null;
242        }
243    }
244 
245    //------------------------------------------------------------Constructors--
246    //--Model-------------------------------------------------------------------
247 
248    public Modules getModules()
249    {
250        return this.modules;
251    }
252 
253    //-------------------------------------------------------------------Model--
254    //--DefaultModel------------------------------------------------------------
255 
256    /** Logger of the class. */
257    private static final Logger LOGGER =
258        Logger.getLogger( DefaultModel.class.getName() );
259 
260    /** Holds the instance of the platform module. */
261    private Module platformModule;
262 
263    /** Holds the loaded model. */
264    private Modules modules;
265 
266    /**
267     * Maps specification identifiers to a list of specification instances by
268     * version.
269     */
270    private Map/*<String,Collection>*/ specifications = new HashMap( 1000 );
271 
272    /** Maps implementation identifiers to implementation instances. */
273    private Map/*<String,Implementation>*/ implementations = new HashMap( 1000 );
274 
275    /**
276     * Maps identifiers of implementations to identifiers of parent
277     * implementations.
278     */
279    private Map/*<String,String>*/ impl2parent = new HashMap( 1000 );
280 
281    /** Maps dependency keys to implementation names. */
282    private Map/*<String,String>*/ dependencies = new HashMap( 1000 );
283 
284    /** Maps module names to resource URLs. */
285    private Map/*<String,URL>*/ moduleMap = new HashMap( 1000 );
286 
287    /**
288     * Reads the module resources.
289     *
290     * @return all read modules without resolved references.
291     *
292     * @throws IOException if reading fails.
293     * @throws ParserConfigurationException if configuring the parser fails.
294     * @throws SAXException if parsing documents fails.
295     * @throws ParseException if parsing versions fails.
296     * @throws TransformerException if creating a transformer fails or if
297     * transforming documents fails.
298     * @throws URISyntaxException if creating a resource URI fails.
299     */
300    private Modules readModules()
301        throws IOException, ParserConfigurationException, SAXException,
302               ParseException, TransformerException, URISyntaxException
303    {
304        final Map documents = new HashMap();
305        final DocumentBuilderFactory xmlFactory =
306            DocumentBuilderFactory.newInstance();
307 
308        final Enumeration resources = ClassLoaderFactory.loadResources(
309            this.getClass(), MODEL_LOCATION );
310 
311        xmlFactory.setNamespaceAware( true );
312 
313        try
314        {
315            xmlFactory.setValidating( true );
316            xmlFactory.setAttribute( SCHEMA_LANGUAGE_KEY, SCHEMA_LANGUAGE );
317        }
318        catch ( final IllegalArgumentException e )
319        {
320            LOGGER.log( Level.CONFIG, e.getMessage() );
321            LOGGER.log( Level.WARNING, DefaultModelBundle.getInstance().
322                getNoValidationWarningMessage( Locale.getDefault(),
323                                               e.getMessage() ) );
324 
325            xmlFactory.setValidating( false );
326        }
327 
328        final DocumentBuilder xmlBuilder = xmlFactory.newDocumentBuilder();
329        xmlBuilder.setEntityResolver( new BootstrapEntityResolver() );
330 
331        // Parse and validate all files from the classpath.
332        while ( resources.hasMoreElements() )
333        {
334            final URL resource = (URL) resources.nextElement();
335 
336            if ( LOGGER.isLoggable( Level.FINE ) )
337            {
338                LOGGER.log( Level.FINE, DefaultModelBundle.getInstance().
339                    getResourceInformationMessage(
340                    Locale.getDefault(), resource.toExternalForm() ) );
341 
342            }
343 
344            final InputStream stream = resource.openStream();
345            xmlBuilder.setErrorHandler(
346                new ErrorHandler()
347                {
348 
349                    public void warning( final SAXParseException e )
350                    {
351                        LOGGER.log( Level.WARNING,
352                                    DefaultModelBundle.getInstance().
353                            getParseExceptionMessage(
354                            Locale.getDefault(), resource.toExternalForm(),
355                            e.getMessage(), new Integer( e.getLineNumber() ),
356                            new Integer( e.getColumnNumber() ) ) );
357 
358                    }
359 
360                    public void fatalError( final SAXParseException e )
361                        throws SAXException
362                    {
363                        throw new SAXException(
364                            DefaultModelBundle.getInstance().
365                            getParseExceptionMessage(
366                            Locale.getDefault(), resource.toExternalForm(),
367                            e.getMessage(), new Integer( e.getLineNumber() ),
368                            new Integer( e.getColumnNumber() ) ), e );
369 
370                    }
371 
372                    public void error( final SAXParseException e )
373                        throws SAXException
374                    {
375                        throw new SAXException(
376                            DefaultModelBundle.getInstance().
377                            getParseExceptionMessage(
378                            Locale.getDefault(), resource.toExternalForm(),
379                            e.getMessage(), new Integer( e.getLineNumber() ),
380                            new Integer( e.getColumnNumber() ) ), e );
381 
382                    }
383 
384                } );
385 
386            final Document doc = xmlBuilder.parse( stream );
387            stream.close();
388            documents.put( new URI( resource.toString() ), doc );
389        }
390 
391        // Transform the XML documents.
392        return this.transformDocuments( documents );
393    }
394 
395    private void updateSpecificationReferences()
396    {
397        for ( int m = this.modules.size() - 1; m >= 0; m-- )
398        {
399            final Module module = this.modules.getModule( m );
400            for ( int s = module.getSpecifications().size() - 1; s >= 0; s-- )
401            {
402                final Specification spec = module.getSpecifications().
403                    getSpecification( s );
404 
405                final Collection references =
406                    (Collection) this.specifications.get( spec.getIdentifier() );
407 
408                assert references != null : "Expected specification meta-data.";
409 
410                for ( final Iterator it = references.iterator(); it.hasNext(); )
411                {
412                    final Specification reference = (Specification) it.next();
413                    reference.setModuleName( module.getName() );
414 
415                    if ( !reference.equals( spec ) )
416                    {
417                        reference.setDocumentation( spec.getDocumentation() );
418                        reference.setMultiplicity( spec.getMultiplicity() );
419                        reference.setProperties( spec.getProperties() );
420                        reference.setScope( spec.getScope() );
421                        reference.setStateless( spec.isStateless() );
422                        reference.setVendor( spec.getVendor() );
423                        reference.setModelVersion( spec.getModelVersion() );
424                    }
425                }
426            }
427        }
428    }
429 
430    private void linkParentImplementations()
431    {
432        for ( final Iterator it = this.implementations.entrySet().iterator();
433              it.hasNext(); )
434        {
435            final Map.Entry e = (Map.Entry) it.next();
436            final String identifier = (String) e.getKey();
437            final Implementation implementation = (Implementation) e.getValue();
438            final String parentIdentifier =
439                (String) this.impl2parent.get( identifier );
440 
441            if ( parentIdentifier != null )
442            {
443                final Implementation parent =
444                    (Implementation) this.implementations.get(
445                    parentIdentifier );
446 
447                if ( parent == null )
448                {
449                    throw new MissingImplementationException(
450                        parentIdentifier );
451 
452                }
453 
454                implementation.setParent( parent );
455            }
456        }
457    }
458 
459    private void linkImplementedSpecifications()
460    {
461        for ( final Iterator it = this.implementations.values().iterator();
462              it.hasNext(); )
463        {
464            final Implementation implementation = (Implementation) it.next();
465 
466            for ( int i = implementation.getImplementedSpecifications().
467                size() - 1; i >= 0; i-- )
468            {
469                final Specification implemented =
470                    implementation.getImplementedSpecifications().
471                    getSpecification( i );
472 
473                final Collection specs =
474                    (Collection) this.specifications.get(
475                    implemented.getIdentifier() );
476 
477                assert specs != null : "Expected specification meta-data.";
478 
479                for ( final Iterator s = specs.iterator(); s.hasNext(); )
480                {
481                    final Specification spec = (Specification) s.next();
482                    final Collection col = new LinkedList(
483                        Arrays.asList( spec.getImplementations().
484                        getImplementations() ) );
485 
486                    col.add( implementation );
487 
488                    final Implementations impls = new Implementations();
489                    impls.setImplementations(
490                        (Implementation[]) col.toArray(
491                        new Implementation[ col.size() ] ) );
492 
493                    spec.setImplementations( impls );
494                }
495            }
496        }
497    }
498 
499    private void linkDependencies()
500    {
501        for ( final Iterator it = this.implementations.values().iterator();
502              it.hasNext(); )
503        {
504            final Implementation implementation = (Implementation) it.next();
505            for ( int i = implementation.getDeclaredDependencies().size() - 1;
506                  i >= 0; i-- )
507            {
508                final Dependency d = implementation.getDeclaredDependencies().
509                    getDependency( i );
510 
511                final String key =
512                    implementation.getIdentifier() + '/' + d.getName();
513 
514                final String name = (String) this.dependencies.get( key );
515 
516                if ( name != null )
517                {
518                    d.setImplementation( d.getSpecification().
519                        getImplementation( name ) );
520 
521                }
522            }
523        }
524    }
525 
526    private void assertSpecificationsAvailable()
527    {
528        final Implementation[] impls = this.modules.getImplementations().
529            getImplementations();
530 
531        for ( int i = impls.length - 1; i >= 0; i-- )
532        {
533            final Specifications specs = impls[i].getImplementedSpecifications();
534            final Dependencies deps = impls[i].getDependencies();
535 
536            for ( int j = specs.size() - 1; j >= 0; j-- )
537            {
538                try
539                {
540                    this.modules.getSpecification(
541                        specs.getSpecification( j ).getIdentifier() );
542 
543                }
544                catch ( final MissingSpecificationException e )
545                {
546                    if ( !this.addPlatformSpecification(
547                        specs.getSpecification( j ).getIdentifier(), true ) )
548                    {
549                        throw e;
550                    }
551                }
552            }
553 
554            for ( int j = deps.size() - 1; j >= 0; j-- )
555            {
556                try
557                {
558                    this.modules.getSpecification(
559                        deps.getDependency( j ).getSpecification().
560                        getIdentifier() );
561 
562                }
563                catch ( final MissingSpecificationException e )
564                {
565                    if ( !this.addPlatformSpecification(
566                        deps.getDependency( j ).getSpecification().
567                        getIdentifier(), true ) )
568                    {
569                        throw e;
570                    }
571                }
572            }
573        }
574    }
575 
576    private void assertCompatibility() throws ParseException
577    {
578        for ( int i = this.modules.getImplementations().size() - 1; i >= 0;
579              i-- )
580        {
581            final Implementation impl = this.modules.getImplementations().
582                getImplementation( i );
583 
584            if ( impl.getModelVersion() == null ||
585                 VersionParser.compare( impl.getModelVersion(), V_1_3 ) < 0 )
586            {
587                continue;
588            }
589 
590            final Specifications specs = impl.getImplementedSpecifications();
591            final Dependencies deps = impl.getDependencies();
592 
593            for ( int s = specs.size() - 1; s >= 0; s-- )
594            {
595                final Specification implemented = specs.getSpecification( s );
596                final Specification available =
597                    this.modules.getSpecification( implemented.getIdentifier() );
598 
599                if ( available.getModelVersion() == null ||
600                     VersionParser.compare( available.getModelVersion(),
601                                            V_1_3 ) < 0 )
602                {
603                    continue;
604                }
605 
606                if ( implemented.getVersion() != null )
607                {
608                    try
609                    {
610                        if ( VersionParser.compare(
611                            implemented.getVersion(),
612                            available.getVersion() ) < 0 )
613                        {
614                            throw new IncompatibleImplementationException(
615                                available.getIdentifier(),
616                                available.getVersion(),
617                                impl.getIdentifier(), implemented.getVersion(),
618                                null );
619 
620                        }
621                    }
622                    catch ( final ParseException e )
623                    {
624                        final IncompatibleImplementationException iie =
625                            new IncompatibleImplementationException(
626                            available.getIdentifier(), available.getVersion(),
627                            impl.getIdentifier(), implemented.getVersion(),
628                            null );
629 
630                        iie.initCause( e );
631                        throw iie;
632                    }
633                }
634            }
635 
636            for ( int d = deps.size() - 1; d >= 0; d-- )
637            {
638                final Specification required =
639                    deps.getDependency( d ).getSpecification();
640 
641                final Specification available =
642                    this.modules.getSpecification( required.getIdentifier() );
643 
644                if ( available.getModelVersion() == null ||
645                     VersionParser.compare( available.getModelVersion(),
646                                            V_1_3 ) < 0 )
647                {
648                    continue;
649                }
650 
651                if ( required.getVersion() != null )
652                {
653                    try
654                    {
655                        if ( VersionParser.compare(
656                            available.getVersion(),
657                            required.getVersion() ) < 0 )
658                        {
659                            throw new IncompatibleImplementationException(
660                                available.getIdentifier(),
661                                available.getVersion(),
662                                impl.getIdentifier(), null,
663                                required.getVersion() );
664 
665                        }
666                    }
667                    catch ( final ParseException e )
668                    {
669                        final IncompatibleImplementationException iie =
670                            new IncompatibleImplementationException(
671                            available.getIdentifier(), available.getVersion(),
672                            impl.getIdentifier(), null, required.getVersion() );
673 
674                        iie.initCause( e );
675                        throw iie;
676                    }
677                }
678            }
679        }
680    }
681 
682    private void assertOverwrittenProperties() throws ParseException
683    {
684        for ( int i = this.modules.getImplementations().size() - 1; i >= 0;
685              i-- )
686        {
687            final Implementation impl = this.modules.getImplementations().
688                getImplementation( i );
689 
690            final Dependencies deps = impl.getDependencies();
691            for ( int d = deps.size() - 1; d >= 0; d-- )
692            {
693                final Dependency dep = deps.getDependency( d );
694                if ( dep.getSpecification().getScope() !=
695                     Specification.SCOPE_MULTITON &&
696                     dep.getDeclaredProperties().size() > 0 )
697                {
698                    throw new PropertyOverwriteConstraintException(
699                        impl.getIdentifier(), dep.getName() );
700 
701                }
702 
703                final Properties properties = dep.getDeclaredProperties();
704                for ( int p = properties.size() - 1; p >= 0; p-- )
705                {
706                    final Property dependencyProperty =
707                        properties.getProperty( p );
708 
709                    try
710                    {
711                        final Property specificationProperty =
712                            dep.getSpecification().getProperties().
713                            getProperty( dependencyProperty.getName() );
714 
715                        if ( !dependencyProperty.getType().
716                            equals( specificationProperty.getType() ) )
717                        {
718                            throw new IllegalPropertyTypeException(
719                                dependencyProperty.getName(),
720                                dependencyProperty.getType(),
721                                specificationProperty.getType() );
722 
723                        }
724 
725                        dependencyProperty.setApi( true );
726                    }
727                    catch ( final MissingPropertyException e )
728                    {
729                        if ( VersionParser.compare(
730                            dep.getSpecification().getModelVersion(),
731                            V_1_3 ) >= 0 )
732                        {
733                            final PropertyOverwriteConstraintException poce =
734                                new PropertyOverwriteConstraintException(
735                                impl.getIdentifier(), dep.getName() );
736 
737                            poce.initCause( e );
738                            throw poce;
739                        }
740                    }
741                }
742            }
743        }
744    }
745 
746    private void assertImplementedProperties() throws ParseException
747    {
748        for ( int i = this.modules.getImplementations().size() - 1; i >= 0;
749              i-- )
750        {
751            final Map properties = new HashMap( 100 );
752            final Implementation impl = this.modules.getImplementations().
753                getImplementation( i );
754 
755            final Specifications specs = impl.getImplementedSpecifications();
756            for ( int s = specs.size() - 1; s >= 0; s-- )
757            {
758                final Specification implementedSpec =
759                    specs.getSpecification( s );
760 
761                final Properties props = implementedSpec.getProperties();
762                for ( int p = props.size() - 1; p >= 0; p-- )
763                {
764                    final Property implementedProperty =
765                        props.getProperty( p );
766 
767                    final Property alreadyImplemented =
768                        (Property) properties.get(
769                        implementedProperty.getName() );
770 
771                    if ( alreadyImplemented != null )
772                    {
773                        if ( !implementedProperty.getType().
774                            equals( alreadyImplemented.getType() ) )
775                        {
776                            throw new IllegalPropertyTypeException(
777                                implementedProperty.getName(),
778                                implementedProperty.getType(),
779                                alreadyImplemented.getType() );
780 
781                        }
782                    }
783                    else
784                    {
785                        properties.put( implementedProperty.getName(),
786                                        implementedProperty );
787 
788                    }
789 
790                    try
791                    {
792                        final Property property =
793                            impl.getProperties().getProperty(
794                            implementedProperty.getName() );
795 
796                        if ( !property.getType().
797                            equals( implementedProperty.getType() ) )
798                        {
799                            throw new IllegalPropertyTypeException(
800                                property.getName(), property.getType(),
801                                implementedProperty.getType() );
802 
803                        }
804                    }
805                    catch ( final MissingPropertyException e )
806                    {
807                        if ( VersionParser.compare( impl.getModelVersion(),
808                                                    V_1_3 ) >= 0 )
809                        {
810                            final PropertyOverwriteConstraintException poce =
811                                new PropertyOverwriteConstraintException(
812                                impl.getIdentifier(),
813                                implementedSpec.getIdentifier(),
814                                implementedProperty.getName() );
815 
816                            poce.initCause( e );
817                            throw poce;
818                        }
819                    }
820                }
821            }
822 
823            for ( int p = impl.getProperties().size() - 1; p >= 0; p-- )
824            {
825                final Property property = impl.getProperties().getProperty( p );
826                final Property specified =
827                    (Property) properties.get( property.getName() );
828 
829                if ( specified != null &&
830                     !property.getType().equals( specified.getType() ) )
831                {
832                    throw new IllegalPropertyTypeException(
833                        property.getName(), property.getType(),
834                        specified.getType() );
835 
836                }
837            }
838        }
839    }
840 
841    private Specification getSpecification( final String identifier,
842                                            final String version )
843    {
844        Collection c = (Collection) this.specifications.get( identifier );
845        if ( c == null )
846        {
847            c = new LinkedList();
848            this.specifications.put( identifier, c );
849        }
850 
851        Specification specification = null;
852        for ( final Iterator it = c.iterator(); it.hasNext(); )
853        {
854            final Specification s = (Specification) it.next();
855 
856            if ( s.getVersion() == null
857                 ? version == null
858                 : s.getVersion().equals( version ) )
859            {
860                specification = s;
861                break;
862            }
863        }
864 
865        if ( specification == null )
866        {
867            specification = new Specification();
868            specification.setIdentifier( identifier );
869            specification.setVersion( version );
870            c.add( specification );
871        }
872 
873        return specification;
874    }
875 
876    private Implementation getImplementation( final String identifier )
877    {
878        Implementation implementation =
879            (Implementation) this.implementations.get( identifier );
880 
881        if ( implementation == null )
882        {
883            implementation = new Implementation();
884            implementation.setIdentifier( identifier );
885            this.implementations.put( identifier, implementation );
886        }
887 
888        return implementation;
889    }
890 
891    private Modules transformDocuments( final Map xml )
892        throws ParseException, IOException, TransformerException
893    {
894        final Modules mods = new Modules();
895        mods.setModelVersion( MODEL_VERSION );
896 
897        final List list = new LinkedList();
898 
899        for ( final Iterator it = xml.entrySet().iterator(); it.hasNext(); )
900        {
901            final Map.Entry entry = (Map.Entry) it.next();
902            Document doc = (Document) entry.getValue();
903 
904            final TransformerFactory f = TransformerFactory.newInstance();
905            final Enumeration transformers = ClassLoaderFactory.loadResources(
906                this.getClass(), TRANSFORMATION_LOCATION );
907 
908            while ( transformers.hasMoreElements() )
909            {
910                final URL rsrc = (URL) transformers.nextElement();
911 
912                if ( LOGGER.isLoggable( Level.CONFIG ) )
913                {
914                    LOGGER.log( Level.CONFIG, DefaultModelBundle.getInstance().
915                        getResourceInformationMessage(
916                        Locale.getDefault(), rsrc.toExternalForm() ) );
917 
918                }
919 
920                f.setErrorListener( new ErrorListener()
921                {
922 
923                    public void warning( final TransformerException e )
924                        throws TransformerException
925                    {
926                        LOGGER.log( Level.WARNING,
927                                    DefaultModelBundle.getInstance().
928                            getParseExceptionMessage(
929                            Locale.getDefault(), rsrc.toExternalForm(),
930                            e.getMessage(),
931                            new Integer( e.getLocator().getLineNumber() ),
932                            new Integer( e.getLocator().getColumnNumber() ) ) );
933 
934                    }
935 
936                    public void error( final TransformerException e )
937                        throws TransformerException
938                    {
939                        throw new TransformerException(
940                            DefaultModelBundle.getInstance().
941                            getParseExceptionMessage(
942                            Locale.getDefault(), rsrc.toExternalForm(),
943                            e.getMessage(),
944                            new Integer( e.getLocator().getLineNumber() ),
945                            new Integer( e.getLocator().getColumnNumber() ) ),
946                            e );
947 
948                    }
949 
950                    public void fatalError( final TransformerException e )
951                        throws TransformerException
952                    {
953                        throw new TransformerException(
954                            DefaultModelBundle.getInstance().
955                            getParseExceptionMessage(
956                            Locale.getDefault(), rsrc.toExternalForm(),
957                            e.getMessage(),
958                            new Integer( e.getLocator().getLineNumber() ),
959                            new Integer( e.getLocator().getColumnNumber() ) ),
960                            e );
961 
962                    }
963 
964                } );
965 
966                final Transformer t =
967                    f.newTransformer( new StreamSource( rsrc.openStream() ) );
968 
969                final DOMSource source = new DOMSource( doc );
970                final DOMResult result = new DOMResult();
971                t.transform( source, result );
972 
973                doc = (Document) result.getNode();
974            }
975 
976            final URL documentResource = ( (URI) entry.getKey() ).toURL();
977            final Element e = doc.getDocumentElement();
978            String namespace = doc.getDocumentElement().getNamespaceURI();
979 
980            if ( namespace == null )
981            {
982                throw new ModelError(
983                    DefaultModelBundle.getInstance().
984                    getUnknownNamespaceMessage(
985                    Locale.getDefault(), null,
986                    doc.getDocumentElement().getNodeName() ) );
987 
988            }
989 
990            final boolean deprecatedModel;
991            final String modelVersion;
992 
993            if ( MODEL_NS.equals( namespace ) )
994            {
995                deprecatedModel = true;
996 
997                if ( !e.hasAttributeNS( namespace, "version" ) )
998                {
999                    throw new ModelError(
1000                        DefaultModelBundle.getInstance().
1001                        getMissingAttributeMessage(
1002                        Locale.getDefault(), "version", e.getLocalName() ) );
1003 
1004                }
1005 
1006                modelVersion = e.getAttributeNS( namespace, "version" );
1007            }
1008            else if ( MODULE_NS.equals( namespace ) )
1009            {
1010                deprecatedModel = true;
1011                namespace = CONTAINER_NS;
1012 
1013                if ( !e.hasAttributeNS( MODULE_NS, "modelVersion" ) )
1014                {
1015                    throw new ModelError(
1016                        DefaultModelBundle.getInstance().
1017                        getMissingAttributeMessage(
1018                        Locale.getDefault(), "modelVersion",
1019                        e.getLocalName() ) );
1020 
1021                }
1022 
1023                modelVersion = e.getAttributeNS( MODULE_NS, "modelVersion" );
1024            }
1025            else if ( CONTAINER_NS.equals( namespace ) )
1026            {
1027                deprecatedModel = false;
1028 
1029                if ( !e.hasAttributeNS( CONTAINER_NS, "modelVersion" ) )
1030                {
1031                    throw new ModelError(
1032                        DefaultModelBundle.getInstance().
1033                        getMissingAttributeMessage(
1034                        Locale.getDefault(), "modelVersion",
1035                        e.getLocalName() ) );
1036 
1037                }
1038 
1039                modelVersion = e.getAttributeNS( CONTAINER_NS, "modelVersion" );
1040            }
1041            else
1042            {
1043                throw new ModelError(
1044                    DefaultModelBundle.getInstance().
1045                    getUnknownNamespaceMessage(
1046                    Locale.getDefault(), namespace,
1047                    doc.getDocumentElement().getLocalName() ) );
1048 
1049            }
1050 
1051            boolean versionSupported = false;
1052            if ( modelVersion != null )
1053            {
1054                for ( int i = SUPPORTED_MODEL_VERSIONS.length - 1; i >= 0; i-- )
1055                {
1056                    if ( SUPPORTED_MODEL_VERSIONS[i].equals( modelVersion ) )
1057                    {
1058                        versionSupported = true;
1059                        break;
1060                    }
1061                }
1062            }
1063 
1064            if ( !versionSupported )
1065            {
1066                throw new ModelError(
1067                    DefaultModelBundle.getInstance().
1068                    getUnsupportedModelversionMessage(
1069                    Locale.getDefault(), modelVersion ) );
1070 
1071            }
1072 
1073            if ( VersionParser.compare( modelVersion, V_1_3 ) >= 0 )
1074            {
1075                if ( e.getLocalName().equals( "module" ) )
1076                {
1077                    final Module m = this.transformModule(
1078                        modelVersion, namespace, e, documentResource );
1079 
1080                    if ( m != null )
1081                    {
1082                        list.add( m );
1083                    }
1084                }
1085                else if ( e.getLocalName().equals( "modules" ) )
1086                {
1087                    final NodeList l = e.getElementsByTagNameNS( namespace,
1088                                                                 "module" );
1089 
1090                    for ( int i = l.getLength() - 1; i >= 0; i-- )
1091                    {
1092                        if ( l.item( i ).getParentNode().equals( e ) )
1093                        {
1094                            final Module m = this.transformModule(
1095                                modelVersion, namespace, (Element) l.item( i ),
1096                                documentResource );
1097 
1098                            if ( m != null )
1099                            {
1100                                list.add( m );
1101                            }
1102                        }
1103                    }
1104                }
1105                else
1106                {
1107                    throw new ModelError(
1108                        DefaultModelBundle.getInstance().
1109                        getUnsupportedElementMessage( Locale.getDefault(),
1110                                                      e.getLocalName() ) );
1111 
1112                }
1113            }
1114            else
1115            {
1116                final Module m = this.transformModule( modelVersion, namespace,
1117                                                       e, documentResource );
1118 
1119                if ( m != null )
1120                {
1121                    list.add( m );
1122                }
1123            }
1124 
1125            if ( deprecatedModel )
1126            {
1127                if ( LOGGER.isLoggable( Level.CONFIG ) )
1128                {
1129                    LOGGER.log( Level.CONFIG, DefaultModelBundle.getInstance().
1130                        getDeprecatedModelMessage( Locale.getDefault(),
1131                                                   namespace,
1132                                                   modelVersion ) );
1133 
1134                }
1135            }
1136        }
1137 
1138        // Merge any provided platform modules.
1139        Module providedPlatformModule = null;
1140        for ( final Iterator it = list.iterator(); it.hasNext(); )
1141        {
1142            final Module module = (Module) it.next();
1143            if ( PLATFORM_MODULE_NAME.equals( module.getName() ) )
1144            {
1145                providedPlatformModule = module;
1146                it.remove();
1147                break;
1148            }
1149        }
1150 
1151        mods.setModules(
1152            (Module[]) list.toArray( new Module[ list.size() ] ) );
1153 
1154        this.modules = mods;
1155 
1156        if ( providedPlatformModule != null &&
1157             providedPlatformModule.getSpecifications() != null )
1158        {
1159            for ( int i = providedPlatformModule.getSpecifications().size() - 1;
1160                  i >= 0; i-- )
1161            {
1162                this.addPlatformSpecification(
1163                    providedPlatformModule.getSpecifications().
1164                    getSpecification( i ).getIdentifier(), true );
1165 
1166            }
1167        }
1168 
1169        return mods;
1170    }
1171 
1172    private Specifications transformSpecifications(
1173        final String modelVersion, final String namespace,
1174        final Element specificationsElement ) throws ParseException
1175    {
1176        final List list = new LinkedList();
1177        NodeList l =
1178            specificationsElement.getElementsByTagNameNS( namespace,
1179                                                          "specification" );
1180 
1181        if ( l != null && l.getLength() > 0 )
1182        {
1183            for ( int i = l.getLength() - 1; i >= 0; i-- )
1184            {
1185                if ( l.item( i ).getParentNode().
1186                    equals( specificationsElement ) )
1187                {
1188                    list.add( this.transformSpecification(
1189                        modelVersion, namespace, (Element) l.item( i ) ) );
1190 
1191                }
1192            }
1193        }
1194 
1195        if ( VersionParser.compare( modelVersion, V_1_3 ) >= 0 )
1196        {
1197            l = specificationsElement.getElementsByTagNameNS( namespace,
1198                                                              "reference" );
1199 
1200            if ( l != null && l.getLength() > 0 )
1201            {
1202                for ( int i = l.getLength() - 1; i >= 0; i-- )
1203                {
1204                    if ( l.item( i ).getParentNode().
1205                        equals( specificationsElement ) )
1206                    {
1207                        list.add(
1208                            this.transformSpecificationReference(
1209                            namespace, (Element) l.item( i ) ) );
1210 
1211                    }
1212                }
1213            }
1214        }
1215 
1216        final Specifications specs = new Specifications();
1217        specs.setModelVersion( modelVersion );
1218        specs.setSpecifications( (Specification[]) list.toArray(
1219            new Specification[ list.size() ] ) );
1220 
1221        if ( VersionParser.compare( modelVersion, V_1_3 ) >= 0 )
1222        {
1223            this.transformModelObject( namespace, specificationsElement, specs );
1224        }
1225 
1226        return specs;
1227    }
1228 
1229    private Implementations transformImplementations(
1230        final String modelVersion, final String namespace,
1231        final Module module, final Element implementationsElement )
1232        throws ParseException
1233    {
1234        final List list = new LinkedList();
1235        final NodeList l =
1236            implementationsElement.getElementsByTagNameNS( namespace,
1237                                                           "implementation" );
1238 
1239        if ( l != null && l.getLength() > 0 )
1240        {
1241            for ( int i = l.getLength() - 1; i >= 0; i-- )
1242            {
1243                if ( l.item( i ).getParentNode().
1244                    equals( implementationsElement ) )
1245                {
1246                    list.add( this.transformImplementation(
1247                        modelVersion, namespace, module,
1248                        (Element) l.item( i ) ) );
1249 
1250                }
1251            }
1252        }
1253 
1254        final Implementations impls = new Implementations();
1255        impls.setModelVersion( modelVersion );
1256        impls.setImplementations( (Implementation[]) list.toArray(
1257            new Implementation[ list.size() ] ) );
1258 
1259        if ( VersionParser.compare( modelVersion, V_1_3 ) >= 0 )
1260        {
1261            this.transformModelObject( namespace, implementationsElement,
1262                                       impls );
1263 
1264        }
1265 
1266        return impls;
1267    }
1268 
1269    private Properties transformProperties(
1270        final String modelVersion, final String namespace,
1271        final Element propertiesElement )
1272        throws ParseException
1273    {
1274        final Map transformed = new TreeMap();
1275        final NodeList l =
1276            propertiesElement.getElementsByTagNameNS( namespace, "property" );
1277 
1278        if ( l != null && l.getLength() > 0 )
1279        {
1280            for ( int i = l.getLength() - 1; i >= 0; i-- )
1281            {
1282                if ( l.item( i ).getParentNode().equals( propertiesElement ) )
1283                {
1284                    final Property p = this.transformProperty(
1285                        modelVersion, namespace, (Element) l.item( i ) );
1286 
1287                    if ( propertiesElement.getParentNode().getLocalName().
1288                        equals( "specification" ) )
1289                    {
1290                        p.setValue( null );
1291                        p.setApi( true );
1292                    }
1293 
1294                    transformed.put( p.getName(), p );
1295                }
1296            }
1297        }
1298 
1299        final Properties props = new Properties();
1300        props.setModelVersion( modelVersion );
1301        props.setProperties( (Property[]) transformed.values().toArray(
1302            new Property[ transformed.size() ] ) );
1303 
1304        if ( VersionParser.compare( modelVersion, V_1_3 ) >= 0 )
1305        {
1306            this.transformModelObject( namespace, propertiesElement, props );
1307        }
1308 
1309        return props;
1310    }
1311 
1312    private Dependencies transformDependencies(
1313        final String modelVersion, final String namespace,
1314        final String implementationIdentifier,
1315        final Element dependenciesElement ) throws ParseException
1316    {
1317        final List list = new LinkedList();
1318        final NodeList l =
1319            dependenciesElement.getElementsByTagNameNS( namespace,
1320                                                        "dependency" );
1321 
1322        if ( l != null && l.getLength() > 0 )
1323        {
1324            for ( int i = l.getLength() - 1; i >= 0; i-- )
1325            {
1326                if ( l.item( i ).getParentNode().equals( dependenciesElement ) )
1327                {
1328                    list.add(
1329                        this.transformDependency( modelVersion, namespace,
1330                                                  implementationIdentifier,
1331                                                  (Element) l.item( i ) ) );
1332 
1333                }
1334            }
1335        }
1336 
1337        final Dependencies deps = new Dependencies();
1338        deps.setModelVersion( modelVersion );
1339        deps.setDependencies( (Dependency[]) list.toArray(
1340            new Dependency[ list.size() ] ) );
1341 
1342        if ( VersionParser.compare( modelVersion, V_1_3 ) >= 0 )
1343        {
1344            this.transformModelObject( namespace, dependenciesElement, deps );
1345        }
1346 
1347        return deps;
1348    }
1349 
1350    private Messages transformMessages(
1351        final String modelVersion, final String namespace, final Module module,
1352        final Element messagesElement )
1353    {
1354        final List messages = new LinkedList();
1355        NodeList l = messagesElement.getElementsByTagNameNS( namespace,
1356                                                             "message" );
1357 
1358        if ( l != null && l.getLength() > 0 )
1359        {
1360            for ( int i = l.getLength() - 1; i >= 0; i-- )
1361            {
1362                if ( l.item( i ).getParentNode().equals( messagesElement ) )
1363                {
1364                    messages.add(
1365                        this.transformMessage( modelVersion, module.getName(),
1366                                               namespace,
1367                                               (Element) l.item( i ) ) );
1368 
1369                }
1370            }
1371        }
1372 
1373        l = messagesElement.getElementsByTagNameNS( namespace,
1374                                                    "reference" );
1375 
1376        if ( l != null && l.getLength() > 0 )
1377        {
1378            for ( int i = l.getLength() - 1; i >= 0; i-- )
1379            {
1380                if ( l.item( i ).getParentNode().equals( messagesElement ) )
1381                {
1382                    final String name =
1383                        ( (Element) l.item( i ) ).getAttributeNS(
1384                        namespace, "name" );
1385 
1386                    messages.add( module.getMessages().getMessage( name ) );
1387                }
1388            }
1389        }
1390 
1391        final Messages msgs = new Messages();
1392        msgs.setModelVersion( modelVersion );
1393        msgs.setMessages( (Message[]) messages.toArray(
1394            new Message[ messages.size() ] ) );
1395 
1396        this.transformModelObject( namespace, messagesElement, msgs );
1397 
1398        return msgs;
1399    }
1400 
1401    private Arguments transformArguments(
1402        final String modelVersion, final String namespace,
1403        final Element argumentsElement )
1404    {
1405        final List arguments = new LinkedList();
1406        final NodeList l =
1407            argumentsElement.getElementsByTagNameNS( namespace,
1408                                                     "argument" );
1409 
1410        if ( l != null && l.getLength() > 0 )
1411        {
1412            for ( int i = l.getLength() - 1; i >= 0; i-- )
1413            {
1414                if ( l.item( i ).getParentNode().equals( argumentsElement ) )
1415                {
1416                    arguments.add(
1417                        this.transformArgument( modelVersion, namespace,
1418                                                (Element) l.item( i ) ) );
1419 
1420                }
1421            }
1422        }
1423 
1424        Collections.sort( arguments, new Comparator()
1425        {
1426 
1427            public int compare( final Object o1, final Object o2 )
1428            {
1429                return ( (Argument) o1 ).getIndex() -
1430                       ( (Argument) o2 ).getIndex();
1431 
1432            }
1433 
1434        } );
1435 
1436        final Arguments args = new Arguments();
1437        args.setModelVersion( modelVersion );
1438        args.setArguments( (Argument[]) arguments.toArray(
1439            new Argument[ arguments.size() ] ) );
1440 
1441        this.transformModelObject( namespace, argumentsElement, args );
1442 
1443        return args;
1444    }
1445 
1446    private Module transformModule( final String modelVersion,
1447                                    final String namespace, final Element e,
1448                                    final URL documentResource )
1449        throws ParseException
1450    {
1451        NodeList l;
1452        Module module = new Module();
1453        module.setModelVersion( modelVersion );
1454        module.setName( e.getAttributeNS( namespace, "name" ) );
1455        module.setVersion( e.getAttributeNS( namespace, "version" ) );
1456        if ( e.hasAttributeNS( namespace, "description" ) )
1457        {
1458            final String txt = e.getAttributeNS( namespace, "description" );
1459            module.setDescription( txt );
1460        }
1461 
1462        l = e.getElementsByTagNameNS( namespace, "specifications" );
1463 
1464        if ( l != null && l.getLength() > 0 )
1465        {
1466            for ( int i = l.getLength() - 1; i >= 0; i-- )
1467            {
1468                if ( l.item( i ).getParentNode().equals( e ) )
1469                {
1470                    module.setSpecifications(
1471                        this.transformSpecifications(
1472                        modelVersion, namespace, (Element) l.item( i ) ) );
1473 
1474                    break;
1475                }
1476            }
1477        }
1478 
1479        l = e.getElementsByTagNameNS( namespace, "properties" );
1480 
1481        if ( l != null && l.getLength() > 0 )
1482        {
1483            for ( int i = l.getLength() - 1; i >= 0; i-- )
1484            {
1485                if ( l.item( i ).getParentNode().equals( e ) )
1486                {
1487                    module.setProperties(
1488                        this.transformProperties(
1489                        modelVersion, namespace, (Element) l.item( i ) ) );
1490 
1491                    break;
1492                }
1493            }
1494        }
1495 
1496        if ( VersionParser.compare( modelVersion, V_1_3 ) >= 0 )
1497        {
1498            l = e.getElementsByTagNameNS( namespace, "messages" );
1499 
1500            if ( l != null && l.getLength() > 0 )
1501            {
1502                for ( int i = l.getLength() - 1; i >= 0; i-- )
1503                {
1504                    if ( l.item( i ).getParentNode().equals( e ) )
1505                    {
1506                        module.setMessages(
1507                            this.transformMessages(
1508                            modelVersion, namespace, module,
1509                            (Element) l.item( i ) ) );
1510 
1511                        break;
1512                    }
1513                }
1514            }
1515 
1516            this.transformModelObject( namespace, e, module );
1517        }
1518 
1519        l = e.getElementsByTagNameNS( namespace, "implementations" );
1520 
1521        if ( l != null && l.getLength() > 0 )
1522        {
1523            for ( int i = l.getLength() - 1; i >= 0; i-- )
1524            {
1525                if ( l.item( i ).getParentNode().equals( e ) )
1526                {
1527                    module.setImplementations(
1528                        this.transformImplementations(
1529                        modelVersion, namespace, module,
1530                        (Element) l.item( i ) ) );
1531 
1532                    break;
1533                }
1534            }
1535        }
1536 
1537        if ( this.moduleMap.containsKey( module.getName() ) &&
1538             Beans.isDesignTime() )
1539        {
1540            if ( LOGGER.isLoggable( Level.CONFIG ) )
1541            {
1542                LOGGER.log( Level.CONFIG, DefaultModelBundle.getInstance().
1543                    getIgnoredModuleMessage(
1544                    Locale.getDefault(), documentResource.toExternalForm(),
1545                    ( (URL) this.moduleMap.get( module.getName() ) ).
1546                    toExternalForm() ) );
1547 
1548            }
1549 
1550            module = null;
1551        }
1552        else
1553        {
1554            this.moduleMap.put( module.getName(), documentResource );
1555        }
1556 
1557        return module;
1558    }
1559 
1560    private Specification transformSpecificationReference(
1561        final String namespace, final Element e )
1562    {
1563        String version = null;
1564        final String identifier = e.getAttributeNS( namespace, "identifier" );
1565        if ( e.hasAttributeNS( namespace, "version" ) )
1566        {
1567            version = e.getAttributeNS( namespace, "version" );
1568        }
1569 
1570        return this.getSpecification( identifier, version );
1571    }
1572 
1573    private Specification transformSpecification( final String modelVersion,
1574                                                  final String namespace,
1575                                                  final Element xml )
1576        throws ParseException
1577    {
1578        final Specification spec =
1579            this.transformSpecificationReference( namespace, xml );
1580 
1581        spec.setModelVersion( modelVersion );
1582        spec.setVendor( xml.getAttributeNS( namespace, "vendor" ) );
1583        if ( xml.hasAttributeNS( namespace, "description" ) )
1584        {
1585            final String txt = xml.getAttributeNS( namespace, "description" );
1586            spec.setDescription( txt );
1587        }
1588 
1589        if ( xml.hasAttributeNS( namespace, "singleton" ) )
1590        {
1591            spec.setSingleton(
1592                Boolean.valueOf( xml.getAttributeNS(
1593                namespace, "singleton" ) ).booleanValue() );
1594 
1595        }
1596 
1597        if ( VersionParser.compare( modelVersion, V_1_1 ) >= 0 )
1598        {
1599            final String multiplicity =
1600                xml.getAttributeNS( namespace, "multiplicity" );
1601 
1602            if ( "one".equalsIgnoreCase( multiplicity ) )
1603            {
1604                spec.setMultiplicity( Specification.MULTIPLICITY_ONE );
1605            }
1606            else if ( "many".equalsIgnoreCase( multiplicity ) )
1607            {
1608                spec.setMultiplicity( Specification.MULTIPLICITY_MANY );
1609            }
1610            else
1611            {
1612                throw new ModelError(
1613                    DefaultModelBundle.getInstance().
1614                    getUnsupportedMultiplicityMessage( Locale.getDefault(),
1615                                                       multiplicity ) );
1616 
1617            }
1618        }
1619 
1620        if ( VersionParser.compare( modelVersion, V_1_3 ) >= 0 )
1621        {
1622            if ( xml.hasAttributeNS( namespace, "stateless" ) )
1623            {
1624                spec.setStateless( Boolean.valueOf( xml.getAttributeNS(
1625                    namespace, "stateless" ) ).booleanValue() );
1626 
1627            }
1628 
1629            final String scope = xml.getAttributeNS( namespace, "scope" );
1630            if ( "multiton".equalsIgnoreCase( scope ) )
1631            {
1632                spec.setScope( Specification.SCOPE_MULTITON );
1633            }
1634            else if ( "context".equalsIgnoreCase( scope ) )
1635            {
1636                spec.setScope( Specification.SCOPE_CONTEXT );
1637            }
1638            else if ( "singleton".equalsIgnoreCase( scope ) )
1639            {
1640                spec.setScope( Specification.SCOPE_SINGLETON );
1641            }
1642            else
1643            {
1644                throw new ModelError(
1645                    DefaultModelBundle.getInstance().
1646                    getUnsupportedScopeMessage( Locale.getDefault(),
1647                                                spec.getIdentifier(), scope ) );
1648 
1649            }
1650 
1651            final NodeList l =
1652                xml.getElementsByTagNameNS( namespace, "properties" );
1653 
1654            if ( l != null && l.getLength() > 0 )
1655            {
1656                for ( int i = l.getLength() - 1; i >= 0; i-- )
1657                {
1658                    if ( l.item( i ).getParentNode().equals( xml ) )
1659                    {
1660                        spec.setProperties(
1661                            this.transformProperties(
1662                            modelVersion, namespace, (Element) l.item( i ) ) );
1663 
1664                        break;
1665                    }
1666                }
1667            }
1668 
1669            this.transformModelObject( namespace, xml, spec );
1670        }
1671 
1672        return spec;
1673    }
1674 
1675    private Implementation transformImplementation( final String modelVersion,
1676                                                    final String namespace,
1677                                                    final Module module,
1678                                                    final Element xml )
1679        throws ParseException
1680    {
1681        final String identifier = xml.getAttributeNS( namespace, "identifier" );
1682        final Implementation impl = this.getImplementation( identifier );
1683        impl.setModelVersion( modelVersion );
1684        impl.setModuleName( module.getName() );
1685        impl.setName( xml.getAttributeNS( namespace, "name" ) );
1686        impl.setVendor( xml.getAttributeNS( namespace, "vendor" ) );
1687        impl.setVersion( xml.getAttributeNS( namespace, "version" ) );
1688 
1689        if ( xml.hasAttributeNS( namespace, "parent" ) )
1690        {
1691            this.impl2parent.put( impl.getIdentifier(),
1692                                  xml.getAttributeNS( namespace, "parent" ) );
1693 
1694        }
1695 
1696        NodeList l = xml.getElementsByTagNameNS( namespace, "dependencies" );
1697 
1698        if ( l != null && l.getLength() > 0 )
1699        {
1700            for ( int i = l.getLength() - 1; i >= 0; i-- )
1701            {
1702                if ( l.item( i ).getParentNode().equals( xml ) )
1703                {
1704                    impl.setDependencies(
1705                        this.transformDependencies(
1706                        modelVersion, namespace, identifier,
1707                        (Element) l.item( i ) ) );
1708 
1709                    break;
1710                }
1711            }
1712        }
1713 
1714        final String specificationsName =
1715            VersionParser.compare( modelVersion, V_1_3 ) >= 0
1716            ? "specifications"
1717            : "implementedSpecifications";
1718 
1719        l = xml.getElementsByTagNameNS( namespace, specificationsName );
1720        if ( l != null && l.getLength() > 0 )
1721        {
1722            for ( int i = l.getLength() - 1; i >= 0; i-- )
1723            {
1724                if ( l.item( i ).getParentNode().equals( xml ) )
1725                {
1726                    if ( VersionParser.compare( modelVersion, V_1_3 ) >= 0 )
1727                    {
1728                        impl.setImplementedSpecifications(
1729                            this.transformSpecifications(
1730                            modelVersion, namespace, (Element) l.item( i ) ) );
1731 
1732                        break;
1733                    }
1734                    else
1735                    {
1736                        final Set set = new HashSet();
1737                        final NodeList deprecated =
1738                            ( (Element) l.item( i ) ).getElementsByTagNameNS(
1739                            namespace, "implementedSpecification" );
1740 
1741                        if ( deprecated != null && deprecated.getLength() > 0 )
1742                        {
1743                            for ( int d = deprecated.getLength() - 1; d >= 0;
1744                                  d-- )
1745                            {
1746                                if ( deprecated.item( d ).getParentNode().
1747                                    equals( l.item( i ) ) )
1748                                {
1749                                    set.add(
1750                                        this.transformSpecificationReference(
1751                                        namespace,
1752                                        (Element) deprecated.item( d ) ) );
1753 
1754                                }
1755                            }
1756                        }
1757 
1758                        final Specifications specs = new Specifications();
1759                        specs.setModelVersion( modelVersion );
1760                        specs.setSpecifications(
1761                            (Specification[]) set.toArray(
1762                            new Specification[ set.size() ] ) );
1763 
1764                        impl.setImplementedSpecifications( specs );
1765                        break;
1766                    }
1767                }
1768            }
1769        }
1770 
1771        l = xml.getElementsByTagNameNS( namespace, "properties" );
1772 
1773        if ( l != null && l.getLength() > 0 )
1774        {
1775            for ( int i = l.getLength() - 1; i >= 0; i-- )
1776            {
1777                if ( l.item( i ).getParentNode().equals( xml ) )
1778                {
1779                    impl.setProperties(
1780                        this.transformProperties( modelVersion, namespace,
1781                                                  (Element) l.item( i ) ) );
1782 
1783                    break;
1784                }
1785            }
1786        }
1787 
1788        if ( VersionParser.compare( modelVersion, V_1_1 ) >= 0 &&
1789             xml.hasAttributeNS( namespace, "final" ) )
1790        {
1791            impl.setFinal( Boolean.valueOf( xml.getAttributeNS( namespace,
1792                                                                "final" ) ).
1793                booleanValue() );
1794 
1795        }
1796 
1797        if ( VersionParser.compare( modelVersion, V_1_3 ) >= 0 )
1798        {
1799            l = xml.getElementsByTagNameNS( namespace, "messages" );
1800 
1801            if ( l != null && l.getLength() > 0 )
1802            {
1803                for ( int i = l.getLength() - 1; i >= 0; i-- )
1804                {
1805                    if ( l.item( i ).getParentNode().equals( xml ) )
1806                    {
1807                        impl.setMessages( this.transformMessages(
1808                            modelVersion, namespace, module,
1809                            (Element) l.item( i ) ) );
1810 
1811                        break;
1812                    }
1813                }
1814            }
1815 
1816            this.transformModelObject( namespace, xml, impl );
1817        }
1818 
1819        return impl;
1820    }
1821 
1822    private Property transformProperty( final String modelVersion,
1823                                        final String namespace,
1824                                        final Element xml )
1825        throws ParseException
1826    {
1827        final Property prop = new Property();
1828        prop.setModelVersion( modelVersion );
1829        prop.setName( xml.getAttributeNS( namespace, "name" ) );
1830 
1831        if ( xml.hasAttributeNS( namespace, "api" ) )
1832        {
1833            final String api = xml.getAttributeNS( namespace, "api" );
1834            prop.setApi( Boolean.valueOf( api ).booleanValue() );
1835        }
1836 
1837        final String type = xml.hasAttributeNS( namespace, "type" )
1838                            ? xml.getAttributeNS( namespace, "type" )
1839                            : null;
1840 
1841        final String value = xml.hasAttributeNS( namespace, "value" )
1842                             ? xml.getAttributeNS( namespace, "value" )
1843                             : null;
1844 
1845        if ( type == null )
1846        {
1847            throw new ModelError(
1848                DefaultModelBundle.getInstance().
1849                getMissingPropertyTypeMessage(
1850                Locale.getDefault(), prop.getName(),
1851                xml.getParentNode().getParentNode().getLocalName() ) );
1852 
1853        }
1854 
1855        this.updatePropertyValue( type, value, prop );
1856 
1857        if ( VersionParser.compare( modelVersion, V_1_3 ) >= 0 )
1858        {
1859            this.transformModelObject( namespace, xml, prop );
1860        }
1861 
1862        return prop;
1863    }
1864 
1865    private Dependency transformDependency(
1866        final String modelVersion, final String namespace,
1867        final String implementationIdentifier, final Element xml )
1868        throws ParseException
1869    {
1870        final Dependency dep = new Dependency();
1871        dep.setModelVersion( modelVersion );
1872        dep.setName( xml.getAttributeNS( namespace, "name" ) );
1873 
1874        if ( xml.hasAttributeNS( namespace, "bound" ) )
1875        {
1876            dep.setBound( Boolean.valueOf( xml.getAttributeNS( namespace,
1877                                                               "bound" ) ).
1878                booleanValue() );
1879 
1880        }
1881 
1882        if ( xml.hasAttributeNS( namespace, "implementationName" ) )
1883        {
1884            final String name = xml.getAttributeNS( namespace,
1885                                                    "implementationName" );
1886 
1887            final String key = implementationIdentifier + '/' +
1888                               dep.getName();
1889 
1890            this.dependencies.put( key, name );
1891        }
1892 
1893        final String specificationIdentifier =
1894            VersionParser.compare( modelVersion, V_1_3 ) < 0
1895            ? "specificationIdentifier"
1896            : "identifier";
1897 
1898        final String identifier = xml.getAttributeNS( namespace,
1899                                                      specificationIdentifier );
1900 
1901        if ( VersionParser.compare( modelVersion, V_1_3 ) < 0 )
1902        {
1903            dep.setSpecification( this.getSpecification( identifier, null ) );
1904        }
1905        else
1906        {
1907            String version = null;
1908            if ( xml.hasAttributeNS( namespace, "version" ) )
1909            {
1910                version = xml.getAttributeNS( namespace, "version" );
1911            }
1912 
1913            dep.setSpecification( this.getSpecification( identifier,
1914                                                         version ) );
1915 
1916        }
1917 
1918        final NodeList l =
1919            xml.getElementsByTagNameNS( namespace, "properties" );
1920 
1921        if ( l != null && l.getLength() > 0 )
1922        {
1923            for ( int i = l.getLength() - 1; i >= 0; i-- )
1924            {
1925                if ( l.item( i ).getParentNode().equals( xml ) )
1926                {
1927                    dep.setProperties(
1928                        this.transformProperties(
1929                        modelVersion, namespace, (Element) l.item( i ) ) );
1930 
1931                    break;
1932                }
1933            }
1934        }
1935 
1936        if ( VersionParser.compare( modelVersion, V_1_3 ) >= 0 )
1937        {
1938            this.transformModelObject( namespace, xml, dep );
1939        }
1940 
1941        return dep;
1942    }
1943 
1944    private Text transformText( final String namespace,
1945                                final Element textsElement )
1946    {
1947        final Text text = new Text();
1948        final String defaultLanguage =
1949            textsElement.getAttributeNS( namespace, "defaultLanguage" );
1950 
1951        final NodeList l =
1952            textsElement.getElementsByTagNameNS( namespace, "text" );
1953 
1954        if ( l != null && l.getLength() > 0 )
1955        {
1956            for ( int i = l.getLength() - 1; i >= 0; i-- )
1957            {
1958                final Element textElement = (Element) l.item( i );
1959                if ( textElement.getParentNode().equals( textsElement ) )
1960                {
1961                    final String language =
1962                        textElement.getAttributeNS( namespace, "language" );
1963 
1964                    final String value =
1965                        textElement.getFirstChild().getNodeValue();
1966 
1967                    final Locale locale = new Locale( language.toLowerCase() );
1968                    text.setValue( locale, value );
1969 
1970                    if ( language.equalsIgnoreCase( defaultLanguage ) )
1971                    {
1972                        text.setValue( value );
1973                    }
1974                }
1975            }
1976        }
1977 
1978        return text;
1979    }
1980 
1981    private void transformModelObject( final String namespace,
1982                                       final Element objectElement,
1983                                       final ModelObject modelObject )
1984    {
1985        final NodeList l = objectElement.getElementsByTagNameNS(
1986            namespace, "documentation" );
1987 
1988        if ( l != null && l.getLength() > 0 )
1989        {
1990            for ( int i = l.getLength() - 1; i >= 0; i-- )
1991            {
1992                if ( l.item( i ).getParentNode().equals( objectElement ) )
1993                {
1994                    modelObject.setDocumentation(
1995                        this.transformText( namespace,
1996                                            (Element) l.item( i ) ) );
1997 
1998                    break;
1999                }
2000            }
2001        }
2002    }
2003 
2004    private Message transformMessage( final String modelVersion,
2005                                      final String moduleName,
2006                                      final String namespace,
2007                                      final Element xml )
2008    {
2009        final Message msg = new Message();
2010        msg.setModelVersion( modelVersion );
2011        msg.setModuleName( moduleName );
2012        msg.setName( xml.getAttributeNS( namespace, "name" ) );
2013 
2014        NodeList l = xml.getElementsByTagNameNS( namespace, "template" );
2015 
2016        if ( l != null && l.getLength() > 0 )
2017        {
2018            for ( int i = l.getLength() - 1; i >= 0; i-- )
2019            {
2020                if ( l.item( i ).getParentNode().equals( xml ) )
2021                {
2022                    final Text template = this.transformText(
2023                        namespace, (Element) l.item( i ) );
2024 
2025                    final Locale[] locales = template.getLocales();
2026                    for ( int t = locales.length - 1; t >= 0; t-- )
2027                    {
2028                        final String text = template.getValue( locales[t] );
2029                        try
2030                        {
2031                            new MessageFormat( text );
2032                        }
2033                        catch ( final IllegalArgumentException e )
2034                        {
2035                            final ModelError modelError = new ModelError(
2036                                DefaultModelBundle.getInstance().
2037                                getIllegalTemplateMessage( Locale.getDefault(),
2038                                                           text, msg.getName(),
2039                                                           e.getMessage() ) );
2040 
2041                            modelError.initCause( e );
2042                            throw modelError;
2043                        }
2044                    }
2045 
2046                    if ( template.getValue() != null )
2047                    {
2048                        try
2049                        {
2050                            new MessageFormat( template.getValue() );
2051                        }
2052                        catch ( final IllegalArgumentException e )
2053                        {
2054                            final ModelError modelError = new ModelError(
2055                                DefaultModelBundle.getInstance().
2056                                getIllegalTemplateMessage( Locale.getDefault(),
2057                                                           template.getValue(),
2058                                                           msg.getName(),
2059                                                           e.getMessage() ) );
2060 
2061                            modelError.initCause( e );
2062                            throw modelError;
2063                        }
2064                    }
2065 
2066                    msg.setTemplate( template );
2067                    break;
2068                }
2069            }
2070        }
2071 
2072        l = xml.getElementsByTagNameNS( namespace, "arguments" );
2073 
2074        if ( l != null && l.getLength() > 0 )
2075        {
2076            for ( int i = l.getLength() - 1; i >= 0; i-- )
2077            {
2078                if ( l.item( i ).getParentNode().equals( xml ) )
2079                {
2080                    msg.setArguments(
2081                        this.transformArguments(
2082                        modelVersion, namespace, (Element) l.item( i ) ) );
2083 
2084                    break;
2085                }
2086            }
2087        }
2088 
2089        this.transformModelObject( namespace, xml, msg );
2090 
2091        return msg;
2092    }
2093 
2094    private Argument transformArgument( final String modelVersion,
2095                                        final String namespace,
2096                                        final Element xml )
2097    {
2098        final Argument arg = new Argument();
2099        arg.setModelVersion( modelVersion );
2100        arg.setName( xml.getAttributeNS( namespace, "name" ) );
2101        arg.setIndex( Integer.valueOf( xml.getAttributeNS( namespace,
2102                                                           "index" ) ).
2103            intValue() );
2104 
2105        final String type = xml.getAttributeNS( namespace, "type" );
2106        if ( type.equalsIgnoreCase( "number" ) )
2107        {
2108            arg.setType( Argument.TYPE_NUMBER );
2109        }
2110        else if ( type.equalsIgnoreCase( "date" ) )
2111        {
2112            arg.setType( Argument.TYPE_DATE );
2113        }
2114        else if ( type.equalsIgnoreCase( "time" ) )
2115        {
2116            arg.setType( Argument.TYPE_TIME );
2117        }
2118        else if ( type.equalsIgnoreCase( "text" ) )
2119        {
2120            arg.setType( Argument.TYPE_TEXT );
2121        }
2122        else
2123        {
2124            throw new ModelError( DefaultModelBundle.getInstance().
2125                getUnsupportedArgumentTypeMessage(
2126                Locale.getDefault(), type ) );
2127 
2128        }
2129 
2130        this.transformModelObject( namespace, xml, arg );
2131 
2132        return arg;
2133    }
2134 
2135    /**
2136     * Gets the {@code Module} holding platform specifications.
2137     *
2138     * @return the {@code Module} holding platform specifications.
2139     */
2140    protected Module getPlatformModule()
2141    {
2142        if ( this.platformModule == null )
2143        {
2144            final String description =
2145                DefaultModelBundle.getInstance().
2146                getPlatformModuleDescriptionMessage( Locale.getDefault() );
2147 
2148            this.platformModule = new Module();
2149            this.platformModule.getDocumentation().setValue( description );
2150            this.platformModule.setName( PLATFORM_MODULE_NAME );
2151            this.platformModule.setVersion( PLATFORM_MODULE_VERSION );
2152 
2153            if ( LOGGER.isLoggable( Level.CONFIG ) )
2154            {
2155                LOGGER.log( Level.CONFIG, DefaultModelBundle.getInstance().
2156                    getAddedPlatformModuleMessage(
2157                    Locale.getDefault(),
2158                    this.platformModule.getDocumentation().getValue() ) );
2159            }
2160        }
2161 
2162        return this.platformModule;
2163    }
2164 
2165    /**
2166     * Checks an identifier to identify a valid platform specification.
2167     *
2168     * @param identifier the identifier to check.
2169     *
2170     * @return {@code true} if {@code identifier} identifies a valid platform
2171     * specification; {@code false} else.
2172     *
2173     * @throws NullPointerException if {@code identifier} is {@code null}.
2174     */
2175    protected boolean isPlatformSpecification( final String identifier )
2176    {
2177        return this.addPlatformSpecification( identifier, false );
2178    }
2179 
2180    /**
2181     * Checks an identifier to identify a valid platform specification and
2182     * optionally adds a new {@code Specification} instance to the platform
2183     * module.
2184     *
2185     * @param identifier the identifier to check.
2186     * @param add {@code true} to add a new {@code Specification} instance to
2187     * the platform module; {@code false} to not update the platform module.
2188     *
2189     * @return {@code true} if {@code identifier} is an identifier of a valid
2190     * platform specification; {@code false} else.
2191     */
2192    private boolean addPlatformSpecification( final String identifier,
2193                                              final boolean add )
2194    {
2195        if ( identifier == null )
2196        {
2197            throw new NullPointerException( "identifier" );
2198        }
2199 
2200        boolean validPlatformSpec = false;
2201 
2202        try
2203        {
2204            final Class platformClass = ClassLoaderFactory.loadClass(
2205                this.getClass(), identifier );
2206 
2207            if ( Modifier.isPublic( platformClass.getModifiers() ) )
2208            {
2209                if ( platformClass.getPackage() != null )
2210                {
2211                    final String specVersion = platformClass.getPackage().
2212                        getSpecificationVersion();
2213 
2214                    String specVendor = platformClass.getPackage().
2215                        getSpecificationVendor();
2216 
2217                    if ( specVendor == null )
2218                    {
2219                        specVendor = DefaultModelBundle.getInstance().
2220                            getUnknownVendorMessage( Locale.getDefault() );
2221 
2222                    }
2223 
2224                    if ( specVersion != null )
2225                    {
2226                        validPlatformSpec = true;
2227 
2228                        if ( add )
2229                        {
2230                            // Add to the platform module.
2231                            try
2232                            {
2233                                final Specification platformSpec =
2234                                    this.getSpecification( identifier,
2235                                                           specVersion );
2236 
2237                                platformSpec.setModelVersion( MODEL_VERSION );
2238                                platformSpec.setDocumentation(
2239                                    this.getPlatformModule().
2240                                    getDocumentation() );
2241 
2242                                platformSpec.setIdentifier( identifier );
2243                                platformSpec.setModuleName(
2244                                    this.getPlatformModule().getName() );
2245 
2246                                platformSpec.setMultiplicity(
2247                                    Specification.MULTIPLICITY_MANY );
2248 
2249                                platformSpec.setScope(
2250                                    Specification.SCOPE_MULTITON );
2251 
2252                                platformSpec.setVendor( specVendor );
2253 
2254                                final Specification[] platformSpecs =
2255                                    this.getPlatformModule().
2256                                    getSpecifications().getSpecifications();
2257 
2258                                final Specification[] newPlatformSpecs =
2259                                    new Specification[ platformSpecs.length + 1 ];
2260 
2261                                System.arraycopy( platformSpecs, 0,
2262                                                  newPlatformSpecs, 0,
2263                                                  platformSpecs.length );
2264 
2265                                newPlatformSpecs[platformSpecs.length] =
2266                                    platformSpec;
2267 
2268                                final Specifications specs =
2269                                    new Specifications();
2270 
2271                                specs.setSpecifications( newPlatformSpecs );
2272                                this.getPlatformModule().
2273                                    setSpecifications( specs );
2274 
2275                                if ( LOGGER.isLoggable( Level.FINE ) )
2276                                {
2277                                    LOGGER.log( Level.FINE,
2278                                                DefaultModelBundle.getInstance().
2279                                        getAddedPlatformSpecificationMessage(
2280                                        Locale.getDefault(), identifier,
2281                                        specVersion,
2282                                        specVendor ) );
2283 
2284                                }
2285 
2286                                this.addDefaultImplementation( platformClass,
2287                                                               platformSpec );
2288 
2289                            }
2290                            catch ( final DuplicateSpecificationException e )
2291                            {
2292                                // Specification already created.
2293                            }
2294                        }
2295                    }
2296                    else
2297                    {
2298                        LOGGER.log( Level.WARNING,
2299                                    DefaultModelBundle.getInstance().
2300                            getNoVersionAvailableMessage( Locale.getDefault(),
2301                                                          identifier ) );
2302 
2303                        validPlatformSpec = false;
2304                    }
2305                }
2306                else
2307                {
2308                    LOGGER.log( Level.WARNING, DefaultModelBundle.getInstance().
2309                        getNoPackageAvailableMessage( Locale.getDefault(),
2310                                                      identifier ) );
2311 
2312                    validPlatformSpec = false;
2313                }
2314            }
2315            else
2316            {
2317                LOGGER.log( Level.WARNING, DefaultModelBundle.getInstance().
2318                    getNotPublicMessage( Locale.getDefault(), identifier ) );
2319 
2320                validPlatformSpec = false;
2321            }
2322        }
2323        catch ( final ClassNotFoundException ex )
2324        {
2325            LOGGER.log( Level.WARNING, DefaultModelBundle.getInstance().
2326                getClassNotFoundMessage( Locale.getDefault(), identifier ) );
2327 
2328            validPlatformSpec = false;
2329        }
2330 
2331        return validPlatformSpec;
2332    }
2333 
2334    private void addDefaultImplementation( final Class platformClass,
2335                                           final Specification platformSpec )
2336    {
2337        try
2338        {
2339            final Method accessor = platformClass.getDeclaredMethod(
2340                "getDefault", new Class[ 0 ] );
2341 
2342            if ( Modifier.isStatic( accessor.getModifiers() ) &&
2343                 accessor.getReturnType() == platformClass )
2344            {
2345                boolean overwritten = false;
2346 
2347                // Check for an overwritten implementation.
2348                for ( int i = this.modules.getImplementations().size() - 1;
2349                      i >= 0; i-- )
2350                {
2351                    final Implementation resourceImpl =
2352                        this.modules.getImplementations().
2353                        getImplementation( i );
2354 
2355                    if ( !"default".equals( resourceImpl.getName() ) )
2356                    {
2357                        continue;
2358                    }
2359 
2360                    for ( int s = resourceImpl.getImplementedSpecifications().
2361                        size() - 1; s >= 0; s-- )
2362                    {
2363                        final Specification implemented =
2364                            resourceImpl.getImplementedSpecifications().
2365                            getSpecification( s );
2366 
2367                        if ( implemented.getIdentifier().equals(
2368                            platformSpec.getIdentifier() ) )
2369                        {
2370                            if ( LOGGER.isLoggable( Level.FINE ) )
2371                            {
2372                                LOGGER.log( Level.FINE,
2373                                            DefaultModelBundle.getInstance().
2374                                    getOverwrittenDefaultImplementationMessage(
2375                                    Locale.getDefault(),
2376                                    platformSpec.getIdentifier(),
2377                                    platformSpec.getIdentifier(),
2378                                    resourceImpl.getIdentifier() ) );
2379 
2380                            }
2381 
2382                            overwritten = true;
2383                            break;
2384                        }
2385                    }
2386                }
2387 
2388                final String implVersion = platformClass.getPackage().
2389                    getImplementationVersion();
2390 
2391                String implVendor = platformClass.getPackage().
2392                    getImplementationVendor();
2393 
2394                if ( implVendor == null )
2395                {
2396                    implVendor = DefaultModelBundle.getInstance().
2397                        getUnknownVendorMessage( Locale.getDefault() );
2398 
2399                }
2400 
2401                if ( implVersion != null && !overwritten )
2402                {
2403                    final Implementation defaultImpl = this.getImplementation(
2404                        platformClass.getName() );
2405 
2406                    defaultImpl.setModelVersion( MODEL_VERSION );
2407                    defaultImpl.setVersion( implVersion );
2408                    defaultImpl.setVendor( implVendor );
2409                    defaultImpl.setDocumentation(
2410                        platformSpec.getDocumentation() );
2411 
2412                    defaultImpl.setFinal( true );
2413                    defaultImpl.setModuleName( PLATFORM_MODULE_NAME );
2414                    defaultImpl.setName( "default" );
2415 
2416                    final Specifications implemented = new Specifications();
2417                    implemented.setSpecifications( new Specification[]
2418                        {
2419                            platformSpec
2420                        } );
2421 
2422                    defaultImpl.setImplementedSpecifications( implemented );
2423 
2424                    final Implementation[] current = this.getPlatformModule().
2425                        getImplementations().getImplementations();
2426 
2427                    final Implementation[] tmp =
2428                        new Implementation[ current.length + 1 ];
2429 
2430                    System.arraycopy( current, 0, tmp, 0, current.length );
2431                    tmp[current.length] = defaultImpl;
2432 
2433                    final Implementations impls = new Implementations();
2434                    impls.setImplementations( tmp );
2435 
2436                    this.getPlatformModule().setImplementations( impls );
2437 
2438                    if ( LOGGER.isLoggable( Level.FINE ) )
2439                    {
2440                        LOGGER.log( Level.FINE, DefaultModelBundle.getInstance().
2441                            getAddedDefaultImplementationMessage(
2442                            Locale.getDefault(), defaultImpl.getIdentifier(),
2443                            platformSpec.getIdentifier(), implVersion,
2444                            implVendor ) );
2445 
2446                    }
2447 
2448                }
2449            }
2450        }
2451        catch ( final NoSuchMethodException e )
2452        {
2453            // No static accessor.
2454        }
2455    }
2456 
2457    /**
2458     * Updates the value of a property.
2459     *
2460     * @param typeName the name of the type of {@code property}.
2461     * @param value the value of {@code property}.
2462     * @param property the property to update.
2463     */
2464    private void updatePropertyValue( final String typeName,
2465                                      final String value,
2466                                      final Property property )
2467    {
2468        final Class objectType;
2469 
2470        if ( typeName.equals( Boolean.TYPE.getName() ) )
2471        {
2472            property.setType( Boolean.TYPE );
2473            objectType = Boolean.class;
2474        }
2475        else if ( typeName.equals( Byte.TYPE.getName() ) )
2476        {
2477            property.setType( Byte.TYPE );
2478            objectType = Byte.class;
2479        }
2480        else if ( typeName.equals( Character.TYPE.getName() ) )
2481        {
2482            property.setType( Character.TYPE );
2483            objectType = Character.class;
2484        }
2485        else if ( typeName.equals( Double.TYPE.getName() ) )
2486        {
2487            property.setType( Double.TYPE );
2488            objectType = Double.class;
2489        }
2490        else if ( typeName.equals( Float.TYPE.getName() ) )
2491        {
2492            property.setType( Float.TYPE );
2493            objectType = Float.class;
2494        }
2495        else if ( typeName.equals( Integer.TYPE.getName() ) )
2496        {
2497            property.setType( Integer.TYPE );
2498            objectType = Integer.class;
2499        }
2500        else if ( typeName.equals( Long.TYPE.getName() ) )
2501        {
2502            property.setType( Long.TYPE );
2503            objectType = Long.class;
2504        }
2505        else if ( typeName.equals( Short.TYPE.getName() ) )
2506        {
2507            property.setType( Short.TYPE );
2508            objectType = Short.class;
2509        }
2510        else if ( typeName.equals( Boolean.class.getName() ) )
2511        {
2512            property.setType( Boolean.class );
2513            objectType = Boolean.class;
2514        }
2515        else if ( typeName.equals( Byte.class.getName() ) )
2516        {
2517            property.setType( Byte.class );
2518            objectType = Byte.class;
2519        }
2520        else if ( typeName.equals( Character.class.getName() ) )
2521        {
2522            property.setType( Character.class );
2523            objectType = Character.class;
2524        }
2525        else if ( typeName.equals( Double.class.getName() ) )
2526        {
2527            property.setType( Double.class );
2528            objectType = Double.class;
2529        }
2530        else if ( typeName.equals( Float.class.getName() ) )
2531        {
2532            property.setType( Float.class );
2533            objectType = Float.class;
2534        }
2535        else if ( typeName.equals( Integer.class.getName() ) )
2536        {
2537            property.setType( Integer.class );
2538            objectType = Integer.class;
2539        }
2540        else if ( typeName.equals( Long.class.getName() ) )
2541        {
2542            property.setType( Long.class );
2543            objectType = Long.class;
2544        }
2545        else if ( typeName.equals( Short.class.getName() ) )
2546        {
2547            property.setType( Short.class );
2548            objectType = Short.class;
2549        }
2550        else if ( typeName.equals( String.class.getName() ) )
2551        {
2552            property.setType( String.class );
2553            objectType = String.class;
2554        }
2555        else
2556        {
2557            throw new ModelError( DefaultModelBundle.getInstance().
2558                getUnsupportedPropertyTypeMessage( Locale.getDefault(),
2559                                                   typeName ) );
2560 
2561        }
2562 
2563        if ( value != null )
2564        {
2565            try
2566            {
2567                // Special handling for class Character which does not provide
2568                // a constructor taking a string.
2569                final Constructor ctor;
2570                final Object arg;
2571 
2572                if ( objectType == Character.class )
2573                {
2574                    ctor = objectType.getDeclaredConstructor( CTOR_ARGS_CHAR );
2575                    arg = new Character( value.charAt( 0 ) );
2576                }
2577                else
2578                {
2579                    ctor = objectType.getDeclaredConstructor( CTOR_ARGS_STRING );
2580                    arg = value;
2581                }
2582 
2583                property.setValue( ctor.newInstance( new Object[]
2584                    {
2585                        arg
2586                    } ) );
2587 
2588            }
2589            catch ( final SecurityException e )
2590            {
2591                throw new ModelError( e );
2592            }
2593            catch ( final NoSuchMethodException e )
2594            {
2595                throw new ModelError( e );
2596            }
2597            catch ( final InvocationTargetException e )
2598            {
2599                final Throwable targetException = e.getTargetException();
2600 
2601                if ( targetException instanceof Error )
2602                {
2603                    throw (Error) targetException;
2604                }
2605                else if ( targetException instanceof RuntimeException )
2606                {
2607                    throw (RuntimeException) targetException;
2608                }
2609                else
2610                {
2611                    throw new ModelError( targetException == null
2612                                          ? e
2613                                          : targetException );
2614 
2615                }
2616            }
2617            catch ( final IllegalAccessException e )
2618            {
2619                throw new ModelError( e );
2620            }
2621            catch ( final InstantiationException e )
2622            {
2623                throw new ModelError( e );
2624            }
2625        }
2626        else
2627        {
2628            property.setValue( null );
2629        }
2630    }
2631 
2632    //------------------------------------------------------------DefaultModel--
2633}

[all classes][org.jdtaus.core.container.ri.client]
EMMA 2.1.5320 (stable) (C) Vladimir Roubtsov