| 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 |  */ | 
| 31 | package org.jomc.model; | 
| 32 |   | 
| 33 | import java.util.Collection; | 
| 34 | import java.util.Collections; | 
| 35 | import java.util.HashMap; | 
| 36 | import java.util.HashSet; | 
| 37 | import java.util.Iterator; | 
| 38 | import java.util.LinkedList; | 
| 39 | import java.util.List; | 
| 40 | import java.util.Map; | 
| 41 | import java.util.Set; | 
| 42 | import javax.xml.bind.JAXBElement; | 
| 43 | import javax.xml.namespace.QName; | 
| 44 | import 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 |  */ | 
| 53 | public 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 | } |