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