001 /* 002 * Copyright (C) Christian Schulte, 2011-325 003 * All rights reserved. 004 * 005 * Redistribution and use in source and binary forms, with or without 006 * modification, are permitted provided that the following conditions 007 * are met: 008 * 009 * o Redistributions of source code must retain the above copyright 010 * notice, this list of conditions and the following disclaimer. 011 * 012 * o Redistributions in binary form must reproduce the above copyright 013 * notice, this list of conditions and the following disclaimer in 014 * the documentation and/or other materials provided with the 015 * distribution. 016 * 017 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 018 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 019 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 020 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT, 021 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 022 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 023 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 024 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 025 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 026 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 027 * 028 * $JOMC: InheritanceModel.java 4138 2011-12-27 18:10:02Z schulte2005 $ 029 * 030 */ 031 package org.jomc.model; 032 033 import java.util.Collection; 034 import java.util.Collections; 035 import java.util.HashMap; 036 import java.util.HashSet; 037 import java.util.Iterator; 038 import java.util.LinkedList; 039 import java.util.List; 040 import java.util.Map; 041 import java.util.Set; 042 import javax.xml.bind.JAXBElement; 043 import javax.xml.namespace.QName; 044 import org.w3c.dom.Element; 045 046 /** 047 * Inheritance model. 048 * 049 * @author <a href="mailto:schulte2005@users.sourceforge.net">Christian Schulte</a> 050 * @version $JOMC: InheritanceModel.java 4138 2011-12-27 18:10:02Z schulte2005 $ 051 * @since 1.2 052 */ 053 public class InheritanceModel 054 { 055 056 /** 057 * Inheritance model node. 058 * 059 * @param <T> The type of the model object of the node. 060 * 061 * @author <a href="mailto:schulte2005@users.sourceforge.net">Christian Schulte</a> 062 * @version $JOMC: InheritanceModel.java 4138 2011-12-27 18:10:02Z schulte2005 $ 063 * @since 1.2 064 */ 065 public static class Node<T> 066 { 067 068 /** The implementation the node originates from. */ 069 private final Implementation implementation; 070 071 /** The specification the node originates from. */ 072 private final Specification specification; 073 074 /** The class declaration the node originates from. */ 075 private final Implementation classDeclaration; 076 077 /** The direct descendant node. */ 078 private final Node<Implementation> descendant; 079 080 /** The model object of the node. */ 081 private final T modelObject; 082 083 /** Flag indicating the node is the final node in an inheritance hierarchy. */ 084 private final boolean _final; 085 086 /** Flag indicating the node is intended to override an ancestor node. */ 087 private final boolean override; 088 089 /** The path to the node. */ 090 private final LinkedList<Node<Implementation>> path = new LinkedList<Node<Implementation>>(); 091 092 /** The nodes overridden by the node. */ 093 private final Set<Node<T>> overriddenNodes = new HashSet<Node<T>>(); 094 095 /** 096 * Creates a new {@code Node} instance. 097 * 098 * @param implementation The implementation the node originates from. 099 * @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 }