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