EMMA Coverage Report (generated Thu Jan 03 04:54:40 CET 2013)
[all classes][org.jomc.model]

COVERAGE SUMMARY FOR SOURCE FILE [InheritanceModel.java]

nameclass, %method, %block, %line, %
InheritanceModel.java100% (3/3)93%  (56/60)86%  (2429/2836)87%  (457.6/524)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class InheritanceModel$ContextState100% (1/1)50%  (2/4)76%  (29/38)92%  (2.8/3)
valueOf (String): InheritanceModel$ContextState 0%   (0/1)0%   (0/5)0%   (0/1)
values (): InheritanceModel$ContextState [] 0%   (0/1)0%   (0/4)0%   (0/1)
<static initializer> 100% (1/1)100% (24/24)100% (3/3)
InheritanceModel$ContextState (String, int): void 100% (1/1)100% (5/5)100% (1/1)
     
class InheritanceModel100% (1/1)95%  (40/42)85%  (2325/2723)87%  (431.8/498)
getSourceNodes (String): Set 0%   (0/1)0%   (0/20)0%   (0/5)
newSet (Collection): Set 0%   (0/1)0%   (0/5)0%   (0/1)
isOverriding (InheritanceModel$Node, InheritanceModel$Node): boolean 100% (1/1)50%  (10/20)67%  (4/6)
getXmlElementName (Element): QName 100% (1/1)65%  (11/17)67%  (2/3)
getDependencyNames (String): Set 100% (1/1)71%  (12/17)75%  (3/4)
getImplementationReferenceIdentifiers (String): Set 100% (1/1)71%  (12/17)75%  (3/4)
getJaxbElementNames (String): Set 100% (1/1)71%  (12/17)75%  (3/4)
getMessageNames (String): Set 100% (1/1)71%  (12/17)75%  (3/4)
getPropertyNames (String): Set 100% (1/1)71%  (12/17)75%  (3/4)
getSpecificationReferenceIdentifiers (String): Set 100% (1/1)71%  (12/17)75%  (3/4)
getXmlElementNames (String): Set 100% (1/1)71%  (12/17)75%  (3/4)
getDependencyNodes (String, String): Set 100% (1/1)71%  (25/35)80%  (8/10)
getImplementationReferenceNodes (String, String): Set 100% (1/1)71%  (25/35)80%  (8/10)
getJaxbElementNodes (String, QName): Set 100% (1/1)71%  (25/35)80%  (8/10)
getMessageNodes (String, String): Set 100% (1/1)71%  (25/35)80%  (8/10)
getPropertyNodes (String, String): Set 100% (1/1)71%  (25/35)80%  (8/10)
getSpecificationReferenceNodes (String, String): Set 100% (1/1)71%  (25/35)80%  (8/10)
getXmlElementNodes (String, QName): Set 100% (1/1)71%  (25/35)80%  (8/10)
addClassDeclarationNodes (String, InheritanceModel$Node): void 100% (1/1)72%  (579/805)73%  (90/124)
<static initializer> 100% (1/1)75%  (6/8)75%  (0.8/1)
prepareContext (String): void 100% (1/1)78%  (62/80)94%  (13.2/14)
isInheritableNode (InheritanceModel$Node): boolean 100% (1/1)86%  (6/7)85%  (0.8/1)
InheritanceModel (Modules): void 100% (1/1)92%  (60/65)95%  (21/22)
addNode (Map, InheritanceModel$Node, Object): void 100% (1/1)100% (19/19)100% (6/6)
collectEffectiveNodes (String, InheritanceModel$Node): void 100% (1/1)100% (265/265)100% (39/39)
collectNodes (String, Implementation, InheritanceModel$Node, LinkedList): void 100% (1/1)100% (653/653)100% (96/96)
effectiveNodes (Map, String, Object): Set 100% (1/1)100% (6/6)100% (1/1)
getClassDeclaration (Implementation): Implementation 100% (1/1)100% (63/63)100% (11/11)
getDirectEffectiveNodes (Map, String): Map 100% (1/1)100% (90/90)100% (20/20)
getEffectiveNodes (Map, String, String): Map 100% (1/1)100% (7/7)100% (1/1)
inheritNodes (Map, Map, InheritanceModel$Node): void 100% (1/1)100% (40/40)100% (7/7)
isDirectEffectiveNode (InheritanceModel$Node, String): boolean 100% (1/1)100% (14/14)100% (1/1)
isDirectNode (InheritanceModel$Node, String): boolean 100% (1/1)100% (6/6)100% (1/1)
isDirectSpecifiedNode (InheritanceModel$Node, String): boolean 100% (1/1)100% (14/14)100% (1/1)
map (Map, Object): Map 100% (1/1)100% (16/16)100% (5/5)
newMap (): Map 100% (1/1)100% (4/4)100% (1/1)
newMap (int): Map 100% (1/1)100% (5/5)100% (1/1)
newSet (): Set 100% (1/1)100% (4/4)100% (1/1)
newSet (int): Set 100% (1/1)100% (5/5)100% (1/1)
nodes (Map, Object): Set 100% (1/1)100% (16/16)100% (5/5)
overrideNodes (Map, InheritanceModel$Node, Map): void 100% (1/1)100% (98/98)100% (24/24)
unmodifiableSet (Set): Set 100% (1/1)100% (7/7)100% (1/1)
     
class InheritanceModel$Node100% (1/1)100% (14/14)100% (75/75)100% (23/23)
InheritanceModel$Node (Implementation, Specification, Implementation, Inherit... 100% (1/1)100% (34/34)100% (11/11)
access$000 (InheritanceModel$Node): LinkedList 100% (1/1)100% (3/3)100% (1/1)
access$100 (InheritanceModel$Node): Set 100% (1/1)100% (3/3)100% (1/1)
getClassDeclaration (): Implementation 100% (1/1)100% (3/3)100% (1/1)
getDescendant (): InheritanceModel$Node 100% (1/1)100% (3/3)100% (1/1)
getImplementation (): Implementation 100% (1/1)100% (3/3)100% (1/1)
getModelObject (): Object 100% (1/1)100% (3/3)100% (1/1)
getModifiableOverriddenNodes (): Set 100% (1/1)100% (3/3)100% (1/1)
getModifiablePath (): LinkedList 100% (1/1)100% (3/3)100% (1/1)
getOverriddenNodes (): Set 100% (1/1)100% (4/4)100% (1/1)
getPath (): List 100% (1/1)100% (4/4)100% (1/1)
getSpecification (): Specification 100% (1/1)100% (3/3)100% (1/1)
isFinal (): boolean 100% (1/1)100% (3/3)100% (1/1)
isOverride (): boolean 100% (1/1)100% (3/3)100% (1/1)

1/*
2 *   Copyright (C) Christian Schulte, 2011-325
3 *   All rights reserved.
4 *
5 *   Redistribution and use in source and binary forms, with or without
6 *   modification, are permitted provided that the following conditions
7 *   are met:
8 *
9 *     o Redistributions of source code must retain the above copyright
10 *       notice, this list of conditions and the following disclaimer.
11 *
12 *     o Redistributions in binary form must reproduce the above copyright
13 *       notice, this list of conditions and the following disclaimer in
14 *       the documentation and/or other materials provided with the
15 *       distribution.
16 *
17 *   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
18 *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
19 *   AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20 *   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
21 *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 *   $JOMC: InheritanceModel.java 4613 2012-09-22 10:07:08Z schulte $
29 *
30 */
31package org.jomc.model;
32 
33import java.util.Collection;
34import java.util.Collections;
35import java.util.HashMap;
36import java.util.HashSet;
37import java.util.Iterator;
38import java.util.LinkedList;
39import java.util.List;
40import java.util.Map;
41import java.util.Set;
42import javax.xml.bind.JAXBElement;
43import javax.xml.namespace.QName;
44import org.w3c.dom.Element;
45 
46/**
47 * Inheritance model.
48 *
49 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
50 * @version $JOMC: InheritanceModel.java 4613 2012-09-22 10:07:08Z schulte $
51 * @since 1.2
52 */
53public class InheritanceModel
54{
55 
56    /**
57     * Inheritance model node.
58     *
59     * @param <T> The type of the model object of the node.
60     *
61     * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
62     * @version $JOMC: InheritanceModel.java 4613 2012-09-22 10:07:08Z schulte $
63     * @since 1.2
64     */
65    public static class Node<T>
66    {
67 
68        /** The implementation the node originates from. */
69        private final Implementation implementation;
70 
71        /** The specification the node originates from. */
72        private final Specification specification;
73 
74        /** The class declaration the node originates from. */
75        private final Implementation classDeclaration;
76 
77        /** The direct descendant node. */
78        private final Node<Implementation> descendant;
79 
80        /** The model object of the node. */
81        private final T modelObject;
82 
83        /** Flag indicating the node is the final node in an inheritance hierarchy. */
84        private final boolean _final;
85 
86        /** Flag indicating the node is intended to override an ancestor node. */
87        private final boolean override;
88 
89        /** The path to the node. */
90        private final LinkedList<Node<Implementation>> path = new LinkedList<Node<Implementation>>();
91 
92        /** The nodes overridden by the node. */
93        private final Set<Node<T>> overriddenNodes = new HashSet<Node<T>>();
94 
95        /**
96         * Creates a new {@code Node} instance.
97         *
98         * @param implementation The implementation the node originates from.
99         * @param specification The specification the node originates from or {@code null}.
100         * @param classDeclaration The class declaration the node originates from or {@code null}.
101         * @param descendant The direct descendant node of the node or {@code null}.
102         * @param modelObject The model object of the node.
103         * @param finalNode {@code true}, if the node is the final node in an inheritance hierarchy; {@code false},
104         * else.
105         * @param overrideNode {@code true}, if the node is intended to override an ancestor node; {@code false}, else.
106         */
107        public Node( final Implementation implementation, final Specification specification,
108                     final Implementation classDeclaration, final Node<Implementation> descendant, final T modelObject,
109                     final boolean finalNode, final boolean overrideNode )
110        {
111            super();
112            this.implementation = implementation;
113            this.specification = specification;
114            this.classDeclaration = classDeclaration;
115            this.descendant = descendant;
116            this.modelObject = modelObject;
117            this._final = finalNode;
118            this.override = overrideNode;
119        }
120 
121        /**
122         * Gets the implementation the node originates from.
123         *
124         * @return The implementation the node originates from.
125         */
126        public final Implementation getImplementation()
127        {
128            return this.implementation;
129        }
130 
131        /**
132         * Gets the specification the node originates from.
133         *
134         * @return The specification the node originates from or {@code null}, if the node does not originate from a
135         * specification.
136         */
137        public final Specification getSpecification()
138        {
139            return this.specification;
140        }
141 
142        /**
143         * Gets the class declaration the node originates from.
144         *
145         * @return The class declaration the node originates from or {@code null}, if the node does not originate from a
146         * class declaration.
147         */
148        public final Implementation getClassDeclaration()
149        {
150            return this.classDeclaration;
151        }
152 
153        /**
154         * Gets the direct descendant node of the node.
155         *
156         * @return The direct descendant node of the node or {@code null}.
157         *
158         * @see InheritanceModel#getSourceNodes(java.lang.String)
159         */
160        public final Node<Implementation> getDescendant()
161        {
162            return this.descendant;
163        }
164 
165        /**
166         * Gets the model object of the node.
167         *
168         * @return The model object of the node.
169         */
170        public final T getModelObject()
171        {
172            return this.modelObject;
173        }
174 
175        /**
176         * Gets a flag indicating the node is the final node in an inheritance hierarchy.
177         *
178         * @return {@code true}, if the node is the final node in an inheritance hierarchy; {@code false}, else.
179         */
180        public final boolean isFinal()
181        {
182            return this._final;
183        }
184 
185        /**
186         * Gets a flag indicating the node is intended to override an ancestor node.
187         *
188         * @return {@code true}, if the node is intended to override an ancestor; {@code false} else.
189         */
190        public final boolean isOverride()
191        {
192            return this.override;
193        }
194 
195        /**
196         * Gets a set of nodes overridden by the node.
197         *
198         * @return An unmodifiable set holding nodes overridden by the node.
199         */
200        public final Set<Node<T>> getOverriddenNodes()
201        {
202            return Collections.unmodifiableSet( this.overriddenNodes );
203        }
204 
205        /**
206         * Gets the path to the node.
207         *
208         * @return An unmodifiable list holding path elements.
209         */
210        public final List<Node<Implementation>> getPath()
211        {
212            return Collections.unmodifiableList( this.path );
213        }
214 
215        /**
216         * Gets a set of nodes overridden by the node.
217         *
218         * @return A modifiable set holding nodes overridden by the node.
219         *
220         * @see #getOverriddenNodes()
221         */
222        private Set<Node<T>> getModifiableOverriddenNodes()
223        {
224            return this.overriddenNodes;
225        }
226 
227        /**
228         * Gets the path to the node.
229         *
230         * @return A modifiable list holding path nodes of the node.
231         *
232         * @see #getPath()
233         */
234        private LinkedList<Node<Implementation>> getModifiablePath()
235        {
236            return this.path;
237        }
238 
239    }
240 
241    /** Enumeration of context states. */
242    private enum ContextState
243    {
244 
245        PREPARING,
246        PREPARED
247 
248    }
249 
250    /** The modules backing the model. */
251    private final Modules modules;
252 
253    /** {@code Dependency} nodes by context and dependency name. */
254    private final Map<String, Map<String, Set<Node<Dependency>>>> dependencies = newMap();
255 
256    /** {@code Dependency} nodes by context and implementation identifier. */
257    private final Map<String, Map<String, Map<String, Set<Node<Dependency>>>>> effDependencies = newMap();
258 
259    /** {@code Message} nodes by context and message name. */
260    private final Map<String, Map<String, Set<Node<Message>>>> messages = newMap();
261 
262    /** {@code Message} nodes by context and implementation identifier. */
263    private final Map<String, Map<String, Map<String, Set<Node<Message>>>>> effMessages = newMap();
264 
265    /** {@code Property} nodes by context and property name. */
266    private final Map<String, Map<String, Set<Node<Property>>>> properties = newMap();
267 
268    /** {@code Property} nodes by context and implementation identifier. */
269    private final Map<String, Map<String, Map<String, Set<Node<Property>>>>> effProperties = newMap();
270 
271    /** {@code SpecificationReference} nodes by context and specification identifier. */
272    private final Map<String, Map<String, Set<Node<SpecificationReference>>>> specReferences = newMap();
273 
274    /** {@code SpecificationReference} nodes by context and implementation identifier. */
275    private final Map<String, Map<String, Map<String, Set<Node<SpecificationReference>>>>> effSpecReferences =
276        newMap();
277 
278    /** {@code ImplementationReference} nodes by context and implementation reference identifier. */
279    private final Map<String, Map<String, Set<Node<ImplementationReference>>>> implReferences = newMap();
280 
281    /** {@code ImplementationReference} nodes by context and implementation identifier. */
282    private final Map<String, Map<String, Map<String, Set<Node<ImplementationReference>>>>> effImplReferences =
283        newMap();
284 
285    /** {@code Element} nodes by context and qualified name. */
286    private final Map<String, Map<QName, Set<Node<Element>>>> xmlElements = newMap();
287 
288    /** {@code Element} nodes by context and implementation identifier. */
289    private final Map<String, Map<String, Map<QName, Set<Node<Element>>>>> effXmlElements = newMap();
290 
291    /** {@code JAXBElement} nodes by context and qualified name. */
292    private final Map<String, Map<QName, Set<Node<JAXBElement<?>>>>> jaxbElements = newMap();
293 
294    /** {@code JAXBElement} nodes by context and implementation identifier. */
295    private final Map<String, Map<String, Map<QName, Set<Node<JAXBElement<?>>>>>> effJaxbElements =
296        newMap();
297 
298    /** {@code Implementation} nodes by context and implementation identifier. */
299    private final Map<String, Map<String, Node<Implementation>>> implementations = newMap();
300 
301    /** Source nodes of a hierarchy by context and implementation identifier. */
302    private final Map<String, Map<String, Node<Implementation>>> sourceNodes = newMap();
303 
304    /** Context states by context identifier. */
305    private final Map<String, ContextState> contextStates = newMap();
306 
307    /**
308     * Creates a new {@code InheritanceModel} instance.
309     *
310     * @param modules The modules backing the model.
311     *
312     * @throws NullPointerException if {@code modules} is {@code null}.
313     *
314     * @see Modules#clone()
315     */
316    public InheritanceModel( final Modules modules )
317    {
318        super();
319 
320        if ( modules == null )
321        {
322            throw new NullPointerException( "modules" );
323        }
324 
325        this.modules = modules.clone();
326    }
327 
328    /**
329     * Gets a set holding the names of all dependencies of an implementation.
330     *
331     * @param implementation The identifier of the implementation to get the names of all dependencies of.
332     *
333     * @return An unmodifiable set holding the names of all dependencies of the implementation identified by
334     * {@code implementation}.
335     *
336     * @throws NullPointerException if {@code implementation} is {@code null}.
337     */
338    public Set<String> getDependencyNames( final String implementation )
339    {
340        if ( implementation == null )
341        {
342            throw new NullPointerException( "implementation" );
343        }
344 
345        this.prepareContext( implementation );
346        return Collections.unmodifiableSet( map( this.dependencies, implementation ).keySet() );
347    }
348 
349    /**
350     * Gets a set holding effective dependency nodes of an implementation.
351     *
352     * @param implementation The identifier of the implementation to get effective dependency nodes of.
353     * @param name The dependency name to get effective nodes for.
354     *
355     * @return An unmodifiable set holding effective dependency nodes matching {@code name} of the implementation
356     * identified by {@code implementation}.
357     *
358     * @throws NullPointerException if {@code implementation} or {@code name} is {@code null}.
359     *
360     * @see #getDependencyNames(java.lang.String)
361     */
362    public Set<Node<Dependency>> getDependencyNodes( final String implementation, final String name )
363    {
364        if ( implementation == null )
365        {
366            throw new NullPointerException( "implementation" );
367        }
368        if ( name == null )
369        {
370            throw new NullPointerException( "name" );
371        }
372 
373        this.prepareContext( implementation );
374        Set<Node<Dependency>> set = null;
375 
376        final Map<String, Set<Node<Dependency>>> map =
377            getEffectiveNodes( this.effDependencies, implementation, implementation );
378 
379        if ( map != null )
380        {
381            set = map.get( name );
382        }
383 
384        return unmodifiableSet( set );
385    }
386 
387    /**
388     * Gets a set holding the identifiers of all implementation references of an implementation.
389     *
390     * @param implementation The identifier of the implementation to get the identifiers of all implementation
391     * references of.
392     *
393     * @return An unmodifiable set holding the identifiers of all implementation references of the implementation
394     * identified by {@code implementation}.
395     *
396     * @throws NullPointerException if {@code implementation} is {@code null}.
397     */
398    public Set<String> getImplementationReferenceIdentifiers( final String implementation )
399    {
400        if ( implementation == null )
401        {
402            throw new NullPointerException( "implementation" );
403        }
404 
405        this.prepareContext( implementation );
406        return Collections.unmodifiableSet( map( this.implReferences, implementation ).keySet() );
407    }
408 
409    /**
410     * Gets a set holding effective implementation reference nodes of an implementation.
411     *
412     * @param implementation The identifier of the implementation to get effective implementation reference nodes of.
413     * @param identifier The implementation reference identifier to get effective nodes for.
414     *
415     * @return An unmodifiable set holding effective implementation reference nodes matching {@code identifier} of the
416     * implementation identified by {@code implementation}.
417     *
418     * @throws NullPointerException if {@code implementation} or {@code identifier} is {@code null}.
419     *
420     * @see #getImplementationReferenceIdentifiers(java.lang.String)
421     */
422    public Set<Node<ImplementationReference>> getImplementationReferenceNodes( final String implementation,
423                                                                               final String identifier )
424    {
425        if ( implementation == null )
426        {
427            throw new NullPointerException( "implementation" );
428        }
429        if ( identifier == null )
430        {
431            throw new NullPointerException( "identifier" );
432        }
433 
434        this.prepareContext( implementation );
435        Set<Node<ImplementationReference>> set = null;
436        final Map<String, Set<Node<ImplementationReference>>> map =
437            getEffectiveNodes( this.effImplReferences, implementation, implementation );
438 
439        if ( map != null )
440        {
441            set = map.get( identifier );
442        }
443 
444        return unmodifiableSet( set );
445    }
446 
447    /**
448     * Gets a set holding the qualified names of all XML elements of an implementation.
449     *
450     * @param implementation The identifier of the implementation to get the qualified names of all XML elements of.
451     *
452     * @return An unmodifiable set holding the qualified names of all XML elements of the implementation identified by
453     * {@code implementation}.
454     *
455     * @throws NullPointerException if {@code implementation} is {@code null}.
456     */
457    public Set<QName> getJaxbElementNames( final String implementation )
458    {
459        if ( implementation == null )
460        {
461            throw new NullPointerException( "implementation" );
462        }
463 
464        this.prepareContext( implementation );
465        return Collections.unmodifiableSet( map( this.jaxbElements, implementation ).keySet() );
466    }
467 
468    /**
469     * Gets a set holding effective JAXB element nodes of an implementation.
470     *
471     * @param implementation The identifier of the implementation to get effective JAXB element nodes of.
472     * @param name The qualified JAXB element name to get effective nodes for.
473     *
474     * @return An unmodifiable set holding effective JAXB element nodes matching {@code name} of the implementation
475     * identified by {@code implementation}.
476     *
477     * @throws NullPointerException if {@code implementation} or {@code name} is {@code null}.
478     *
479     * @see #getJaxbElementNames(java.lang.String)
480     */
481    public Set<Node<JAXBElement<?>>> getJaxbElementNodes( final String implementation, final QName name )
482    {
483        if ( implementation == null )
484        {
485            throw new NullPointerException( "implementation" );
486        }
487        if ( name == null )
488        {
489            throw new NullPointerException( "name" );
490        }
491 
492        this.prepareContext( implementation );
493        Set<Node<JAXBElement<?>>> set = null;
494        final Map<QName, Set<Node<JAXBElement<?>>>> map =
495            getEffectiveNodes( this.effJaxbElements, implementation, implementation );
496 
497        if ( map != null )
498        {
499            set = map.get( name );
500        }
501 
502        return unmodifiableSet( set );
503    }
504 
505    /**
506     * Gets a set holding the names of all messages of an implementation.
507     *
508     * @param implementation The identifier of the implementation to get the names of all messages of.
509     *
510     * @return An unmodifiable set holding the names of all messages of the implementation identified by
511     * {@code implementation}.
512     *
513     * @throws NullPointerException if {@code implementation} is {@code null}.
514     */
515    public Set<String> getMessageNames( final String implementation )
516    {
517        if ( implementation == null )
518        {
519            throw new NullPointerException( "implementation" );
520        }
521 
522        this.prepareContext( implementation );
523        return Collections.unmodifiableSet( map( this.messages, implementation ).keySet() );
524    }
525 
526    /**
527     * Gets a set holding effective message nodes of an implementation.
528     *
529     * @param implementation The identifier of the implementation to get effective message nodes of.
530     * @param name The message name to get effective nodes for.
531     *
532     * @return An unmodifiable set holding effective message nodes matching {@code name} of the implementation
533     * identified by {@code implementation}.
534     *
535     * @throws NullPointerException if {@code implementation} or {@code name} is {@code null}.
536     *
537     * @see #getMessageNames(java.lang.String)
538     */
539    public Set<Node<Message>> getMessageNodes( final String implementation, final String name )
540    {
541        if ( implementation == null )
542        {
543            throw new NullPointerException( "implementation" );
544        }
545        if ( name == null )
546        {
547            throw new NullPointerException( "name" );
548        }
549 
550        this.prepareContext( implementation );
551        Set<Node<Message>> set = null;
552        final Map<String, Set<Node<Message>>> map =
553            getEffectiveNodes( this.effMessages, implementation, implementation );
554 
555        if ( map != null )
556        {
557            set = map.get( name );
558        }
559 
560        return unmodifiableSet( set );
561    }
562 
563    /**
564     * Gets a set holding the names of all properties of an implementation.
565     *
566     * @param implementation The identifier of the implementation to get the names of all properties of.
567     *
568     * @return An unmodifiable set holding the names of all properties of the implementation identified by
569     * {@code implementation}.
570     *
571     * @throws NullPointerException if {@code implementation} is {@code null}.
572     */
573    public Set<String> getPropertyNames( final String implementation )
574    {
575        if ( implementation == null )
576        {
577            throw new NullPointerException( "implementation" );
578        }
579 
580        this.prepareContext( implementation );
581        return Collections.unmodifiableSet( map( this.properties, implementation ).keySet() );
582    }
583 
584    /**
585     * Gets a set holding effective property nodes of an implementation.
586     *
587     * @param implementation The identifier of the implementation to get effective property nodes of.
588     * @param name The property name to get effective nodes for.
589     *
590     * @return An unmodifiable set holding effective property nodes matching {@code name} of the implementation
591     * identified by {@code implementation}.
592     *
593     * @throws NullPointerException if {@code implementation} or {@code name} is {@code null}.
594     *
595     * @see #getPropertyNames(java.lang.String)
596     */
597    public Set<Node<Property>> getPropertyNodes( final String implementation, final String name )
598    {
599        if ( implementation == null )
600        {
601            throw new NullPointerException( "implementation" );
602        }
603        if ( name == null )
604        {
605            throw new NullPointerException( "name" );
606        }
607 
608        this.prepareContext( implementation );
609        Set<Node<Property>> set = null;
610        final Map<String, Set<Node<Property>>> map =
611            getEffectiveNodes( this.effProperties, implementation, implementation );
612 
613        if ( map != null )
614        {
615            set = map.get( name );
616        }
617 
618        return unmodifiableSet( set );
619    }
620 
621    /**
622     * Gets a set holding source nodes of an implementation.
623     *
624     * @param implementation The identifier of the implementation to get source nodes of.
625     *
626     * @return An unmodifiable set holding source nodes of the implementation identified by {@code implementation}.
627     *
628     * @throws NullPointerException if {@code implementation} is {@code null}.
629     *
630     * @see Node#getDescendant()
631     */
632    public Set<Node<Implementation>> getSourceNodes( final String implementation )
633    {
634        if ( implementation == null )
635        {
636            throw new NullPointerException( "implementation" );
637        }
638 
639        this.prepareContext( implementation );
640        final Collection<Node<Implementation>> col = map( this.sourceNodes, implementation ).values();
641        return unmodifiableSet( newSet( col ) );
642    }
643 
644    /**
645     * Gets a set holding the identifiers of all specification references of an implementation.
646     *
647     * @param implementation The identifier of the implementation to get the identifiers of all specification references
648     * of.
649     *
650     * @return An unmodifiable set holding the identifiers of all specification references of the implementation
651     * identified by {@code implementation}.
652     *
653     * @throws NullPointerException if {@code implementation} is {@code null}.
654     */
655    public Set<String> getSpecificationReferenceIdentifiers( final String implementation )
656    {
657        if ( implementation == null )
658        {
659            throw new NullPointerException( "implementation" );
660        }
661 
662        this.prepareContext( implementation );
663        return Collections.unmodifiableSet( map( this.specReferences, implementation ).keySet() );
664    }
665 
666    /**
667     * Gets a set holding effective specification reference nodes of an implementation.
668     *
669     * @param implementation The identifier of the implementation to get effective specification reference nodes of.
670     * @param identifier The specification reference identifier to get effective nodes for.
671     *
672     * @return An unmodifiable set holding effective specification reference nodes matching {@code identifier} of the
673     * implementation identified by {@code implementation}.
674     *
675     * @throws NullPointerException if {@code implementation} or {@code identifier} is {@code null}.
676     *
677     * @see #getSpecificationReferenceIdentifiers(java.lang.String)
678     */
679    public Set<Node<SpecificationReference>> getSpecificationReferenceNodes( final String implementation,
680                                                                             final String identifier )
681    {
682        if ( implementation == null )
683        {
684            throw new NullPointerException( "implementation" );
685        }
686        if ( identifier == null )
687        {
688            throw new NullPointerException( "identifier" );
689        }
690 
691        this.prepareContext( implementation );
692        Set<Node<SpecificationReference>> set = null;
693        final Map<String, Set<Node<SpecificationReference>>> map =
694            getEffectiveNodes( this.effSpecReferences, implementation, implementation );
695 
696        if ( map != null )
697        {
698            set = map.get( identifier );
699        }
700 
701        return unmodifiableSet( set );
702    }
703 
704    /**
705     * Gets a set holding the qualified names of all XML elements of an implementation.
706     *
707     * @param implementation The identifier of the implementation to get the qualified names of all XML elements of.
708     *
709     * @return An unmodifiable set holding the qualified names of all XML elements of the implementation identified by
710     * {@code implementation}.
711     *
712     * @throws NullPointerException if {@code implementation} is {@code null}.
713     */
714    public Set<QName> getXmlElementNames( final String implementation )
715    {
716        if ( implementation == null )
717        {
718            throw new NullPointerException( "implementation" );
719        }
720 
721        this.prepareContext( implementation );
722        return Collections.unmodifiableSet( map( this.xmlElements, implementation ).keySet() );
723    }
724 
725    /**
726     * Gets a set holding effective XML element nodes of an implementation.
727     *
728     * @param implementation The identifier of the implementation to get effective XML element nodes of.
729     * @param name The qualified XML element name to get effective nodes for.
730     *
731     * @return An unmodifiable set holding effective XML element nodes matching {@code name} of the implementation
732     * identified by {@code implementation}.
733     *
734     * @throws NullPointerException if {@code implementation} or {@code name} is {@code null}.
735     *
736     * @see #getXmlElementNames(java.lang.String)
737     */
738    public Set<Node<Element>> getXmlElementNodes( final String implementation, final QName name )
739    {
740        if ( implementation == null )
741        {
742            throw new NullPointerException( "implementation" );
743        }
744        if ( name == null )
745        {
746            throw new NullPointerException( "name" );
747        }
748 
749        this.prepareContext( implementation );
750        Set<Node<Element>> set = null;
751        final Map<QName, Set<Node<Element>>> map =
752            getEffectiveNodes( this.effXmlElements, implementation, implementation );
753 
754        if ( map != null )
755        {
756            set = map.get( name );
757        }
758 
759        return unmodifiableSet( set );
760    }
761 
762    private void prepareContext( final String context )
763    {
764        ContextState state = this.contextStates.get( context );
765 
766        if ( state == null )
767        {
768            state = ContextState.PREPARING;
769            this.contextStates.put( context, state );
770 
771            final Implementation i = this.modules.getImplementation( context );
772 
773            if ( i != null )
774            {
775                this.collectNodes( context, i, null, null );
776 
777                for ( Node<Implementation> source : map( this.sourceNodes, context ).values() )
778                {
779                    this.collectEffectiveNodes( context, source );
780                }
781            }
782 
783            state = ContextState.PREPARED;
784            this.contextStates.put( context, state );
785        }
786 
787        assert state == ContextState.PREPARED :
788            "Unexpected context state '" + state + "' for context '" + context + "'.";
789 
790    }
791 
792    private void collectNodes( final String context, final Implementation declaration,
793                               final Node<Implementation> descendant, LinkedList<Node<Implementation>> path )
794    {
795        if ( path == null )
796        {
797            path = new LinkedList<Node<Implementation>>();
798        }
799 
800        final Map<String, Node<Implementation>> contextImplementations = map( this.implementations, context );
801 
802        if ( declaration != null && !contextImplementations.containsKey( declaration.getIdentifier() ) )
803        {
804            final Node<Implementation> declarationNode = new Node<Implementation>(
805                declaration, null, null, descendant, declaration, declaration.isFinal(), false );
806 
807            declarationNode.getModifiablePath().addAll( path );
808 
809            contextImplementations.put( declaration.getIdentifier(), declarationNode );
810 
811            path.addLast( declarationNode );
812 
813            if ( declaration.getDependencies() != null )
814            {
815                for ( int i = 0, s0 = declaration.getDependencies().getDependency().size(); i < s0; i++ )
816                {
817                    final Dependency d = declaration.getDependencies().getDependency().get( i );
818                    final Node<Dependency> node =
819                        new Node<Dependency>( declaration, null, null, descendant, d, d.isFinal(), d.isOverride() );
820 
821                    node.getModifiablePath().addAll( path );
822 
823                    addNode( map( this.dependencies, context ), node, node.getModelObject().getName() );
824                }
825            }
826 
827            if ( declaration.getMessages() != null )
828            {
829                for ( int i = 0, s0 = declaration.getMessages().getMessage().size(); i < s0; i++ )
830                {
831                    final Message m = declaration.getMessages().getMessage().get( i );
832                    final Node<Message> node =
833                        new Node<Message>( declaration, null, null, descendant, m, m.isFinal(), m.isOverride() );
834 
835                    node.getModifiablePath().addAll( path );
836 
837                    addNode( map( this.messages, context ), node, node.getModelObject().getName() );
838                }
839 
840                if ( !declaration.getMessages().getReference().isEmpty() )
841                {
842                    final Module m = this.modules.getModuleOfImplementation( declaration.getIdentifier() );
843 
844                    if ( m != null && m.getMessages() != null )
845                    {
846                        for ( int i = 0, s0 = declaration.getMessages().getReference().size(); i < s0; i++ )
847                        {
848                            final MessageReference r = declaration.getMessages().getReference().get( i );
849                            Message msg = m.getMessages().getMessage( r.getName() );
850 
851                            if ( msg != null )
852                            {
853                                msg = msg.clone();
854                                msg.setFinal( r.isFinal() );
855                                msg.setOverride( r.isOverride() );
856 
857                                final Node<Message> node = new Node<Message>(
858                                    declaration, null, null, descendant, msg, msg.isFinal(), msg.isOverride() );
859 
860                                node.getModifiablePath().addAll( path );
861 
862                                addNode( map( this.messages, context ), node, node.getModelObject().getName() );
863                            }
864                        }
865                    }
866                }
867            }
868 
869            if ( declaration.getProperties() != null )
870            {
871                for ( int i = 0, s0 = declaration.getProperties().getProperty().size(); i < s0; i++ )
872                {
873                    final Property p = declaration.getProperties().getProperty().get( i );
874                    final Node<Property> node =
875                        new Node<Property>( declaration, null, null, descendant, p, p.isFinal(), p.isOverride() );
876 
877                    node.getModifiablePath().addAll( path );
878 
879                    addNode( map( this.properties, context ), node, node.getModelObject().getName() );
880                }
881 
882                if ( !declaration.getProperties().getReference().isEmpty() )
883                {
884                    final Module m = this.modules.getModuleOfImplementation( declaration.getIdentifier() );
885 
886                    if ( m != null && m.getProperties() != null )
887                    {
888                        for ( int i = 0, s0 = declaration.getProperties().getReference().size(); i < s0; i++ )
889                        {
890                            final PropertyReference r = declaration.getProperties().getReference().get( i );
891                            Property p = m.getProperties().getProperty( r.getName() );
892 
893                            if ( p != null )
894                            {
895                                p = p.clone();
896                                p.setFinal( r.isFinal() );
897                                p.setOverride( r.isOverride() );
898 
899                                final Node<Property> node = new Node<Property>(
900                                    declaration, null, null, descendant, p, p.isFinal(), p.isOverride() );
901 
902                                node.getModifiablePath().addAll( path );
903 
904                                addNode( map( this.properties, context ), node, node.getModelObject().getName() );
905                            }
906                        }
907                    }
908                }
909            }
910 
911            if ( declaration.getSpecifications() != null )
912            {
913                for ( int i = 0, s0 = declaration.getSpecifications().getReference().size(); i < s0; i++ )
914                {
915                    final SpecificationReference r = declaration.getSpecifications().getReference().get( i );
916                    final Node<SpecificationReference> node = new Node<SpecificationReference>(
917                        declaration, null, null, descendant, r, r.isFinal(), r.isOverride() );
918 
919                    node.getModifiablePath().addAll( path );
920 
921                    addNode( map( this.specReferences, context ), node, node.getModelObject().getIdentifier() );
922 
923                    final Specification s = this.modules.getSpecification( r.getIdentifier() );
924 
925                    if ( s != null && s.getProperties() != null )
926                    {
927                        for ( int j = 0, s1 = s.getProperties().getProperty().size(); j < s1; j++ )
928                        {
929                            final Property p = s.getProperties().getProperty().get( j );
930                            final Node<Property> n =
931                                new Node<Property>( declaration, s, null, descendant, p, p.isFinal(), p.isOverride() );
932 
933                            n.getModifiablePath().addAll( path );
934 
935                            addNode( map( this.properties, context ), n, n.getModelObject().getName() );
936                        }
937                    }
938                }
939            }
940 
941            if ( !declaration.getAny().isEmpty() )
942            {
943                for ( int i = 0, s0 = declaration.getAny().size(); i < s0; i++ )
944                {
945                    final Object any = declaration.getAny().get( i );
946 
947                    if ( any instanceof Element )
948                    {
949                        final Element e = (Element) any;
950                        final Node<Element> node =
951                            new Node<Element>( declaration, null, null, descendant, e, false, false );
952 
953                        node.getModifiablePath().addAll( path );
954 
955                        addNode( map( this.xmlElements, context ), node, getXmlElementName( e ) );
956                        continue;
957                    }
958 
959                    if ( any instanceof JAXBElement<?> )
960                    {
961                        final JAXBElement<?> e = (JAXBElement<?>) any;
962                        boolean _final = false;
963                        boolean override = false;
964 
965                        if ( e.getValue() instanceof Inheritable )
966                        {
967                            _final = ( (Inheritable) e.getValue() ).isFinal();
968                            override = ( (Inheritable) e.getValue() ).isOverride();
969                        }
970 
971                        final Node<JAXBElement<?>> node =
972                            new Node<JAXBElement<?>>( declaration, null, null, descendant, e, _final, override );
973 
974                        node.getModifiablePath().addAll( path );
975 
976                        addNode( map( this.jaxbElements, context ), node, e.getName() );
977                        continue;
978                    }
979                }
980            }
981 
982            if ( declaration.getImplementations() != null
983                 && !declaration.getImplementations().getReference().isEmpty() )
984            {
985                for ( int i = 0, s0 = declaration.getImplementations().getReference().size(); i < s0; i++ )
986                {
987                    final ImplementationReference r = declaration.getImplementations().getReference().get( i );
988                    final Node<ImplementationReference> node = new Node<ImplementationReference>(
989                        declaration, null, null, descendant, r, r.isFinal(), r.isOverride() );
990 
991                    node.getModifiablePath().addAll( path );
992 
993                    addNode( map( this.implReferences, context ), node, node.getModelObject().getIdentifier() );
994 
995                    final Implementation ancestor = this.modules.getImplementation( r.getIdentifier() );
996                    this.collectNodes( context, ancestor, declarationNode, path );
997                }
998            }
999            else
1000            {
1001                map( this.sourceNodes, context ).
1002                    put( declarationNode.getModelObject().getIdentifier(), declarationNode );
1003 
1004            }
1005 
1006            path.removeLast();
1007        }
1008    }
1009 
1010    private void collectEffectiveNodes( final String context, final Node<Implementation> node )
1011    {
1012        final Map<String, Set<Node<SpecificationReference>>> directSpecificationReferences =
1013            getDirectEffectiveNodes( map( this.specReferences, context ), node.getModelObject().getIdentifier() );
1014 
1015        final Map<String, Set<Node<Dependency>>> directDependencies =
1016            getDirectEffectiveNodes( map( this.dependencies, context ), node.getModelObject().getIdentifier() );
1017 
1018        final Map<String, Set<Node<Message>>> directMessages =
1019            getDirectEffectiveNodes( map( this.messages, context ), node.getModelObject().getIdentifier() );
1020 
1021        final Map<String, Set<Node<Property>>> directProperties =
1022            getDirectEffectiveNodes( map( this.properties, context ), node.getModelObject().getIdentifier() );
1023 
1024        final Map<String, Set<Node<ImplementationReference>>> directImplementationReferences =
1025            getDirectEffectiveNodes( map( this.implReferences, context ), node.getModelObject().getIdentifier() );
1026 
1027        final Map<QName, Set<Node<Element>>> directXmlElements =
1028            getDirectEffectiveNodes( map( this.xmlElements, context ), node.getModelObject().getIdentifier() );
1029 
1030        final Map<QName, Set<Node<JAXBElement<?>>>> directJaxbElements =
1031            getDirectEffectiveNodes( map( this.jaxbElements, context ), node.getModelObject().getIdentifier() );
1032 
1033        overrideNodes( map( this.effSpecReferences, context ), node, directSpecificationReferences );
1034        overrideNodes( map( this.effImplReferences, context ), node, directImplementationReferences );
1035        overrideNodes( map( this.effDependencies, context ), node, directDependencies );
1036        overrideNodes( map( this.effMessages, context ), node, directMessages );
1037        overrideNodes( map( this.effProperties, context ), node, directProperties );
1038        overrideNodes( map( this.effJaxbElements, context ), node, directJaxbElements );
1039        overrideNodes( map( this.effXmlElements, context ), node, directXmlElements );
1040 
1041        this.addClassDeclarationNodes( context, node );
1042 
1043        final Map<String, Set<Node<SpecificationReference>>> ancestorSpecificationReferences =
1044            getEffectiveNodes( this.effSpecReferences, context, node.getModelObject().getIdentifier() );
1045 
1046        final Map<String, Set<Node<Dependency>>> ancestorDependencies =
1047            getEffectiveNodes( this.effDependencies, context, node.getModelObject().getIdentifier() );
1048 
1049        final Map<String, Set<Node<Message>>> ancestorMessages =
1050            getEffectiveNodes( this.effMessages, context, node.getModelObject().getIdentifier() );
1051 
1052        final Map<String, Set<Node<Property>>> ancestorProperties =
1053            getEffectiveNodes( this.effProperties, context, node.getModelObject().getIdentifier() );
1054 
1055        final Map<String, Set<Node<ImplementationReference>>> ancestorImplementationReferences =
1056            getEffectiveNodes( this.effImplReferences, context, node.getModelObject().getIdentifier() );
1057 
1058        final Map<QName, Set<Node<Element>>> ancestorXmlElements =
1059            getEffectiveNodes( this.effXmlElements, context, node.getModelObject().getIdentifier() );
1060 
1061        final Map<QName, Set<Node<JAXBElement<?>>>> ancestorJaxbElements =
1062            getEffectiveNodes( this.effJaxbElements, context, node.getModelObject().getIdentifier() );
1063 
1064        if ( node.getDescendant() != null )
1065        {
1066            if ( ancestorSpecificationReferences != null )
1067            {
1068                inheritNodes( map( this.effSpecReferences, context ), ancestorSpecificationReferences,
1069                              node.getDescendant() );
1070 
1071            }
1072 
1073            if ( ancestorDependencies != null )
1074            {
1075                inheritNodes( map( this.effDependencies, context ), ancestorDependencies,
1076                              node.getDescendant() );
1077 
1078            }
1079 
1080            if ( ancestorProperties != null )
1081            {
1082                inheritNodes( map( this.effProperties, context ), ancestorProperties, node.getDescendant() );
1083            }
1084 
1085            if ( ancestorMessages != null )
1086            {
1087                inheritNodes( map( this.effMessages, context ), ancestorMessages, node.getDescendant() );
1088            }
1089 
1090            if ( ancestorImplementationReferences != null )
1091            {
1092                inheritNodes( map( this.effImplReferences, context ), ancestorImplementationReferences,
1093                              node.getDescendant() );
1094 
1095            }
1096 
1097            if ( ancestorXmlElements != null )
1098            {
1099                inheritNodes( map( this.effXmlElements, context ), ancestorXmlElements,
1100                              node.getDescendant() );
1101 
1102            }
1103 
1104            if ( ancestorJaxbElements != null )
1105            {
1106                inheritNodes( map( this.effJaxbElements, context ), ancestorJaxbElements,
1107                              node.getDescendant() );
1108 
1109            }
1110 
1111            collectEffectiveNodes( context, node.getDescendant() );
1112        }
1113    }
1114 
1115    private void addClassDeclarationNodes( final String context, final Node<Implementation> node )
1116    {
1117        final Implementation classDeclaration = this.getClassDeclaration( node.getModelObject() );
1118 
1119        if ( classDeclaration != null )
1120        {
1121            this.prepareContext( classDeclaration.getIdentifier() );
1122 
1123            Map<String, Set<Node<Dependency>>> effectiveDependencies =
1124                getEffectiveNodes( this.effDependencies, context, node.getModelObject().getIdentifier() );
1125 
1126            Map<String, Set<Node<Message>>> effectiveMessages =
1127                getEffectiveNodes( this.effMessages, context, node.getModelObject().getIdentifier() );
1128 
1129            Map<String, Set<Node<Property>>> effectiveProperties =
1130                getEffectiveNodes( this.effProperties, context, node.getModelObject().getIdentifier() );
1131 
1132            Map<String, Set<Node<SpecificationReference>>> effectiveSpecificationReferences =
1133                getEffectiveNodes( this.effSpecReferences, context, node.getModelObject().getIdentifier() );
1134 
1135            Map<QName, Set<Node<Element>>> effectiveXmlElements =
1136                getEffectiveNodes( this.effXmlElements, context, node.getModelObject().getIdentifier() );
1137 
1138            Map<QName, Set<Node<JAXBElement<?>>>> effectiveJaxbElements =
1139                getEffectiveNodes( this.effJaxbElements, context, node.getModelObject().getIdentifier() );
1140 
1141            final Map<String, Set<Node<Dependency>>> declDependencies =
1142                getEffectiveNodes( this.effDependencies, classDeclaration.getIdentifier(),
1143                                   classDeclaration.getIdentifier() );
1144 
1145            final Map<String, Set<Node<Message>>> declMessages =
1146                getEffectiveNodes( this.effMessages, classDeclaration.getIdentifier(),
1147                                   classDeclaration.getIdentifier() );
1148 
1149            final Map<String, Set<Node<Property>>> declProperties =
1150                getEffectiveNodes( this.effProperties, classDeclaration.getIdentifier(),
1151                                   classDeclaration.getIdentifier() );
1152 
1153            final Map<String, Set<Node<SpecificationReference>>> declSpecReferences =
1154                getEffectiveNodes( this.effSpecReferences, classDeclaration.getIdentifier(),
1155                                   classDeclaration.getIdentifier() );
1156 
1157            final Map<QName, Set<Node<Element>>> declXmlElements =
1158                getEffectiveNodes( this.effXmlElements, classDeclaration.getIdentifier(),
1159                                   classDeclaration.getIdentifier() );
1160 
1161            final Map<QName, Set<Node<JAXBElement<?>>>> declJaxbElements =
1162                getEffectiveNodes( this.effJaxbElements, classDeclaration.getIdentifier(),
1163                                   classDeclaration.getIdentifier() );
1164 
1165            if ( declDependencies != null )
1166            {
1167                if ( effectiveDependencies == null )
1168                {
1169                    effectiveDependencies = newMap();
1170                    map( this.effDependencies, context ).
1171                        put( node.getModelObject().getIdentifier(), effectiveDependencies );
1172 
1173                }
1174 
1175                for ( Map.Entry<String, Set<Node<Dependency>>> e : declDependencies.entrySet() )
1176                {
1177                    final Set<Node<Dependency>> set = newSet( e.getValue().size() );
1178 
1179                    for ( final Node<Dependency> n : e.getValue() )
1180                    {
1181                        final Node<Dependency> effNode = new Node<Dependency>(
1182                            node.getModelObject(), n.getSpecification(), classDeclaration, null, n.getModelObject(),
1183                            n.isFinal(), n.isOverride() );
1184 
1185                        effNode.getModifiablePath().addAll( n.getPath() );
1186                        set.add( effNode );
1187 
1188                        addNode( map( this.dependencies, context ), effNode, e.getKey() );
1189                    }
1190 
1191                    if ( effectiveDependencies.containsKey( e.getKey() ) )
1192                    {
1193                        for ( final Node<Dependency> effNode : effectiveDependencies.get( e.getKey() ) )
1194                        {
1195                            effNode.getModifiableOverriddenNodes().addAll( set );
1196                        }
1197                    }
1198                    else
1199                    {
1200                        effectiveDependencies.put( e.getKey(), set );
1201                    }
1202                }
1203            }
1204 
1205            if ( declSpecReferences != null )
1206            {
1207                if ( effectiveSpecificationReferences == null )
1208                {
1209                    effectiveSpecificationReferences = newMap();
1210                    map( this.effSpecReferences, context ).
1211                        put( node.getModelObject().getIdentifier(), effectiveSpecificationReferences );
1212 
1213                }
1214 
1215                for ( Map.Entry<String, Set<Node<SpecificationReference>>> e : declSpecReferences.entrySet() )
1216                {
1217                    final Set<Node<SpecificationReference>> set = newSet( e.getValue().size() );
1218 
1219                    for ( final Node<SpecificationReference> n : e.getValue() )
1220                    {
1221                        final Node<SpecificationReference> effNode = new Node<SpecificationReference>(
1222                            node.getModelObject(), n.getSpecification(), classDeclaration, null, n.getModelObject(),
1223                            n.isFinal(), n.isOverride() );
1224 
1225                        effNode.getModifiablePath().addAll( n.getPath() );
1226                        set.add( effNode );
1227 
1228                        addNode( map( this.specReferences, context ), effNode, e.getKey() );
1229                    }
1230 
1231                    if ( effectiveSpecificationReferences.containsKey( e.getKey() ) )
1232                    {
1233                        for ( final Node<SpecificationReference> effNode :
1234                              effectiveSpecificationReferences.get( e.getKey() ) )
1235                        {
1236                            effNode.getModifiableOverriddenNodes().addAll( set );
1237                        }
1238                    }
1239                    else
1240                    {
1241                        effectiveSpecificationReferences.put( e.getKey(), set );
1242                    }
1243                }
1244            }
1245 
1246            if ( declMessages != null )
1247            {
1248                if ( effectiveMessages == null )
1249                {
1250                    effectiveMessages = newMap();
1251                    map( this.effMessages, context ).
1252                        put( node.getModelObject().getIdentifier(), effectiveMessages );
1253 
1254                }
1255 
1256                for ( Map.Entry<String, Set<Node<Message>>> e : declMessages.entrySet() )
1257                {
1258                    final Set<Node<Message>> set = newSet( e.getValue().size() );
1259 
1260                    for ( final Node<Message> n : e.getValue() )
1261                    {
1262                        final Node<Message> effNode = new Node<Message>(
1263                            node.getModelObject(), n.getSpecification(), classDeclaration, null, n.getModelObject(),
1264                            n.isFinal(), n.isOverride() );
1265 
1266                        effNode.getModifiablePath().addAll( n.getPath() );
1267                        set.add( effNode );
1268 
1269                        addNode( map( this.messages, context ), effNode, e.getKey() );
1270                    }
1271 
1272                    if ( effectiveMessages.containsKey( e.getKey() ) )
1273                    {
1274                        for ( final Node<Message> effNode : effectiveMessages.get( e.getKey() ) )
1275                        {
1276                            effNode.getModifiableOverriddenNodes().addAll( set );
1277                        }
1278                    }
1279                    else
1280                    {
1281                        effectiveMessages.put( e.getKey(), set );
1282                    }
1283                }
1284            }
1285 
1286            if ( declProperties != null )
1287            {
1288                if ( effectiveProperties == null )
1289                {
1290                    effectiveProperties = newMap();
1291                    map( this.effProperties, context ).
1292                        put( node.getModelObject().getIdentifier(), effectiveProperties );
1293 
1294                }
1295 
1296                for ( Map.Entry<String, Set<Node<Property>>> e : declProperties.entrySet() )
1297                {
1298                    final Set<Node<Property>> set = newSet( e.getValue().size() );
1299 
1300                    for ( final Node<Property> n : e.getValue() )
1301                    {
1302                        final Node<Property> effNode = new Node<Property>(
1303                            node.getModelObject(), n.getSpecification(), classDeclaration, null, n.getModelObject(),
1304                            n.isFinal(), n.isOverride() );
1305 
1306                        effNode.getModifiablePath().addAll( n.getPath() );
1307                        set.add( effNode );
1308 
1309                        addNode( map( this.properties, context ), effNode, e.getKey() );
1310                    }
1311 
1312                    if ( effectiveProperties.containsKey( e.getKey() ) )
1313                    {
1314                        for ( final Node<Property> effNode : effectiveProperties.get( e.getKey() ) )
1315                        {
1316                            effNode.getModifiableOverriddenNodes().addAll( set );
1317                        }
1318                    }
1319                    else
1320                    {
1321                        effectiveProperties.put( e.getKey(), set );
1322                    }
1323                }
1324            }
1325 
1326            if ( declXmlElements != null )
1327            {
1328                if ( effectiveXmlElements == null )
1329                {
1330                    effectiveXmlElements = newMap();
1331                    map( this.effXmlElements, context ).
1332                        put( node.getModelObject().getIdentifier(), effectiveXmlElements );
1333 
1334                }
1335 
1336                for ( Map.Entry<QName, Set<Node<Element>>> e : declXmlElements.entrySet() )
1337                {
1338                    final Set<Node<Element>> set = newSet( e.getValue().size() );
1339 
1340                    for ( final Node<Element> n : e.getValue() )
1341                    {
1342                        final Node<Element> effNode = new Node<Element>(
1343                            node.getModelObject(), n.getSpecification(), classDeclaration, null, n.getModelObject(),
1344                            n.isFinal(), n.isOverride() );
1345 
1346                        effNode.getModifiablePath().addAll( n.getPath() );
1347                        set.add( effNode );
1348 
1349                        addNode( map( this.xmlElements, context ), effNode, e.getKey() );
1350                    }
1351 
1352                    if ( effectiveXmlElements.containsKey( e.getKey() ) )
1353                    {
1354                        for ( final Node<Element> effNode : effectiveXmlElements.get( e.getKey() ) )
1355                        {
1356                            effNode.getModifiableOverriddenNodes().addAll( set );
1357                        }
1358                    }
1359                    else
1360                    {
1361                        effectiveXmlElements.put( e.getKey(), set );
1362                    }
1363                }
1364            }
1365 
1366            if ( declJaxbElements != null )
1367            {
1368                if ( effectiveJaxbElements == null )
1369                {
1370                    effectiveJaxbElements = newMap();
1371                    map( this.effJaxbElements, context ).
1372                        put( node.getModelObject().getIdentifier(), effectiveJaxbElements );
1373 
1374                }
1375 
1376                for ( Map.Entry<QName, Set<Node<JAXBElement<?>>>> e : declJaxbElements.entrySet() )
1377                {
1378                    final Set<Node<JAXBElement<?>>> set = newSet( e.getValue().size() );
1379 
1380                    for ( final Node<JAXBElement<?>> n : e.getValue() )
1381                    {
1382                        final Node<JAXBElement<?>> effNode = new Node<JAXBElement<?>>(
1383                            node.getModelObject(), n.getSpecification(), classDeclaration, null, n.getModelObject(),
1384                            n.isFinal(), n.isOverride() );
1385 
1386                        effNode.getModifiablePath().addAll( n.getPath() );
1387                        set.add( effNode );
1388 
1389                        addNode( map( this.jaxbElements, context ), effNode, e.getKey() );
1390                    }
1391 
1392                    if ( effectiveJaxbElements.containsKey( e.getKey() ) )
1393                    {
1394                        for ( final Node<JAXBElement<?>> effNode : effectiveJaxbElements.get( e.getKey() ) )
1395                        {
1396                            effNode.getModifiableOverriddenNodes().addAll( set );
1397                        }
1398                    }
1399                    else
1400                    {
1401                        effectiveJaxbElements.put( e.getKey(), set );
1402                    }
1403                }
1404            }
1405        }
1406    }
1407 
1408    private Implementation getClassDeclaration( final Implementation implementation )
1409    {
1410        Implementation declaration = null;
1411 
1412        if ( implementation.getClazz() != null && !implementation.isClassDeclaration() )
1413        {
1414            find:
1415            for ( int i = 0, s0 = this.modules.getModule().size(); i < s0; i++ )
1416            {
1417                final Module candidateModule = this.modules.getModule().get( i );
1418 
1419                if ( candidateModule.getImplementations() != null )
1420                {
1421                    for ( int j = 0, s1 = candidateModule.getImplementations().getImplementation().size(); j < s1; j++ )
1422                    {
1423                        final Implementation candidate =
1424                            candidateModule.getImplementations().getImplementation().get( j );
1425 
1426                        if ( candidate.isClassDeclaration()
1427                             && candidate.getClazz().equals( implementation.getClazz() ) )
1428                        {
1429                            declaration = candidate;
1430                            break find;
1431                        }
1432                    }
1433                }
1434            }
1435        }
1436 
1437        return declaration;
1438    }
1439 
1440    private static <T, K> void addNode( final Map<K, Set<Node<T>>> map, final Node<T> node, final K key )
1441    {
1442        Set<Node<T>> set = map.get( key );
1443 
1444        if ( set == null )
1445        {
1446            set = newSet();
1447            map.put( key, set );
1448        }
1449 
1450        set.add( node );
1451    }
1452 
1453    private static <T, K> void overrideNodes( final Map<String, Map<K, Set<Node<T>>>> effective,
1454                                              final Node<Implementation> implementation,
1455                                              final Map<K, Set<Node<T>>> directNodes )
1456    {
1457        for ( final Map.Entry<K, Set<Node<T>>> e : directNodes.entrySet() )
1458        {
1459            final Set<Node<T>> effectiveNodes =
1460                effectiveNodes( effective, implementation.getModelObject().getIdentifier(), e.getKey() );
1461 
1462            final Set<Node<T>> overridingNodes = newSet();
1463 
1464            for ( final Node<T> directNode : e.getValue() )
1465            {
1466                for ( final Iterator<Node<T>> it = effectiveNodes.iterator(); it.hasNext(); )
1467                {
1468                    final Node<T> effectiveNode = it.next();
1469 
1470                    if ( isOverriding( effectiveNode, directNode ) )
1471                    {
1472                        it.remove();
1473 
1474                        if ( directNode != effectiveNode )
1475                        {
1476                            directNode.getModifiableOverriddenNodes().add( effectiveNode );
1477                        }
1478                    }
1479                }
1480 
1481                boolean overriddenByAncestor = false;
1482 
1483                if ( directNode.getSpecification() != null )
1484                {
1485                    for ( final Node<T> effectiveNode : effectiveNodes )
1486                    {
1487                        if ( effectiveNode.getSpecification() == null )
1488                        {
1489                            overriddenByAncestor = true;
1490                            effectiveNode.getModifiableOverriddenNodes().add( directNode );
1491                        }
1492                    }
1493                }
1494 
1495                if ( !overriddenByAncestor )
1496                {
1497                    overridingNodes.add( directNode );
1498                }
1499            }
1500 
1501            effectiveNodes.addAll( overridingNodes );
1502        }
1503    }
1504 
1505    private static <K, V, T> Map<K, V> map( final Map<T, Map<K, V>> map, final T context )
1506    {
1507        Map<K, V> contextMap = map.get( context );
1508 
1509        if ( contextMap == null )
1510        {
1511            contextMap = newMap();
1512            map.put( context, contextMap );
1513        }
1514 
1515        return contextMap;
1516    }
1517 
1518    private static <K, V> Set<Node<V>> nodes( final Map<K, Set<Node<V>>> map, final K key )
1519    {
1520        Set<Node<V>> nodes = map.get( key );
1521 
1522        if ( nodes == null )
1523        {
1524            nodes = newSet();
1525            map.put( key, nodes );
1526        }
1527 
1528        return nodes;
1529    }
1530 
1531    private static <K, V> Set<Node<V>> effectiveNodes( final Map<String, Map<K, Set<Node<V>>>> map,
1532                                                       final String context, final K key )
1533    {
1534        return nodes( map( map, context ), key );
1535    }
1536 
1537    private static <T, K> void inheritNodes(
1538        final Map<String, Map<K, Set<Node<T>>>> effective, final Map<K, Set<Node<T>>> ancestor,
1539        final Node<Implementation> descendant )
1540    {
1541        for ( Map.Entry<K, Set<Node<T>>> e : ancestor.entrySet() )
1542        {
1543            for ( final Node<T> inherit : e.getValue() )
1544            {
1545                if ( isInheritableNode( inherit ) )
1546                {
1547                    effectiveNodes( effective, descendant.getModelObject().getIdentifier(), e.getKey() ).add( inherit );
1548                }
1549            }
1550        }
1551    }
1552 
1553    private static <T, K> Map<K, Set<Node<T>>> getDirectEffectiveNodes( final Map<K, Set<Node<T>>> map,
1554                                                                        final String origin )
1555    {
1556        final Map<K, Set<Node<T>>> declarationMap = newMap( map.size() );
1557 
1558        for ( Map.Entry<K, Set<Node<T>>> e : map.entrySet() )
1559        {
1560            final Set<Node<T>> set = nodes( declarationMap, e.getKey() );
1561 
1562            for ( final Node<T> n : e.getValue() )
1563            {
1564                if ( isDirectEffectiveNode( n, origin ) )
1565                {
1566                    set.add( n );
1567                }
1568            }
1569 
1570            for ( final Node<T> n : e.getValue() )
1571            {
1572                if ( isDirectSpecifiedNode( n, origin ) )
1573                {
1574                    boolean add = true;
1575 
1576                    for ( final Node<T> override : set )
1577                    {
1578                        if ( override.getSpecification() == null )
1579                        {
1580                            override.getModifiableOverriddenNodes().add( n );
1581                            add = false;
1582                        }
1583                    }
1584 
1585                    if ( add )
1586                    {
1587                        set.add( n );
1588                    }
1589                }
1590            }
1591        }
1592 
1593        return declarationMap;
1594    }
1595 
1596    private static <T, K> Map<K, Set<Node<T>>> getEffectiveNodes(
1597        final Map<String, Map<String, Map<K, Set<Node<T>>>>> effective, final String context,
1598        final String implementation )
1599    {
1600        return map( effective, context ).get( implementation );
1601    }
1602 
1603    private static boolean isDirectNode( final Node<?> node, final String implementation )
1604    {
1605        return implementation.equals( node.getImplementation().getIdentifier() );
1606    }
1607 
1608    private static boolean isDirectEffectiveNode( final Node<?> node, final String implementation )
1609    {
1610        return isDirectNode( node, implementation ) && node.getClassDeclaration() == null
1611               && node.getSpecification() == null;
1612 
1613    }
1614 
1615    private static boolean isDirectSpecifiedNode( final Node<?> node, final String implementation )
1616    {
1617        return isDirectNode( node, implementation ) && node.getClassDeclaration() == null
1618               && node.getSpecification() != null;
1619 
1620    }
1621 
1622    private static boolean isOverriding( final Node<?> node, final Node<?> override )
1623    {
1624        if ( override.getSpecification() != null )
1625        {
1626            if ( node.getSpecification() == null )
1627            {
1628                return false;
1629            }
1630            else if ( !override.getSpecification().getIdentifier().equals( node.getSpecification().getIdentifier() ) )
1631            {
1632                return false;
1633            }
1634        }
1635 
1636        return true;
1637    }
1638 
1639    private static boolean isInheritableNode( final Node<?> node )
1640    {
1641        return node.getClassDeclaration() == null;
1642    }
1643 
1644    private static <K, V> Map<K, V> newMap()
1645    {
1646        return new HashMap<K, V>();
1647    }
1648 
1649    private static <K, V> Map<K, V> newMap( final int initialCapacity )
1650    {
1651        return new HashMap<K, V>( initialCapacity );
1652    }
1653 
1654    private static <T> Set<T> newSet()
1655    {
1656        return new HashSet<T>();
1657    }
1658 
1659    private static <T> Set<T> newSet( final int initialCapacity )
1660    {
1661        return new HashSet<T>( initialCapacity );
1662    }
1663 
1664    private static <T> Set<T> newSet( final Collection<? extends T> col )
1665    {
1666        return new HashSet<T>( col );
1667    }
1668 
1669    private static <T> Set<T> unmodifiableSet( final Set<T> set )
1670    {
1671        return set != null ? Collections.unmodifiableSet( set ) : Collections.<T>emptySet();
1672    }
1673 
1674    private static QName getXmlElementName( final Element element )
1675    {
1676        if ( element.getNamespaceURI() != null )
1677        {
1678            return new QName( element.getNamespaceURI(), element.getLocalName() );
1679        }
1680        else
1681        {
1682            return new QName( element.getLocalName() );
1683        }
1684    }
1685 
1686}

[all classes][org.jomc.model]
EMMA 2.1.5320 (stable) (C) Vladimir Roubtsov