EMMA Coverage Report (generated Fri Feb 21 04:03:47 CET 2014)
[all classes][org.jomc.model]

COVERAGE SUMMARY FOR SOURCE FILE [InheritanceModel.java]

nameclass, %method, %block, %line, %
InheritanceModel.java100% (3/3)93%  (57/61)86%  (2508/2920)88%  (476.6/544)

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%  (41/43)86%  (2404/2807)87%  (450.8/518)
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)
getCycleNodes (String): Set 100% (1/1)69%  (11/16)75%  (3/4)
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)93%  (63/68)96%  (22/23)
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% (718/718)100% (111/111)
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 4777 2013-04-13 17:55:38Z 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 4777 2013-04-13 17:55:38Z 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 4777 2013-04-13 17:55:38Z 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 reference identifier. */
282    private final Map<String, Set<Node<ImplementationReference>>> cyclicImplReferences = newMap();
283 
284    /** {@code ImplementationReference} nodes by context and implementation identifier. */
285    private final Map<String, Map<String, Map<String, Set<Node<ImplementationReference>>>>> effImplReferences =
286        newMap();
287 
288    /** {@code Element} nodes by context and qualified name. */
289    private final Map<String, Map<QName, Set<Node<Element>>>> xmlElements = newMap();
290 
291    /** {@code Element} nodes by context and implementation identifier. */
292    private final Map<String, Map<String, Map<QName, Set<Node<Element>>>>> effXmlElements = newMap();
293 
294    /** {@code JAXBElement} nodes by context and qualified name. */
295    private final Map<String, Map<QName, Set<Node<JAXBElement<?>>>>> jaxbElements = newMap();
296 
297    /** {@code JAXBElement} nodes by context and implementation identifier. */
298    private final Map<String, Map<String, Map<QName, Set<Node<JAXBElement<?>>>>>> effJaxbElements =
299        newMap();
300 
301    /** {@code Implementation} nodes by context and implementation identifier. */
302    private final Map<String, Map<String, Node<Implementation>>> implementations = newMap();
303 
304    /** Source nodes of a hierarchy by context and implementation identifier. */
305    private final Map<String, Map<String, Node<Implementation>>> sourceNodes = newMap();
306 
307    /** Context states by context identifier. */
308    private final Map<String, ContextState> contextStates = newMap();
309 
310    /**
311     * Creates a new {@code InheritanceModel} instance.
312     *
313     * @param modules The modules backing the model.
314     *
315     * @throws NullPointerException if {@code modules} is {@code null}.
316     *
317     * @see Modules#clone()
318     */
319    public InheritanceModel( final Modules modules )
320    {
321        super();
322 
323        if ( modules == null )
324        {
325            throw new NullPointerException( "modules" );
326        }
327 
328        this.modules = modules.clone();
329    }
330 
331    /**
332     * Gets a set holding source nodes of an implementation.
333     *
334     * @param implementation The identifier of the implementation to get source nodes of.
335     *
336     * @return An unmodifiable set holding source nodes of the implementation identified by {@code implementation}.
337     *
338     * @throws NullPointerException if {@code implementation} is {@code null}.
339     *
340     * @see Node#getDescendant()
341     */
342    public Set<Node<Implementation>> getSourceNodes( final String implementation )
343    {
344        if ( implementation == null )
345        {
346            throw new NullPointerException( "implementation" );
347        }
348 
349        this.prepareContext( implementation );
350        final Collection<Node<Implementation>> col = map( this.sourceNodes, implementation ).values();
351        return unmodifiableSet( newSet( col ) );
352    }
353 
354    /**
355     * Gets a set holding implementation reference nodes of an implementation causing a cycle.
356     *
357     * @param implementation The identifier of the implementation to get implementation reference nodes causing a cycle
358     * of.
359     *
360     * @return An unmodifiable set holding implementation reference nodes of the implementation identified by
361     * {@code implementation} causing a cycle.
362     *
363     * @throws NullPointerException if {@code implementation} is {@code null}.
364     *
365     * @since 1.5
366     *
367     * @see Node#getPath()
368     */
369    public Set<Node<ImplementationReference>> getCycleNodes( final String implementation )
370    {
371        if ( implementation == null )
372        {
373            throw new NullPointerException( "implementation" );
374        }
375 
376        this.prepareContext( implementation );
377        return unmodifiableSet( nodes( this.cyclicImplReferences, implementation ) );
378    }
379 
380    /**
381     * Gets a set holding the names of all dependencies of an implementation.
382     *
383     * @param implementation The identifier of the implementation to get the names of all dependencies of.
384     *
385     * @return An unmodifiable set holding the names of all dependencies of the implementation identified by
386     * {@code implementation}.
387     *
388     * @throws NullPointerException if {@code implementation} is {@code null}.
389     */
390    public Set<String> getDependencyNames( final String implementation )
391    {
392        if ( implementation == null )
393        {
394            throw new NullPointerException( "implementation" );
395        }
396 
397        this.prepareContext( implementation );
398        return Collections.unmodifiableSet( map( this.dependencies, implementation ).keySet() );
399    }
400 
401    /**
402     * Gets a set holding effective dependency nodes of an implementation.
403     *
404     * @param implementation The identifier of the implementation to get effective dependency nodes of.
405     * @param name The dependency name to get effective nodes for.
406     *
407     * @return An unmodifiable set holding effective dependency nodes matching {@code name} of the implementation
408     * identified by {@code implementation}.
409     *
410     * @throws NullPointerException if {@code implementation} or {@code name} is {@code null}.
411     *
412     * @see #getDependencyNames(java.lang.String)
413     */
414    public Set<Node<Dependency>> getDependencyNodes( final String implementation, final String name )
415    {
416        if ( implementation == null )
417        {
418            throw new NullPointerException( "implementation" );
419        }
420        if ( name == null )
421        {
422            throw new NullPointerException( "name" );
423        }
424 
425        this.prepareContext( implementation );
426        Set<Node<Dependency>> set = null;
427 
428        final Map<String, Set<Node<Dependency>>> map =
429            getEffectiveNodes( this.effDependencies, implementation, implementation );
430 
431        if ( map != null )
432        {
433            set = map.get( name );
434        }
435 
436        return unmodifiableSet( set );
437    }
438 
439    /**
440     * Gets a set holding the identifiers of all implementation references of an implementation.
441     *
442     * @param implementation The identifier of the implementation to get the identifiers of all implementation
443     * references of.
444     *
445     * @return An unmodifiable set holding the identifiers of all implementation references of the implementation
446     * identified by {@code implementation}.
447     *
448     * @throws NullPointerException if {@code implementation} is {@code null}.
449     */
450    public Set<String> getImplementationReferenceIdentifiers( final String implementation )
451    {
452        if ( implementation == null )
453        {
454            throw new NullPointerException( "implementation" );
455        }
456 
457        this.prepareContext( implementation );
458        return Collections.unmodifiableSet( map( this.implReferences, implementation ).keySet() );
459    }
460 
461    /**
462     * Gets a set holding effective implementation reference nodes of an implementation.
463     *
464     * @param implementation The identifier of the implementation to get effective implementation reference nodes of.
465     * @param identifier The implementation reference identifier to get effective nodes for.
466     *
467     * @return An unmodifiable set holding effective implementation reference nodes matching {@code identifier} of the
468     * implementation identified by {@code implementation}.
469     *
470     * @throws NullPointerException if {@code implementation} or {@code identifier} is {@code null}.
471     *
472     * @see #getImplementationReferenceIdentifiers(java.lang.String)
473     */
474    public Set<Node<ImplementationReference>> getImplementationReferenceNodes( final String implementation,
475                                                                               final String identifier )
476    {
477        if ( implementation == null )
478        {
479            throw new NullPointerException( "implementation" );
480        }
481        if ( identifier == null )
482        {
483            throw new NullPointerException( "identifier" );
484        }
485 
486        this.prepareContext( implementation );
487        Set<Node<ImplementationReference>> set = null;
488        final Map<String, Set<Node<ImplementationReference>>> map =
489            getEffectiveNodes( this.effImplReferences, implementation, implementation );
490 
491        if ( map != null )
492        {
493            set = map.get( identifier );
494        }
495 
496        return unmodifiableSet( set );
497    }
498 
499    /**
500     * Gets a set holding the qualified names of all XML elements of an implementation.
501     *
502     * @param implementation The identifier of the implementation to get the qualified names of all XML elements of.
503     *
504     * @return An unmodifiable set holding the qualified names of all XML elements of the implementation identified by
505     * {@code implementation}.
506     *
507     * @throws NullPointerException if {@code implementation} is {@code null}.
508     */
509    public Set<QName> getJaxbElementNames( final String implementation )
510    {
511        if ( implementation == null )
512        {
513            throw new NullPointerException( "implementation" );
514        }
515 
516        this.prepareContext( implementation );
517        return Collections.unmodifiableSet( map( this.jaxbElements, implementation ).keySet() );
518    }
519 
520    /**
521     * Gets a set holding effective JAXB element nodes of an implementation.
522     *
523     * @param implementation The identifier of the implementation to get effective JAXB element nodes of.
524     * @param name The qualified JAXB element name to get effective nodes for.
525     *
526     * @return An unmodifiable set holding effective JAXB element nodes matching {@code name} of the implementation
527     * identified by {@code implementation}.
528     *
529     * @throws NullPointerException if {@code implementation} or {@code name} is {@code null}.
530     *
531     * @see #getJaxbElementNames(java.lang.String)
532     */
533    public Set<Node<JAXBElement<?>>> getJaxbElementNodes( final String implementation, final QName name )
534    {
535        if ( implementation == null )
536        {
537            throw new NullPointerException( "implementation" );
538        }
539        if ( name == null )
540        {
541            throw new NullPointerException( "name" );
542        }
543 
544        this.prepareContext( implementation );
545        Set<Node<JAXBElement<?>>> set = null;
546        final Map<QName, Set<Node<JAXBElement<?>>>> map =
547            getEffectiveNodes( this.effJaxbElements, implementation, implementation );
548 
549        if ( map != null )
550        {
551            set = map.get( name );
552        }
553 
554        return unmodifiableSet( set );
555    }
556 
557    /**
558     * Gets a set holding the names of all messages of an implementation.
559     *
560     * @param implementation The identifier of the implementation to get the names of all messages of.
561     *
562     * @return An unmodifiable set holding the names of all messages of the implementation identified by
563     * {@code implementation}.
564     *
565     * @throws NullPointerException if {@code implementation} is {@code null}.
566     */
567    public Set<String> getMessageNames( final String implementation )
568    {
569        if ( implementation == null )
570        {
571            throw new NullPointerException( "implementation" );
572        }
573 
574        this.prepareContext( implementation );
575        return Collections.unmodifiableSet( map( this.messages, implementation ).keySet() );
576    }
577 
578    /**
579     * Gets a set holding effective message nodes of an implementation.
580     *
581     * @param implementation The identifier of the implementation to get effective message nodes of.
582     * @param name The message name to get effective nodes for.
583     *
584     * @return An unmodifiable set holding effective message nodes matching {@code name} of the implementation
585     * identified by {@code implementation}.
586     *
587     * @throws NullPointerException if {@code implementation} or {@code name} is {@code null}.
588     *
589     * @see #getMessageNames(java.lang.String)
590     */
591    public Set<Node<Message>> getMessageNodes( final String implementation, final String name )
592    {
593        if ( implementation == null )
594        {
595            throw new NullPointerException( "implementation" );
596        }
597        if ( name == null )
598        {
599            throw new NullPointerException( "name" );
600        }
601 
602        this.prepareContext( implementation );
603        Set<Node<Message>> set = null;
604        final Map<String, Set<Node<Message>>> map =
605            getEffectiveNodes( this.effMessages, implementation, implementation );
606 
607        if ( map != null )
608        {
609            set = map.get( name );
610        }
611 
612        return unmodifiableSet( set );
613    }
614 
615    /**
616     * Gets a set holding the names of all properties of an implementation.
617     *
618     * @param implementation The identifier of the implementation to get the names of all properties of.
619     *
620     * @return An unmodifiable set holding the names of all properties of the implementation identified by
621     * {@code implementation}.
622     *
623     * @throws NullPointerException if {@code implementation} is {@code null}.
624     */
625    public Set<String> getPropertyNames( final String implementation )
626    {
627        if ( implementation == null )
628        {
629            throw new NullPointerException( "implementation" );
630        }
631 
632        this.prepareContext( implementation );
633        return Collections.unmodifiableSet( map( this.properties, implementation ).keySet() );
634    }
635 
636    /**
637     * Gets a set holding effective property nodes of an implementation.
638     *
639     * @param implementation The identifier of the implementation to get effective property nodes of.
640     * @param name The property name to get effective nodes for.
641     *
642     * @return An unmodifiable set holding effective property nodes matching {@code name} of the implementation
643     * identified by {@code implementation}.
644     *
645     * @throws NullPointerException if {@code implementation} or {@code name} is {@code null}.
646     *
647     * @see #getPropertyNames(java.lang.String)
648     */
649    public Set<Node<Property>> getPropertyNodes( final String implementation, final String name )
650    {
651        if ( implementation == null )
652        {
653            throw new NullPointerException( "implementation" );
654        }
655        if ( name == null )
656        {
657            throw new NullPointerException( "name" );
658        }
659 
660        this.prepareContext( implementation );
661        Set<Node<Property>> set = null;
662        final Map<String, Set<Node<Property>>> map =
663            getEffectiveNodes( this.effProperties, implementation, implementation );
664 
665        if ( map != null )
666        {
667            set = map.get( name );
668        }
669 
670        return unmodifiableSet( set );
671    }
672 
673    /**
674     * Gets a set holding the identifiers of all specification references of an implementation.
675     *
676     * @param implementation The identifier of the implementation to get the identifiers of all specification references
677     * of.
678     *
679     * @return An unmodifiable set holding the identifiers of all specification references of the implementation
680     * identified by {@code implementation}.
681     *
682     * @throws NullPointerException if {@code implementation} is {@code null}.
683     */
684    public Set<String> getSpecificationReferenceIdentifiers( final String implementation )
685    {
686        if ( implementation == null )
687        {
688            throw new NullPointerException( "implementation" );
689        }
690 
691        this.prepareContext( implementation );
692        return Collections.unmodifiableSet( map( this.specReferences, implementation ).keySet() );
693    }
694 
695    /**
696     * Gets a set holding effective specification reference nodes of an implementation.
697     *
698     * @param implementation The identifier of the implementation to get effective specification reference nodes of.
699     * @param identifier The specification reference identifier to get effective nodes for.
700     *
701     * @return An unmodifiable set holding effective specification reference nodes matching {@code identifier} of the
702     * implementation identified by {@code implementation}.
703     *
704     * @throws NullPointerException if {@code implementation} or {@code identifier} is {@code null}.
705     *
706     * @see #getSpecificationReferenceIdentifiers(java.lang.String)
707     */
708    public Set<Node<SpecificationReference>> getSpecificationReferenceNodes( final String implementation,
709                                                                             final String identifier )
710    {
711        if ( implementation == null )
712        {
713            throw new NullPointerException( "implementation" );
714        }
715        if ( identifier == null )
716        {
717            throw new NullPointerException( "identifier" );
718        }
719 
720        this.prepareContext( implementation );
721        Set<Node<SpecificationReference>> set = null;
722        final Map<String, Set<Node<SpecificationReference>>> map =
723            getEffectiveNodes( this.effSpecReferences, implementation, implementation );
724 
725        if ( map != null )
726        {
727            set = map.get( identifier );
728        }
729 
730        return unmodifiableSet( set );
731    }
732 
733    /**
734     * Gets a set holding the qualified names of all XML elements of an implementation.
735     *
736     * @param implementation The identifier of the implementation to get the qualified names of all XML elements of.
737     *
738     * @return An unmodifiable set holding the qualified names of all XML elements of the implementation identified by
739     * {@code implementation}.
740     *
741     * @throws NullPointerException if {@code implementation} is {@code null}.
742     */
743    public Set<QName> getXmlElementNames( final String implementation )
744    {
745        if ( implementation == null )
746        {
747            throw new NullPointerException( "implementation" );
748        }
749 
750        this.prepareContext( implementation );
751        return Collections.unmodifiableSet( map( this.xmlElements, implementation ).keySet() );
752    }
753 
754    /**
755     * Gets a set holding effective XML element nodes of an implementation.
756     *
757     * @param implementation The identifier of the implementation to get effective XML element nodes of.
758     * @param name The qualified XML element name to get effective nodes for.
759     *
760     * @return An unmodifiable set holding effective XML element nodes matching {@code name} of the implementation
761     * identified by {@code implementation}.
762     *
763     * @throws NullPointerException if {@code implementation} or {@code name} is {@code null}.
764     *
765     * @see #getXmlElementNames(java.lang.String)
766     */
767    public Set<Node<Element>> getXmlElementNodes( final String implementation, final QName name )
768    {
769        if ( implementation == null )
770        {
771            throw new NullPointerException( "implementation" );
772        }
773        if ( name == null )
774        {
775            throw new NullPointerException( "name" );
776        }
777 
778        this.prepareContext( implementation );
779        Set<Node<Element>> set = null;
780        final Map<QName, Set<Node<Element>>> map =
781            getEffectiveNodes( this.effXmlElements, implementation, implementation );
782 
783        if ( map != null )
784        {
785            set = map.get( name );
786        }
787 
788        return unmodifiableSet( set );
789    }
790 
791    private void prepareContext( final String context )
792    {
793        ContextState state = this.contextStates.get( context );
794 
795        if ( state == null )
796        {
797            state = ContextState.PREPARING;
798            this.contextStates.put( context, state );
799 
800            final Implementation i = this.modules.getImplementation( context );
801 
802            if ( i != null )
803            {
804                this.collectNodes( context, i, null, null );
805 
806                for ( Node<Implementation> source : map( this.sourceNodes, context ).values() )
807                {
808                    this.collectEffectiveNodes( context, source );
809                }
810            }
811 
812            state = ContextState.PREPARED;
813            this.contextStates.put( context, state );
814        }
815 
816        assert state == ContextState.PREPARED :
817            "Unexpected context state '" + state + "' for context '" + context + "'.";
818 
819    }
820 
821    private void collectNodes( final String context, final Implementation declaration,
822                               final Node<Implementation> descendant, LinkedList<Node<Implementation>> path )
823    {
824        if ( path == null )
825        {
826            path = new LinkedList<Node<Implementation>>();
827        }
828 
829        final Map<String, Node<Implementation>> contextImplementations = map( this.implementations, context );
830 
831        if ( declaration != null && !contextImplementations.containsKey( declaration.getIdentifier() ) )
832        {
833            final Node<Implementation> declarationNode = new Node<Implementation>(
834                declaration, null, null, descendant, declaration, declaration.isFinal(), false );
835 
836            declarationNode.getModifiablePath().addAll( path );
837 
838            contextImplementations.put( declaration.getIdentifier(), declarationNode );
839 
840            path.addLast( declarationNode );
841 
842            if ( declaration.getDependencies() != null )
843            {
844                for ( int i = 0, s0 = declaration.getDependencies().getDependency().size(); i < s0; i++ )
845                {
846                    final Dependency d = declaration.getDependencies().getDependency().get( i );
847                    final Node<Dependency> node =
848                        new Node<Dependency>( declaration, null, null, descendant, d, d.isFinal(), d.isOverride() );
849 
850                    node.getModifiablePath().addAll( path );
851 
852                    addNode( map( this.dependencies, context ), node, node.getModelObject().getName() );
853                }
854            }
855 
856            if ( declaration.getMessages() != null )
857            {
858                for ( int i = 0, s0 = declaration.getMessages().getMessage().size(); i < s0; i++ )
859                {
860                    final Message m = declaration.getMessages().getMessage().get( i );
861                    final Node<Message> node =
862                        new Node<Message>( declaration, null, null, descendant, m, m.isFinal(), m.isOverride() );
863 
864                    node.getModifiablePath().addAll( path );
865 
866                    addNode( map( this.messages, context ), node, node.getModelObject().getName() );
867                }
868 
869                if ( !declaration.getMessages().getReference().isEmpty() )
870                {
871                    final Module m = this.modules.getModuleOfImplementation( declaration.getIdentifier() );
872 
873                    if ( m != null && m.getMessages() != null )
874                    {
875                        for ( int i = 0, s0 = declaration.getMessages().getReference().size(); i < s0; i++ )
876                        {
877                            final MessageReference r = declaration.getMessages().getReference().get( i );
878                            Message msg = m.getMessages().getMessage( r.getName() );
879 
880                            if ( msg != null )
881                            {
882                                msg = msg.clone();
883                                msg.setFinal( r.isFinal() );
884                                msg.setOverride( r.isOverride() );
885 
886                                final Node<Message> node = new Node<Message>(
887                                    declaration, null, null, descendant, msg, msg.isFinal(), msg.isOverride() );
888 
889                                node.getModifiablePath().addAll( path );
890 
891                                addNode( map( this.messages, context ), node, node.getModelObject().getName() );
892                            }
893                        }
894                    }
895                }
896            }
897 
898            if ( declaration.getProperties() != null )
899            {
900                for ( int i = 0, s0 = declaration.getProperties().getProperty().size(); i < s0; i++ )
901                {
902                    final Property p = declaration.getProperties().getProperty().get( i );
903                    final Node<Property> node =
904                        new Node<Property>( declaration, null, null, descendant, p, p.isFinal(), p.isOverride() );
905 
906                    node.getModifiablePath().addAll( path );
907 
908                    addNode( map( this.properties, context ), node, node.getModelObject().getName() );
909                }
910 
911                if ( !declaration.getProperties().getReference().isEmpty() )
912                {
913                    final Module m = this.modules.getModuleOfImplementation( declaration.getIdentifier() );
914 
915                    if ( m != null && m.getProperties() != null )
916                    {
917                        for ( int i = 0, s0 = declaration.getProperties().getReference().size(); i < s0; i++ )
918                        {
919                            final PropertyReference r = declaration.getProperties().getReference().get( i );
920                            Property p = m.getProperties().getProperty( r.getName() );
921 
922                            if ( p != null )
923                            {
924                                p = p.clone();
925                                p.setFinal( r.isFinal() );
926                                p.setOverride( r.isOverride() );
927 
928                                final Node<Property> node = new Node<Property>(
929                                    declaration, null, null, descendant, p, p.isFinal(), p.isOverride() );
930 
931                                node.getModifiablePath().addAll( path );
932 
933                                addNode( map( this.properties, context ), node, node.getModelObject().getName() );
934                            }
935                        }
936                    }
937                }
938            }
939 
940            if ( declaration.getSpecifications() != null )
941            {
942                for ( int i = 0, s0 = declaration.getSpecifications().getReference().size(); i < s0; i++ )
943                {
944                    final SpecificationReference r = declaration.getSpecifications().getReference().get( i );
945                    final Node<SpecificationReference> node = new Node<SpecificationReference>(
946                        declaration, null, null, descendant, r, r.isFinal(), r.isOverride() );
947 
948                    node.getModifiablePath().addAll( path );
949 
950                    addNode( map( this.specReferences, context ), node, node.getModelObject().getIdentifier() );
951 
952                    final Specification s = this.modules.getSpecification( r.getIdentifier() );
953 
954                    if ( s != null && s.getProperties() != null )
955                    {
956                        for ( int j = 0, s1 = s.getProperties().getProperty().size(); j < s1; j++ )
957                        {
958                            final Property p = s.getProperties().getProperty().get( j );
959                            final Node<Property> n =
960                                new Node<Property>( declaration, s, null, descendant, p, p.isFinal(), p.isOverride() );
961 
962                            n.getModifiablePath().addAll( path );
963 
964                            addNode( map( this.properties, context ), n, n.getModelObject().getName() );
965                        }
966                    }
967                }
968            }
969 
970            if ( !declaration.getAny().isEmpty() )
971            {
972                for ( int i = 0, s0 = declaration.getAny().size(); i < s0; i++ )
973                {
974                    final Object any = declaration.getAny().get( i );
975 
976                    if ( any instanceof Element )
977                    {
978                        final Element e = (Element) any;
979                        final Node<Element> node =
980                            new Node<Element>( declaration, null, null, descendant, e, false, false );
981 
982                        node.getModifiablePath().addAll( path );
983 
984                        addNode( map( this.xmlElements, context ), node, getXmlElementName( e ) );
985                        continue;
986                    }
987 
988                    if ( any instanceof JAXBElement<?> )
989                    {
990                        final JAXBElement<?> e = (JAXBElement<?>) any;
991                        boolean _final = false;
992                        boolean override = false;
993 
994                        if ( e.getValue() instanceof Inheritable )
995                        {
996                            _final = ( (Inheritable) e.getValue() ).isFinal();
997                            override = ( (Inheritable) e.getValue() ).isOverride();
998                        }
999 
1000                        final Node<JAXBElement<?>> node =
1001                            new Node<JAXBElement<?>>( declaration, null, null, descendant, e, _final, override );
1002 
1003                        node.getModifiablePath().addAll( path );
1004 
1005                        addNode( map( this.jaxbElements, context ), node, e.getName() );
1006                        continue;
1007                    }
1008                }
1009            }
1010 
1011            if ( declaration.getImplementations() != null
1012                 && !declaration.getImplementations().getReference().isEmpty() )
1013            {
1014                boolean all_cyclic = true;
1015 
1016                for ( int i = 0, s0 = declaration.getImplementations().getReference().size(); i < s0; i++ )
1017                {
1018                    final ImplementationReference r = declaration.getImplementations().getReference().get( i );
1019                    final Node<ImplementationReference> node = new Node<ImplementationReference>(
1020                        declaration, null, null, descendant, r, r.isFinal(), r.isOverride() );
1021 
1022                    node.getModifiablePath().addAll( path );
1023 
1024                    final Implementation ancestor = this.modules.getImplementation( r.getIdentifier() );
1025 
1026                    boolean cycle = false;
1027                    if ( ancestor != null && contextImplementations.containsKey( ancestor.getIdentifier() ) )
1028                    {
1029                        for ( int j = 0, s1 = path.size(); j < s1; j++ )
1030                        {
1031                            final Node<Implementation> n = path.get( j );
1032 
1033                            if ( n.getModelObject().getIdentifier().equals( ancestor.getIdentifier() ) )
1034                            {
1035                                cycle = true;
1036                                node.getModifiablePath().add( n );
1037                                break;
1038                            }
1039                        }
1040                    }
1041 
1042                    if ( cycle )
1043                    {
1044                        addNode( this.cyclicImplReferences, node, context );
1045                    }
1046                    else
1047                    {
1048                        all_cyclic = false;
1049                        addNode( map( this.implReferences, context ), node, node.getModelObject().getIdentifier() );
1050                        this.collectNodes( context, ancestor, declarationNode, path );
1051                    }
1052                }
1053 
1054                if ( all_cyclic )
1055                {
1056                    map( this.sourceNodes, context ).
1057                        put( declarationNode.getModelObject().getIdentifier(), declarationNode );
1058 
1059                }
1060            }
1061            else
1062            {
1063                map( this.sourceNodes, context ).
1064                    put( declarationNode.getModelObject().getIdentifier(), declarationNode );
1065 
1066            }
1067 
1068            path.removeLast();
1069        }
1070    }
1071 
1072    private void collectEffectiveNodes( final String context, final Node<Implementation> node )
1073    {
1074        final Map<String, Set<Node<SpecificationReference>>> directSpecificationReferences =
1075            getDirectEffectiveNodes( map( this.specReferences, context ), node.getModelObject().getIdentifier() );
1076 
1077        final Map<String, Set<Node<Dependency>>> directDependencies =
1078            getDirectEffectiveNodes( map( this.dependencies, context ), node.getModelObject().getIdentifier() );
1079 
1080        final Map<String, Set<Node<Message>>> directMessages =
1081            getDirectEffectiveNodes( map( this.messages, context ), node.getModelObject().getIdentifier() );
1082 
1083        final Map<String, Set<Node<Property>>> directProperties =
1084            getDirectEffectiveNodes( map( this.properties, context ), node.getModelObject().getIdentifier() );
1085 
1086        final Map<String, Set<Node<ImplementationReference>>> directImplementationReferences =
1087            getDirectEffectiveNodes( map( this.implReferences, context ), node.getModelObject().getIdentifier() );
1088 
1089        final Map<QName, Set<Node<Element>>> directXmlElements =
1090            getDirectEffectiveNodes( map( this.xmlElements, context ), node.getModelObject().getIdentifier() );
1091 
1092        final Map<QName, Set<Node<JAXBElement<?>>>> directJaxbElements =
1093            getDirectEffectiveNodes( map( this.jaxbElements, context ), node.getModelObject().getIdentifier() );
1094 
1095        overrideNodes( map( this.effSpecReferences, context ), node, directSpecificationReferences );
1096        overrideNodes( map( this.effImplReferences, context ), node, directImplementationReferences );
1097        overrideNodes( map( this.effDependencies, context ), node, directDependencies );
1098        overrideNodes( map( this.effMessages, context ), node, directMessages );
1099        overrideNodes( map( this.effProperties, context ), node, directProperties );
1100        overrideNodes( map( this.effJaxbElements, context ), node, directJaxbElements );
1101        overrideNodes( map( this.effXmlElements, context ), node, directXmlElements );
1102 
1103        this.addClassDeclarationNodes( context, node );
1104 
1105        final Map<String, Set<Node<SpecificationReference>>> ancestorSpecificationReferences =
1106            getEffectiveNodes( this.effSpecReferences, context, node.getModelObject().getIdentifier() );
1107 
1108        final Map<String, Set<Node<Dependency>>> ancestorDependencies =
1109            getEffectiveNodes( this.effDependencies, context, node.getModelObject().getIdentifier() );
1110 
1111        final Map<String, Set<Node<Message>>> ancestorMessages =
1112            getEffectiveNodes( this.effMessages, context, node.getModelObject().getIdentifier() );
1113 
1114        final Map<String, Set<Node<Property>>> ancestorProperties =
1115            getEffectiveNodes( this.effProperties, context, node.getModelObject().getIdentifier() );
1116 
1117        final Map<String, Set<Node<ImplementationReference>>> ancestorImplementationReferences =
1118            getEffectiveNodes( this.effImplReferences, context, node.getModelObject().getIdentifier() );
1119 
1120        final Map<QName, Set<Node<Element>>> ancestorXmlElements =
1121            getEffectiveNodes( this.effXmlElements, context, node.getModelObject().getIdentifier() );
1122 
1123        final Map<QName, Set<Node<JAXBElement<?>>>> ancestorJaxbElements =
1124            getEffectiveNodes( this.effJaxbElements, context, node.getModelObject().getIdentifier() );
1125 
1126        if ( node.getDescendant() != null )
1127        {
1128            if ( ancestorSpecificationReferences != null )
1129            {
1130                inheritNodes( map( this.effSpecReferences, context ), ancestorSpecificationReferences,
1131                              node.getDescendant() );
1132 
1133            }
1134 
1135            if ( ancestorDependencies != null )
1136            {
1137                inheritNodes( map( this.effDependencies, context ), ancestorDependencies,
1138                              node.getDescendant() );
1139 
1140            }
1141 
1142            if ( ancestorProperties != null )
1143            {
1144                inheritNodes( map( this.effProperties, context ), ancestorProperties, node.getDescendant() );
1145            }
1146 
1147            if ( ancestorMessages != null )
1148            {
1149                inheritNodes( map( this.effMessages, context ), ancestorMessages, node.getDescendant() );
1150            }
1151 
1152            if ( ancestorImplementationReferences != null )
1153            {
1154                inheritNodes( map( this.effImplReferences, context ), ancestorImplementationReferences,
1155                              node.getDescendant() );
1156 
1157            }
1158 
1159            if ( ancestorXmlElements != null )
1160            {
1161                inheritNodes( map( this.effXmlElements, context ), ancestorXmlElements,
1162                              node.getDescendant() );
1163 
1164            }
1165 
1166            if ( ancestorJaxbElements != null )
1167            {
1168                inheritNodes( map( this.effJaxbElements, context ), ancestorJaxbElements,
1169                              node.getDescendant() );
1170 
1171            }
1172 
1173            collectEffectiveNodes( context, node.getDescendant() );
1174        }
1175    }
1176 
1177    private void addClassDeclarationNodes( final String context, final Node<Implementation> node )
1178    {
1179        final Implementation classDeclaration = this.getClassDeclaration( node.getModelObject() );
1180 
1181        if ( classDeclaration != null )
1182        {
1183            this.prepareContext( classDeclaration.getIdentifier() );
1184 
1185            Map<String, Set<Node<Dependency>>> effectiveDependencies =
1186                getEffectiveNodes( this.effDependencies, context, node.getModelObject().getIdentifier() );
1187 
1188            Map<String, Set<Node<Message>>> effectiveMessages =
1189                getEffectiveNodes( this.effMessages, context, node.getModelObject().getIdentifier() );
1190 
1191            Map<String, Set<Node<Property>>> effectiveProperties =
1192                getEffectiveNodes( this.effProperties, context, node.getModelObject().getIdentifier() );
1193 
1194            Map<String, Set<Node<SpecificationReference>>> effectiveSpecificationReferences =
1195                getEffectiveNodes( this.effSpecReferences, context, node.getModelObject().getIdentifier() );
1196 
1197            Map<QName, Set<Node<Element>>> effectiveXmlElements =
1198                getEffectiveNodes( this.effXmlElements, context, node.getModelObject().getIdentifier() );
1199 
1200            Map<QName, Set<Node<JAXBElement<?>>>> effectiveJaxbElements =
1201                getEffectiveNodes( this.effJaxbElements, context, node.getModelObject().getIdentifier() );
1202 
1203            final Map<String, Set<Node<Dependency>>> declDependencies =
1204                getEffectiveNodes( this.effDependencies, classDeclaration.getIdentifier(),
1205                                   classDeclaration.getIdentifier() );
1206 
1207            final Map<String, Set<Node<Message>>> declMessages =
1208                getEffectiveNodes( this.effMessages, classDeclaration.getIdentifier(),
1209                                   classDeclaration.getIdentifier() );
1210 
1211            final Map<String, Set<Node<Property>>> declProperties =
1212                getEffectiveNodes( this.effProperties, classDeclaration.getIdentifier(),
1213                                   classDeclaration.getIdentifier() );
1214 
1215            final Map<String, Set<Node<SpecificationReference>>> declSpecReferences =
1216                getEffectiveNodes( this.effSpecReferences, classDeclaration.getIdentifier(),
1217                                   classDeclaration.getIdentifier() );
1218 
1219            final Map<QName, Set<Node<Element>>> declXmlElements =
1220                getEffectiveNodes( this.effXmlElements, classDeclaration.getIdentifier(),
1221                                   classDeclaration.getIdentifier() );
1222 
1223            final Map<QName, Set<Node<JAXBElement<?>>>> declJaxbElements =
1224                getEffectiveNodes( this.effJaxbElements, classDeclaration.getIdentifier(),
1225                                   classDeclaration.getIdentifier() );
1226 
1227            if ( declDependencies != null )
1228            {
1229                if ( effectiveDependencies == null )
1230                {
1231                    effectiveDependencies = newMap();
1232                    map( this.effDependencies, context ).
1233                        put( node.getModelObject().getIdentifier(), effectiveDependencies );
1234 
1235                }
1236 
1237                for ( Map.Entry<String, Set<Node<Dependency>>> e : declDependencies.entrySet() )
1238                {
1239                    final Set<Node<Dependency>> set = newSet( e.getValue().size() );
1240 
1241                    for ( final Node<Dependency> n : e.getValue() )
1242                    {
1243                        final Node<Dependency> effNode = new Node<Dependency>(
1244                            node.getModelObject(), n.getSpecification(), classDeclaration, null, n.getModelObject(),
1245                            n.isFinal(), n.isOverride() );
1246 
1247                        effNode.getModifiablePath().addAll( n.getPath() );
1248                        set.add( effNode );
1249 
1250                        addNode( map( this.dependencies, context ), effNode, e.getKey() );
1251                    }
1252 
1253                    if ( effectiveDependencies.containsKey( e.getKey() ) )
1254                    {
1255                        for ( final Node<Dependency> effNode : effectiveDependencies.get( e.getKey() ) )
1256                        {
1257                            effNode.getModifiableOverriddenNodes().addAll( set );
1258                        }
1259                    }
1260                    else
1261                    {
1262                        effectiveDependencies.put( e.getKey(), set );
1263                    }
1264                }
1265            }
1266 
1267            if ( declSpecReferences != null )
1268            {
1269                if ( effectiveSpecificationReferences == null )
1270                {
1271                    effectiveSpecificationReferences = newMap();
1272                    map( this.effSpecReferences, context ).
1273                        put( node.getModelObject().getIdentifier(), effectiveSpecificationReferences );
1274 
1275                }
1276 
1277                for ( Map.Entry<String, Set<Node<SpecificationReference>>> e : declSpecReferences.entrySet() )
1278                {
1279                    final Set<Node<SpecificationReference>> set = newSet( e.getValue().size() );
1280 
1281                    for ( final Node<SpecificationReference> n : e.getValue() )
1282                    {
1283                        final Node<SpecificationReference> effNode = new Node<SpecificationReference>(
1284                            node.getModelObject(), n.getSpecification(), classDeclaration, null, n.getModelObject(),
1285                            n.isFinal(), n.isOverride() );
1286 
1287                        effNode.getModifiablePath().addAll( n.getPath() );
1288                        set.add( effNode );
1289 
1290                        addNode( map( this.specReferences, context ), effNode, e.getKey() );
1291                    }
1292 
1293                    if ( effectiveSpecificationReferences.containsKey( e.getKey() ) )
1294                    {
1295                        for ( final Node<SpecificationReference> effNode
1296                              : effectiveSpecificationReferences.get( e.getKey() ) )
1297                        {
1298                            effNode.getModifiableOverriddenNodes().addAll( set );
1299                        }
1300                    }
1301                    else
1302                    {
1303                        effectiveSpecificationReferences.put( e.getKey(), set );
1304                    }
1305                }
1306            }
1307 
1308            if ( declMessages != null )
1309            {
1310                if ( effectiveMessages == null )
1311                {
1312                    effectiveMessages = newMap();
1313                    map( this.effMessages, context ).
1314                        put( node.getModelObject().getIdentifier(), effectiveMessages );
1315 
1316                }
1317 
1318                for ( Map.Entry<String, Set<Node<Message>>> e : declMessages.entrySet() )
1319                {
1320                    final Set<Node<Message>> set = newSet( e.getValue().size() );
1321 
1322                    for ( final Node<Message> n : e.getValue() )
1323                    {
1324                        final Node<Message> effNode = new Node<Message>(
1325                            node.getModelObject(), n.getSpecification(), classDeclaration, null, n.getModelObject(),
1326                            n.isFinal(), n.isOverride() );
1327 
1328                        effNode.getModifiablePath().addAll( n.getPath() );
1329                        set.add( effNode );
1330 
1331                        addNode( map( this.messages, context ), effNode, e.getKey() );
1332                    }
1333 
1334                    if ( effectiveMessages.containsKey( e.getKey() ) )
1335                    {
1336                        for ( final Node<Message> effNode : effectiveMessages.get( e.getKey() ) )
1337                        {
1338                            effNode.getModifiableOverriddenNodes().addAll( set );
1339                        }
1340                    }
1341                    else
1342                    {
1343                        effectiveMessages.put( e.getKey(), set );
1344                    }
1345                }
1346            }
1347 
1348            if ( declProperties != null )
1349            {
1350                if ( effectiveProperties == null )
1351                {
1352                    effectiveProperties = newMap();
1353                    map( this.effProperties, context ).
1354                        put( node.getModelObject().getIdentifier(), effectiveProperties );
1355 
1356                }
1357 
1358                for ( Map.Entry<String, Set<Node<Property>>> e : declProperties.entrySet() )
1359                {
1360                    final Set<Node<Property>> set = newSet( e.getValue().size() );
1361 
1362                    for ( final Node<Property> n : e.getValue() )
1363                    {
1364                        final Node<Property> effNode = new Node<Property>(
1365                            node.getModelObject(), n.getSpecification(), classDeclaration, null, n.getModelObject(),
1366                            n.isFinal(), n.isOverride() );
1367 
1368                        effNode.getModifiablePath().addAll( n.getPath() );
1369                        set.add( effNode );
1370 
1371                        addNode( map( this.properties, context ), effNode, e.getKey() );
1372                    }
1373 
1374                    if ( effectiveProperties.containsKey( e.getKey() ) )
1375                    {
1376                        for ( final Node<Property> effNode : effectiveProperties.get( e.getKey() ) )
1377                        {
1378                            effNode.getModifiableOverriddenNodes().addAll( set );
1379                        }
1380                    }
1381                    else
1382                    {
1383                        effectiveProperties.put( e.getKey(), set );
1384                    }
1385                }
1386            }
1387 
1388            if ( declXmlElements != null )
1389            {
1390                if ( effectiveXmlElements == null )
1391                {
1392                    effectiveXmlElements = newMap();
1393                    map( this.effXmlElements, context ).
1394                        put( node.getModelObject().getIdentifier(), effectiveXmlElements );
1395 
1396                }
1397 
1398                for ( Map.Entry<QName, Set<Node<Element>>> e : declXmlElements.entrySet() )
1399                {
1400                    final Set<Node<Element>> set = newSet( e.getValue().size() );
1401 
1402                    for ( final Node<Element> n : e.getValue() )
1403                    {
1404                        final Node<Element> effNode = new Node<Element>(
1405                            node.getModelObject(), n.getSpecification(), classDeclaration, null, n.getModelObject(),
1406                            n.isFinal(), n.isOverride() );
1407 
1408                        effNode.getModifiablePath().addAll( n.getPath() );
1409                        set.add( effNode );
1410 
1411                        addNode( map( this.xmlElements, context ), effNode, e.getKey() );
1412                    }
1413 
1414                    if ( effectiveXmlElements.containsKey( e.getKey() ) )
1415                    {
1416                        for ( final Node<Element> effNode : effectiveXmlElements.get( e.getKey() ) )
1417                        {
1418                            effNode.getModifiableOverriddenNodes().addAll( set );
1419                        }
1420                    }
1421                    else
1422                    {
1423                        effectiveXmlElements.put( e.getKey(), set );
1424                    }
1425                }
1426            }
1427 
1428            if ( declJaxbElements != null )
1429            {
1430                if ( effectiveJaxbElements == null )
1431                {
1432                    effectiveJaxbElements = newMap();
1433                    map( this.effJaxbElements, context ).
1434                        put( node.getModelObject().getIdentifier(), effectiveJaxbElements );
1435 
1436                }
1437 
1438                for ( Map.Entry<QName, Set<Node<JAXBElement<?>>>> e : declJaxbElements.entrySet() )
1439                {
1440                    final Set<Node<JAXBElement<?>>> set = newSet( e.getValue().size() );
1441 
1442                    for ( final Node<JAXBElement<?>> n : e.getValue() )
1443                    {
1444                        final Node<JAXBElement<?>> effNode = new Node<JAXBElement<?>>(
1445                            node.getModelObject(), n.getSpecification(), classDeclaration, null, n.getModelObject(),
1446                            n.isFinal(), n.isOverride() );
1447 
1448                        effNode.getModifiablePath().addAll( n.getPath() );
1449                        set.add( effNode );
1450 
1451                        addNode( map( this.jaxbElements, context ), effNode, e.getKey() );
1452                    }
1453 
1454                    if ( effectiveJaxbElements.containsKey( e.getKey() ) )
1455                    {
1456                        for ( final Node<JAXBElement<?>> effNode : effectiveJaxbElements.get( e.getKey() ) )
1457                        {
1458                            effNode.getModifiableOverriddenNodes().addAll( set );
1459                        }
1460                    }
1461                    else
1462                    {
1463                        effectiveJaxbElements.put( e.getKey(), set );
1464                    }
1465                }
1466            }
1467        }
1468    }
1469 
1470    private Implementation getClassDeclaration( final Implementation implementation )
1471    {
1472        Implementation declaration = null;
1473 
1474        if ( implementation.getClazz() != null && !implementation.isClassDeclaration() )
1475        {
1476            find:
1477            for ( int i = 0, s0 = this.modules.getModule().size(); i < s0; i++ )
1478            {
1479                final Module candidateModule = this.modules.getModule().get( i );
1480 
1481                if ( candidateModule.getImplementations() != null )
1482                {
1483                    for ( int j = 0, s1 = candidateModule.getImplementations().getImplementation().size(); j < s1; j++ )
1484                    {
1485                        final Implementation candidate =
1486                            candidateModule.getImplementations().getImplementation().get( j );
1487 
1488                        if ( candidate.isClassDeclaration()
1489                             && candidate.getClazz().equals( implementation.getClazz() ) )
1490                        {
1491                            declaration = candidate;
1492                            break find;
1493                        }
1494                    }
1495                }
1496            }
1497        }
1498 
1499        return declaration;
1500    }
1501 
1502    private static <T, K> void addNode( final Map<K, Set<Node<T>>> map, final Node<T> node, final K key )
1503    {
1504        Set<Node<T>> set = map.get( key );
1505 
1506        if ( set == null )
1507        {
1508            set = newSet();
1509            map.put( key, set );
1510        }
1511 
1512        set.add( node );
1513    }
1514 
1515    private static <T, K> void overrideNodes( final Map<String, Map<K, Set<Node<T>>>> effective,
1516                                              final Node<Implementation> implementation,
1517                                              final Map<K, Set<Node<T>>> directNodes )
1518    {
1519        for ( final Map.Entry<K, Set<Node<T>>> e : directNodes.entrySet() )
1520        {
1521            final Set<Node<T>> effectiveNodes =
1522                effectiveNodes( effective, implementation.getModelObject().getIdentifier(), e.getKey() );
1523 
1524            final Set<Node<T>> overridingNodes = newSet();
1525 
1526            for ( final Node<T> directNode : e.getValue() )
1527            {
1528                for ( final Iterator<Node<T>> it = effectiveNodes.iterator(); it.hasNext(); )
1529                {
1530                    final Node<T> effectiveNode = it.next();
1531 
1532                    if ( isOverriding( effectiveNode, directNode ) )
1533                    {
1534                        it.remove();
1535 
1536                        if ( directNode != effectiveNode )
1537                        {
1538                            directNode.getModifiableOverriddenNodes().add( effectiveNode );
1539                        }
1540                    }
1541                }
1542 
1543                boolean overriddenByAncestor = false;
1544 
1545                if ( directNode.getSpecification() != null )
1546                {
1547                    for ( final Node<T> effectiveNode : effectiveNodes )
1548                    {
1549                        if ( effectiveNode.getSpecification() == null )
1550                        {
1551                            overriddenByAncestor = true;
1552                            effectiveNode.getModifiableOverriddenNodes().add( directNode );
1553                        }
1554                    }
1555                }
1556 
1557                if ( !overriddenByAncestor )
1558                {
1559                    overridingNodes.add( directNode );
1560                }
1561            }
1562 
1563            effectiveNodes.addAll( overridingNodes );
1564        }
1565    }
1566 
1567    private static <K, V, T> Map<K, V> map( final Map<T, Map<K, V>> map, final T context )
1568    {
1569        Map<K, V> contextMap = map.get( context );
1570 
1571        if ( contextMap == null )
1572        {
1573            contextMap = newMap();
1574            map.put( context, contextMap );
1575        }
1576 
1577        return contextMap;
1578    }
1579 
1580    private static <K, V> Set<Node<V>> nodes( final Map<K, Set<Node<V>>> map, final K key )
1581    {
1582        Set<Node<V>> nodes = map.get( key );
1583 
1584        if ( nodes == null )
1585        {
1586            nodes = newSet();
1587            map.put( key, nodes );
1588        }
1589 
1590        return nodes;
1591    }
1592 
1593    private static <K, V> Set<Node<V>> effectiveNodes( final Map<String, Map<K, Set<Node<V>>>> map,
1594                                                       final String context, final K key )
1595    {
1596        return nodes( map( map, context ), key );
1597    }
1598 
1599    private static <T, K> void inheritNodes(
1600        final Map<String, Map<K, Set<Node<T>>>> effective, final Map<K, Set<Node<T>>> ancestor,
1601        final Node<Implementation> descendant )
1602    {
1603        for ( Map.Entry<K, Set<Node<T>>> e : ancestor.entrySet() )
1604        {
1605            for ( final Node<T> inherit : e.getValue() )
1606            {
1607                if ( isInheritableNode( inherit ) )
1608                {
1609                    effectiveNodes( effective, descendant.getModelObject().getIdentifier(), e.getKey() ).add( inherit );
1610                }
1611            }
1612        }
1613    }
1614 
1615    private static <T, K> Map<K, Set<Node<T>>> getDirectEffectiveNodes( final Map<K, Set<Node<T>>> map,
1616                                                                        final String origin )
1617    {
1618        final Map<K, Set<Node<T>>> declarationMap = newMap( map.size() );
1619 
1620        for ( Map.Entry<K, Set<Node<T>>> e : map.entrySet() )
1621        {
1622            final Set<Node<T>> set = nodes( declarationMap, e.getKey() );
1623 
1624            for ( final Node<T> n : e.getValue() )
1625            {
1626                if ( isDirectEffectiveNode( n, origin ) )
1627                {
1628                    set.add( n );
1629                }
1630            }
1631 
1632            for ( final Node<T> n : e.getValue() )
1633            {
1634                if ( isDirectSpecifiedNode( n, origin ) )
1635                {
1636                    boolean add = true;
1637 
1638                    for ( final Node<T> override : set )
1639                    {
1640                        if ( override.getSpecification() == null )
1641                        {
1642                            override.getModifiableOverriddenNodes().add( n );
1643                            add = false;
1644                        }
1645                    }
1646 
1647                    if ( add )
1648                    {
1649                        set.add( n );
1650                    }
1651                }
1652            }
1653        }
1654 
1655        return declarationMap;
1656    }
1657 
1658    private static <T, K> Map<K, Set<Node<T>>> getEffectiveNodes(
1659        final Map<String, Map<String, Map<K, Set<Node<T>>>>> effective, final String context,
1660        final String implementation )
1661    {
1662        return map( effective, context ).get( implementation );
1663    }
1664 
1665    private static boolean isDirectNode( final Node<?> node, final String implementation )
1666    {
1667        return implementation.equals( node.getImplementation().getIdentifier() );
1668    }
1669 
1670    private static boolean isDirectEffectiveNode( final Node<?> node, final String implementation )
1671    {
1672        return isDirectNode( node, implementation ) && node.getClassDeclaration() == null
1673               && node.getSpecification() == null;
1674 
1675    }
1676 
1677    private static boolean isDirectSpecifiedNode( final Node<?> node, final String implementation )
1678    {
1679        return isDirectNode( node, implementation ) && node.getClassDeclaration() == null
1680               && node.getSpecification() != null;
1681 
1682    }
1683 
1684    private static boolean isOverriding( final Node<?> node, final Node<?> override )
1685    {
1686        if ( override.getSpecification() != null )
1687        {
1688            if ( node.getSpecification() == null )
1689            {
1690                return false;
1691            }
1692            else if ( !override.getSpecification().getIdentifier().equals( node.getSpecification().getIdentifier() ) )
1693            {
1694                return false;
1695            }
1696        }
1697 
1698        return true;
1699    }
1700 
1701    private static boolean isInheritableNode( final Node<?> node )
1702    {
1703        return node.getClassDeclaration() == null;
1704    }
1705 
1706    private static <K, V> Map<K, V> newMap()
1707    {
1708        return new HashMap<K, V>();
1709    }
1710 
1711    private static <K, V> Map<K, V> newMap( final int initialCapacity )
1712    {
1713        return new HashMap<K, V>( initialCapacity );
1714    }
1715 
1716    private static <T> Set<T> newSet()
1717    {
1718        return new HashSet<T>();
1719    }
1720 
1721    private static <T> Set<T> newSet( final int initialCapacity )
1722    {
1723        return new HashSet<T>( initialCapacity );
1724    }
1725 
1726    private static <T> Set<T> newSet( final Collection<? extends T> col )
1727    {
1728        return new HashSet<T>( col );
1729    }
1730 
1731    private static <T> Set<T> unmodifiableSet( final Set<T> set )
1732    {
1733        return set != null ? Collections.unmodifiableSet( set ) : Collections.<T>emptySet();
1734    }
1735 
1736    private static QName getXmlElementName( final Element element )
1737    {
1738        if ( element.getNamespaceURI() != null )
1739        {
1740            return new QName( element.getNamespaceURI(), element.getLocalName() );
1741        }
1742        else
1743        {
1744            return new QName( element.getLocalName() );
1745        }
1746    }
1747 
1748}

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