InheritanceModel.java
/*
* Copyright (C) Christian Schulte <cs@schulte.it>, 2011-325
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* o Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* o Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $JOMC: InheritanceModel.java 5043 2015-05-27 07:03:39Z schulte $
*
*/
package org.jomc.model;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.bind.JAXBElement;
import javax.xml.namespace.QName;
import org.w3c.dom.Element;
/**
* Inheritance model.
*
* @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
* @version $JOMC: InheritanceModel.java 5043 2015-05-27 07:03:39Z schulte $
* @since 1.2
*/
public class InheritanceModel
{
/**
* Inheritance model node.
*
* @param <T> The type of the model object of the node.
*
* @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
* @version $JOMC: InheritanceModel.java 5043 2015-05-27 07:03:39Z schulte $
* @since 1.2
*/
public static class Node<T>
{
/**
* The implementation the node originates from.
*/
private final Implementation implementation;
/**
* The specification the node originates from.
*/
private final Specification specification;
/**
* The class declaration the node originates from.
*/
private final Implementation classDeclaration;
/**
* The direct descendant node.
*/
private final Node<Implementation> descendant;
/**
* The model object of the node.
*/
private final T modelObject;
/**
* Flag indicating the node is the final node in an inheritance hierarchy.
*/
private final boolean _final;
/**
* Flag indicating the node is intended to override an ancestor node.
*/
private final boolean override;
/**
* The path to the node.
*/
private final LinkedList<Node<Implementation>> path = new LinkedList<Node<Implementation>>();
/**
* The nodes overridden by the node.
*/
private final Set<Node<T>> overriddenNodes = new HashSet<Node<T>>();
/**
* Creates a new {@code Node} instance.
*
* @param implementation The implementation the node originates from.
* @param specification The specification the node originates from or {@code null}.
* @param classDeclaration The class declaration the node originates from or {@code null}.
* @param descendant The direct descendant node of the node or {@code null}.
* @param modelObject The model object of the node.
* @param finalNode {@code true}, if the node is the final node in an inheritance hierarchy; {@code false},
* else.
* @param overrideNode {@code true}, if the node is intended to override an ancestor node; {@code false}, else.
*/
public Node( final Implementation implementation, final Specification specification,
final Implementation classDeclaration, final Node<Implementation> descendant, final T modelObject,
final boolean finalNode, final boolean overrideNode )
{
super();
this.implementation = implementation;
this.specification = specification;
this.classDeclaration = classDeclaration;
this.descendant = descendant;
this.modelObject = modelObject;
this._final = finalNode;
this.override = overrideNode;
}
/**
* Gets the implementation the node originates from.
*
* @return The implementation the node originates from.
*/
public final Implementation getImplementation()
{
return this.implementation;
}
/**
* Gets the specification the node originates from.
*
* @return The specification the node originates from or {@code null}, if the node does not originate from a
* specification.
*/
public final Specification getSpecification()
{
return this.specification;
}
/**
* Gets the class declaration the node originates from.
*
* @return The class declaration the node originates from or {@code null}, if the node does not originate from a
* class declaration.
*/
public final Implementation getClassDeclaration()
{
return this.classDeclaration;
}
/**
* Gets the direct descendant node of the node.
*
* @return The direct descendant node of the node or {@code null}.
*
* @see InheritanceModel#getSourceNodes(java.lang.String)
*/
public final Node<Implementation> getDescendant()
{
return this.descendant;
}
/**
* Gets the model object of the node.
*
* @return The model object of the node.
*/
public final T getModelObject()
{
return this.modelObject;
}
/**
* Gets a flag indicating the node is the final node in an inheritance hierarchy.
*
* @return {@code true}, if the node is the final node in an inheritance hierarchy; {@code false}, else.
*/
public final boolean isFinal()
{
return this._final;
}
/**
* Gets a flag indicating the node is intended to override an ancestor node.
*
* @return {@code true}, if the node is intended to override an ancestor; {@code false} else.
*/
public final boolean isOverride()
{
return this.override;
}
/**
* Gets a set of nodes overridden by the node.
*
* @return An unmodifiable set holding nodes overridden by the node.
*/
public final Set<Node<T>> getOverriddenNodes()
{
return Collections.unmodifiableSet( this.overriddenNodes );
}
/**
* Gets the path to the node.
*
* @return An unmodifiable list holding path elements.
*/
public final List<Node<Implementation>> getPath()
{
return Collections.unmodifiableList( this.path );
}
/**
* Gets a set of nodes overridden by the node.
*
* @return A modifiable set holding nodes overridden by the node.
*
* @see #getOverriddenNodes()
*/
private Set<Node<T>> getModifiableOverriddenNodes()
{
return this.overriddenNodes;
}
/**
* Gets the path to the node.
*
* @return A modifiable list holding path nodes of the node.
*
* @see #getPath()
*/
private LinkedList<Node<Implementation>> getModifiablePath()
{
return this.path;
}
}
/**
* Enumeration of context states.
*/
private enum ContextState
{
PREPARING,
PREPARED
}
/**
* The modules backing the model.
*/
private final Modules modules;
/**
* {@code Dependency} nodes by context and dependency name.
*/
private final Map<String, Map<String, Set<Node<Dependency>>>> dependencies = newMap();
/**
* {@code Dependency} nodes by context and implementation identifier.
*/
private final Map<String, Map<String, Map<String, Set<Node<Dependency>>>>> effDependencies = newMap();
/**
* {@code Message} nodes by context and message name.
*/
private final Map<String, Map<String, Set<Node<Message>>>> messages = newMap();
/**
* {@code Message} nodes by context and implementation identifier.
*/
private final Map<String, Map<String, Map<String, Set<Node<Message>>>>> effMessages = newMap();
/**
* {@code Property} nodes by context and property name.
*/
private final Map<String, Map<String, Set<Node<Property>>>> properties = newMap();
/**
* {@code Property} nodes by context and implementation identifier.
*/
private final Map<String, Map<String, Map<String, Set<Node<Property>>>>> effProperties = newMap();
/**
* {@code SpecificationReference} nodes by context and specification identifier.
*/
private final Map<String, Map<String, Set<Node<SpecificationReference>>>> specReferences = newMap();
/**
* {@code SpecificationReference} nodes by context and implementation identifier.
*/
private final Map<String, Map<String, Map<String, Set<Node<SpecificationReference>>>>> effSpecReferences =
newMap();
/**
* {@code ImplementationReference} nodes by context and implementation reference identifier.
*/
private final Map<String, Map<String, Set<Node<ImplementationReference>>>> implReferences = newMap();
/**
* {@code ImplementationReference} nodes by context and implementation reference identifier.
*/
private final Map<String, Set<Node<ImplementationReference>>> cyclicImplReferences = newMap();
/**
* {@code ImplementationReference} nodes by context and implementation identifier.
*/
private final Map<String, Map<String, Map<String, Set<Node<ImplementationReference>>>>> effImplReferences =
newMap();
/**
* {@code Element} nodes by context and qualified name.
*/
private final Map<String, Map<QName, Set<Node<Element>>>> xmlElements = newMap();
/**
* {@code Element} nodes by context and implementation identifier.
*/
private final Map<String, Map<String, Map<QName, Set<Node<Element>>>>> effXmlElements = newMap();
/**
* {@code JAXBElement} nodes by context and qualified name.
*/
private final Map<String, Map<QName, Set<Node<JAXBElement<?>>>>> jaxbElements = newMap();
/**
* {@code JAXBElement} nodes by context and implementation identifier.
*/
private final Map<String, Map<String, Map<QName, Set<Node<JAXBElement<?>>>>>> effJaxbElements =
newMap();
/**
* {@code Implementation} nodes by context and implementation identifier.
*/
private final Map<String, Map<String, Node<Implementation>>> implementations = newMap();
/**
* Source nodes of a hierarchy by context and implementation identifier.
*/
private final Map<String, Map<String, Node<Implementation>>> sourceNodes = newMap();
/**
* Context states by context identifier.
*/
private final Map<String, ContextState> contextStates = newMap();
/**
* Creates a new {@code InheritanceModel} instance.
*
* @param modules The modules backing the model.
*
* @throws NullPointerException if {@code modules} is {@code null}.
*
* @see Modules#clone()
*/
public InheritanceModel( final Modules modules )
{
super();
if ( modules == null )
{
throw new NullPointerException( "modules" );
}
this.modules = modules.clone();
}
/**
* Gets a set holding source nodes of an implementation.
*
* @param implementation The identifier of the implementation to get source nodes of.
*
* @return An unmodifiable set holding source nodes of the implementation identified by {@code implementation}.
*
* @throws NullPointerException if {@code implementation} is {@code null}.
*
* @see Node#getDescendant()
*/
public Set<Node<Implementation>> getSourceNodes( final String implementation )
{
if ( implementation == null )
{
throw new NullPointerException( "implementation" );
}
this.prepareContext( implementation );
final Collection<Node<Implementation>> col = map( this.sourceNodes, implementation ).values();
return unmodifiableSet( newSet( col ) );
}
/**
* Gets a set holding implementation reference nodes of an implementation causing a cycle.
*
* @param implementation The identifier of the implementation to get implementation reference nodes causing a cycle
* of.
*
* @return An unmodifiable set holding implementation reference nodes of the implementation identified by
* {@code implementation} causing a cycle.
*
* @throws NullPointerException if {@code implementation} is {@code null}.
*
* @since 1.5
*
* @see Node#getPath()
*/
public Set<Node<ImplementationReference>> getCycleNodes( final String implementation )
{
if ( implementation == null )
{
throw new NullPointerException( "implementation" );
}
this.prepareContext( implementation );
return unmodifiableSet( nodes( this.cyclicImplReferences, implementation ) );
}
/**
* Gets a set holding the names of all dependencies of an implementation.
*
* @param implementation The identifier of the implementation to get the names of all dependencies of.
*
* @return An unmodifiable set holding the names of all dependencies of the implementation identified by
* {@code implementation}.
*
* @throws NullPointerException if {@code implementation} is {@code null}.
*/
public Set<String> getDependencyNames( final String implementation )
{
if ( implementation == null )
{
throw new NullPointerException( "implementation" );
}
this.prepareContext( implementation );
return Collections.unmodifiableSet( map( this.dependencies, implementation ).keySet() );
}
/**
* Gets a set holding effective dependency nodes of an implementation.
*
* @param implementation The identifier of the implementation to get effective dependency nodes of.
* @param name The dependency name to get effective nodes for.
*
* @return An unmodifiable set holding effective dependency nodes matching {@code name} of the implementation
* identified by {@code implementation}.
*
* @throws NullPointerException if {@code implementation} or {@code name} is {@code null}.
*
* @see #getDependencyNames(java.lang.String)
*/
public Set<Node<Dependency>> getDependencyNodes( final String implementation, final String name )
{
if ( implementation == null )
{
throw new NullPointerException( "implementation" );
}
if ( name == null )
{
throw new NullPointerException( "name" );
}
this.prepareContext( implementation );
Set<Node<Dependency>> set = null;
final Map<String, Set<Node<Dependency>>> map =
getEffectiveNodes( this.effDependencies, implementation, implementation );
if ( map != null )
{
set = map.get( name );
}
return unmodifiableSet( set );
}
/**
* Gets a set holding the identifiers of all implementation references of an implementation.
*
* @param implementation The identifier of the implementation to get the identifiers of all implementation
* references of.
*
* @return An unmodifiable set holding the identifiers of all implementation references of the implementation
* identified by {@code implementation}.
*
* @throws NullPointerException if {@code implementation} is {@code null}.
*/
public Set<String> getImplementationReferenceIdentifiers( final String implementation )
{
if ( implementation == null )
{
throw new NullPointerException( "implementation" );
}
this.prepareContext( implementation );
return Collections.unmodifiableSet( map( this.implReferences, implementation ).keySet() );
}
/**
* Gets a set holding effective implementation reference nodes of an implementation.
*
* @param implementation The identifier of the implementation to get effective implementation reference nodes of.
* @param identifier The implementation reference identifier to get effective nodes for.
*
* @return An unmodifiable set holding effective implementation reference nodes matching {@code identifier} of the
* implementation identified by {@code implementation}.
*
* @throws NullPointerException if {@code implementation} or {@code identifier} is {@code null}.
*
* @see #getImplementationReferenceIdentifiers(java.lang.String)
*/
public Set<Node<ImplementationReference>> getImplementationReferenceNodes( final String implementation,
final String identifier )
{
if ( implementation == null )
{
throw new NullPointerException( "implementation" );
}
if ( identifier == null )
{
throw new NullPointerException( "identifier" );
}
this.prepareContext( implementation );
Set<Node<ImplementationReference>> set = null;
final Map<String, Set<Node<ImplementationReference>>> map =
getEffectiveNodes( this.effImplReferences, implementation, implementation );
if ( map != null )
{
set = map.get( identifier );
}
return unmodifiableSet( set );
}
/**
* Gets a set holding the qualified names of all XML elements of an implementation.
*
* @param implementation The identifier of the implementation to get the qualified names of all XML elements of.
*
* @return An unmodifiable set holding the qualified names of all XML elements of the implementation identified by
* {@code implementation}.
*
* @throws NullPointerException if {@code implementation} is {@code null}.
*/
public Set<QName> getJaxbElementNames( final String implementation )
{
if ( implementation == null )
{
throw new NullPointerException( "implementation" );
}
this.prepareContext( implementation );
return Collections.unmodifiableSet( map( this.jaxbElements, implementation ).keySet() );
}
/**
* Gets a set holding effective JAXB element nodes of an implementation.
*
* @param implementation The identifier of the implementation to get effective JAXB element nodes of.
* @param name The qualified JAXB element name to get effective nodes for.
*
* @return An unmodifiable set holding effective JAXB element nodes matching {@code name} of the implementation
* identified by {@code implementation}.
*
* @throws NullPointerException if {@code implementation} or {@code name} is {@code null}.
*
* @see #getJaxbElementNames(java.lang.String)
*/
public Set<Node<JAXBElement<?>>> getJaxbElementNodes( final String implementation, final QName name )
{
if ( implementation == null )
{
throw new NullPointerException( "implementation" );
}
if ( name == null )
{
throw new NullPointerException( "name" );
}
this.prepareContext( implementation );
Set<Node<JAXBElement<?>>> set = null;
final Map<QName, Set<Node<JAXBElement<?>>>> map =
getEffectiveNodes( this.effJaxbElements, implementation, implementation );
if ( map != null )
{
set = map.get( name );
}
return unmodifiableSet( set );
}
/**
* Gets a set holding the names of all messages of an implementation.
*
* @param implementation The identifier of the implementation to get the names of all messages of.
*
* @return An unmodifiable set holding the names of all messages of the implementation identified by
* {@code implementation}.
*
* @throws NullPointerException if {@code implementation} is {@code null}.
*/
public Set<String> getMessageNames( final String implementation )
{
if ( implementation == null )
{
throw new NullPointerException( "implementation" );
}
this.prepareContext( implementation );
return Collections.unmodifiableSet( map( this.messages, implementation ).keySet() );
}
/**
* Gets a set holding effective message nodes of an implementation.
*
* @param implementation The identifier of the implementation to get effective message nodes of.
* @param name The message name to get effective nodes for.
*
* @return An unmodifiable set holding effective message nodes matching {@code name} of the implementation
* identified by {@code implementation}.
*
* @throws NullPointerException if {@code implementation} or {@code name} is {@code null}.
*
* @see #getMessageNames(java.lang.String)
*/
public Set<Node<Message>> getMessageNodes( final String implementation, final String name )
{
if ( implementation == null )
{
throw new NullPointerException( "implementation" );
}
if ( name == null )
{
throw new NullPointerException( "name" );
}
this.prepareContext( implementation );
Set<Node<Message>> set = null;
final Map<String, Set<Node<Message>>> map =
getEffectiveNodes( this.effMessages, implementation, implementation );
if ( map != null )
{
set = map.get( name );
}
return unmodifiableSet( set );
}
/**
* Gets a set holding the names of all properties of an implementation.
*
* @param implementation The identifier of the implementation to get the names of all properties of.
*
* @return An unmodifiable set holding the names of all properties of the implementation identified by
* {@code implementation}.
*
* @throws NullPointerException if {@code implementation} is {@code null}.
*/
public Set<String> getPropertyNames( final String implementation )
{
if ( implementation == null )
{
throw new NullPointerException( "implementation" );
}
this.prepareContext( implementation );
return Collections.unmodifiableSet( map( this.properties, implementation ).keySet() );
}
/**
* Gets a set holding effective property nodes of an implementation.
*
* @param implementation The identifier of the implementation to get effective property nodes of.
* @param name The property name to get effective nodes for.
*
* @return An unmodifiable set holding effective property nodes matching {@code name} of the implementation
* identified by {@code implementation}.
*
* @throws NullPointerException if {@code implementation} or {@code name} is {@code null}.
*
* @see #getPropertyNames(java.lang.String)
*/
public Set<Node<Property>> getPropertyNodes( final String implementation, final String name )
{
if ( implementation == null )
{
throw new NullPointerException( "implementation" );
}
if ( name == null )
{
throw new NullPointerException( "name" );
}
this.prepareContext( implementation );
Set<Node<Property>> set = null;
final Map<String, Set<Node<Property>>> map =
getEffectiveNodes( this.effProperties, implementation, implementation );
if ( map != null )
{
set = map.get( name );
}
return unmodifiableSet( set );
}
/**
* Gets a set holding the identifiers of all specification references of an implementation.
*
* @param implementation The identifier of the implementation to get the identifiers of all specification references
* of.
*
* @return An unmodifiable set holding the identifiers of all specification references of the implementation
* identified by {@code implementation}.
*
* @throws NullPointerException if {@code implementation} is {@code null}.
*/
public Set<String> getSpecificationReferenceIdentifiers( final String implementation )
{
if ( implementation == null )
{
throw new NullPointerException( "implementation" );
}
this.prepareContext( implementation );
return Collections.unmodifiableSet( map( this.specReferences, implementation ).keySet() );
}
/**
* Gets a set holding effective specification reference nodes of an implementation.
*
* @param implementation The identifier of the implementation to get effective specification reference nodes of.
* @param identifier The specification reference identifier to get effective nodes for.
*
* @return An unmodifiable set holding effective specification reference nodes matching {@code identifier} of the
* implementation identified by {@code implementation}.
*
* @throws NullPointerException if {@code implementation} or {@code identifier} is {@code null}.
*
* @see #getSpecificationReferenceIdentifiers(java.lang.String)
*/
public Set<Node<SpecificationReference>> getSpecificationReferenceNodes( final String implementation,
final String identifier )
{
if ( implementation == null )
{
throw new NullPointerException( "implementation" );
}
if ( identifier == null )
{
throw new NullPointerException( "identifier" );
}
this.prepareContext( implementation );
Set<Node<SpecificationReference>> set = null;
final Map<String, Set<Node<SpecificationReference>>> map =
getEffectiveNodes( this.effSpecReferences, implementation, implementation );
if ( map != null )
{
set = map.get( identifier );
}
return unmodifiableSet( set );
}
/**
* Gets a set holding the qualified names of all XML elements of an implementation.
*
* @param implementation The identifier of the implementation to get the qualified names of all XML elements of.
*
* @return An unmodifiable set holding the qualified names of all XML elements of the implementation identified by
* {@code implementation}.
*
* @throws NullPointerException if {@code implementation} is {@code null}.
*/
public Set<QName> getXmlElementNames( final String implementation )
{
if ( implementation == null )
{
throw new NullPointerException( "implementation" );
}
this.prepareContext( implementation );
return Collections.unmodifiableSet( map( this.xmlElements, implementation ).keySet() );
}
/**
* Gets a set holding effective XML element nodes of an implementation.
*
* @param implementation The identifier of the implementation to get effective XML element nodes of.
* @param name The qualified XML element name to get effective nodes for.
*
* @return An unmodifiable set holding effective XML element nodes matching {@code name} of the implementation
* identified by {@code implementation}.
*
* @throws NullPointerException if {@code implementation} or {@code name} is {@code null}.
*
* @see #getXmlElementNames(java.lang.String)
*/
public Set<Node<Element>> getXmlElementNodes( final String implementation, final QName name )
{
if ( implementation == null )
{
throw new NullPointerException( "implementation" );
}
if ( name == null )
{
throw new NullPointerException( "name" );
}
this.prepareContext( implementation );
Set<Node<Element>> set = null;
final Map<QName, Set<Node<Element>>> map =
getEffectiveNodes( this.effXmlElements, implementation, implementation );
if ( map != null )
{
set = map.get( name );
}
return unmodifiableSet( set );
}
private void prepareContext( final String context )
{
ContextState state = this.contextStates.get( context );
if ( state == null )
{
state = ContextState.PREPARING;
this.contextStates.put( context, state );
final Implementation i = this.modules.getImplementation( context );
if ( i != null )
{
this.collectNodes( context, i, null, null );
for ( final Node<Implementation> source : map( this.sourceNodes, context ).values() )
{
this.collectEffectiveNodes( context, source );
}
}
state = ContextState.PREPARED;
this.contextStates.put( context, state );
}
assert state == ContextState.PREPARED :
"Unexpected context state '" + state + "' for context '" + context + "'.";
}
private void collectNodes( final String context, final Implementation declaration,
final Node<Implementation> descendant, LinkedList<Node<Implementation>> path )
{
if ( path == null )
{
path = new LinkedList<Node<Implementation>>();
}
final Map<String, Node<Implementation>> contextImplementations = map( this.implementations, context );
if ( declaration != null && !contextImplementations.containsKey( declaration.getIdentifier() ) )
{
final Node<Implementation> declarationNode = new Node<Implementation>(
declaration, null, null, descendant, declaration, declaration.isFinal(), false );
declarationNode.getModifiablePath().addAll( path );
contextImplementations.put( declaration.getIdentifier(), declarationNode );
path.addLast( declarationNode );
if ( declaration.getDependencies() != null )
{
for ( int i = 0, s0 = declaration.getDependencies().getDependency().size(); i < s0; i++ )
{
final Dependency d = declaration.getDependencies().getDependency().get( i );
final Node<Dependency> node =
new Node<Dependency>( declaration, null, null, descendant, d, d.isFinal(), d.isOverride() );
node.getModifiablePath().addAll( path );
addNode( map( this.dependencies, context ), node, node.getModelObject().getName() );
}
}
if ( declaration.getMessages() != null )
{
for ( int i = 0, s0 = declaration.getMessages().getMessage().size(); i < s0; i++ )
{
final Message m = declaration.getMessages().getMessage().get( i );
final Node<Message> node =
new Node<Message>( declaration, null, null, descendant, m, m.isFinal(), m.isOverride() );
node.getModifiablePath().addAll( path );
addNode( map( this.messages, context ), node, node.getModelObject().getName() );
}
if ( !declaration.getMessages().getReference().isEmpty() )
{
final Module m = this.modules.getModuleOfImplementation( declaration.getIdentifier() );
if ( m != null && m.getMessages() != null )
{
for ( int i = 0, s0 = declaration.getMessages().getReference().size(); i < s0; i++ )
{
final MessageReference r = declaration.getMessages().getReference().get( i );
Message msg = m.getMessages().getMessage( r.getName() );
if ( msg != null )
{
msg = msg.clone();
msg.setFinal( r.isFinal() );
msg.setOverride( r.isOverride() );
final Node<Message> node = new Node<Message>(
declaration, null, null, descendant, msg, msg.isFinal(), msg.isOverride() );
node.getModifiablePath().addAll( path );
addNode( map( this.messages, context ), node, node.getModelObject().getName() );
}
}
}
}
}
if ( declaration.getProperties() != null )
{
for ( int i = 0, s0 = declaration.getProperties().getProperty().size(); i < s0; i++ )
{
final Property p = declaration.getProperties().getProperty().get( i );
final Node<Property> node =
new Node<Property>( declaration, null, null, descendant, p, p.isFinal(), p.isOverride() );
node.getModifiablePath().addAll( path );
addNode( map( this.properties, context ), node, node.getModelObject().getName() );
}
if ( !declaration.getProperties().getReference().isEmpty() )
{
final Module m = this.modules.getModuleOfImplementation( declaration.getIdentifier() );
if ( m != null && m.getProperties() != null )
{
for ( int i = 0, s0 = declaration.getProperties().getReference().size(); i < s0; i++ )
{
final PropertyReference r = declaration.getProperties().getReference().get( i );
Property p = m.getProperties().getProperty( r.getName() );
if ( p != null )
{
p = p.clone();
p.setFinal( r.isFinal() );
p.setOverride( r.isOverride() );
final Node<Property> node = new Node<Property>(
declaration, null, null, descendant, p, p.isFinal(), p.isOverride() );
node.getModifiablePath().addAll( path );
addNode( map( this.properties, context ), node, node.getModelObject().getName() );
}
}
}
}
}
if ( declaration.getSpecifications() != null )
{
for ( int i = 0, s0 = declaration.getSpecifications().getReference().size(); i < s0; i++ )
{
final SpecificationReference r = declaration.getSpecifications().getReference().get( i );
final Node<SpecificationReference> node = new Node<SpecificationReference>(
declaration, null, null, descendant, r, r.isFinal(), r.isOverride() );
node.getModifiablePath().addAll( path );
addNode( map( this.specReferences, context ), node, node.getModelObject().getIdentifier() );
final Specification s = this.modules.getSpecification( r.getIdentifier() );
if ( s != null && s.getProperties() != null )
{
for ( int j = 0, s1 = s.getProperties().getProperty().size(); j < s1; j++ )
{
final Property p = s.getProperties().getProperty().get( j );
final Node<Property> n =
new Node<Property>( declaration, s, null, descendant, p, p.isFinal(), p.isOverride() );
n.getModifiablePath().addAll( path );
addNode( map( this.properties, context ), n, n.getModelObject().getName() );
}
}
}
}
if ( !declaration.getAny().isEmpty() )
{
for ( int i = 0, s0 = declaration.getAny().size(); i < s0; i++ )
{
final Object any = declaration.getAny().get( i );
if ( any instanceof Element )
{
final Element e = (Element) any;
final Node<Element> node =
new Node<Element>( declaration, null, null, descendant, e, false, false );
node.getModifiablePath().addAll( path );
addNode( map( this.xmlElements, context ), node, getXmlElementName( e ) );
continue;
}
if ( any instanceof JAXBElement<?> )
{
final JAXBElement<?> e = (JAXBElement<?>) any;
boolean _final = false;
boolean override = false;
if ( e.getValue() instanceof Inheritable )
{
_final = ( (Inheritable) e.getValue() ).isFinal();
override = ( (Inheritable) e.getValue() ).isOverride();
}
final Node<JAXBElement<?>> node =
new Node<JAXBElement<?>>( declaration, null, null, descendant, e, _final, override );
node.getModifiablePath().addAll( path );
addNode( map( this.jaxbElements, context ), node, e.getName() );
continue;
}
}
}
if ( declaration.getImplementations() != null
&& !declaration.getImplementations().getReference().isEmpty() )
{
boolean all_cyclic = true;
for ( int i = 0, s0 = declaration.getImplementations().getReference().size(); i < s0; i++ )
{
final ImplementationReference r = declaration.getImplementations().getReference().get( i );
final Node<ImplementationReference> node = new Node<ImplementationReference>(
declaration, null, null, descendant, r, r.isFinal(), r.isOverride() );
node.getModifiablePath().addAll( path );
final Implementation ancestor = this.modules.getImplementation( r.getIdentifier() );
boolean cycle = false;
if ( ancestor != null && contextImplementations.containsKey( ancestor.getIdentifier() ) )
{
for ( int j = 0, s1 = path.size(); j < s1; j++ )
{
final Node<Implementation> n = path.get( j );
if ( n.getModelObject().getIdentifier().equals( ancestor.getIdentifier() ) )
{
cycle = true;
node.getModifiablePath().add( n );
break;
}
}
}
if ( cycle )
{
addNode( this.cyclicImplReferences, node, context );
}
else
{
all_cyclic = false;
addNode( map( this.implReferences, context ), node, node.getModelObject().getIdentifier() );
this.collectNodes( context, ancestor, declarationNode, path );
}
}
if ( all_cyclic )
{
map( this.sourceNodes, context ).
put( declarationNode.getModelObject().getIdentifier(), declarationNode );
}
}
else
{
map( this.sourceNodes, context ).
put( declarationNode.getModelObject().getIdentifier(), declarationNode );
}
path.removeLast();
}
}
private void collectEffectiveNodes( final String context, final Node<Implementation> node )
{
final Map<String, Set<Node<SpecificationReference>>> directSpecificationReferences =
getDirectEffectiveNodes( map( this.specReferences, context ), node.getModelObject().getIdentifier() );
final Map<String, Set<Node<Dependency>>> directDependencies =
getDirectEffectiveNodes( map( this.dependencies, context ), node.getModelObject().getIdentifier() );
final Map<String, Set<Node<Message>>> directMessages =
getDirectEffectiveNodes( map( this.messages, context ), node.getModelObject().getIdentifier() );
final Map<String, Set<Node<Property>>> directProperties =
getDirectEffectiveNodes( map( this.properties, context ), node.getModelObject().getIdentifier() );
final Map<String, Set<Node<ImplementationReference>>> directImplementationReferences =
getDirectEffectiveNodes( map( this.implReferences, context ), node.getModelObject().getIdentifier() );
final Map<QName, Set<Node<Element>>> directXmlElements =
getDirectEffectiveNodes( map( this.xmlElements, context ), node.getModelObject().getIdentifier() );
final Map<QName, Set<Node<JAXBElement<?>>>> directJaxbElements =
getDirectEffectiveNodes( map( this.jaxbElements, context ), node.getModelObject().getIdentifier() );
overrideNodes( map( this.effSpecReferences, context ), node, directSpecificationReferences );
overrideNodes( map( this.effImplReferences, context ), node, directImplementationReferences );
overrideNodes( map( this.effDependencies, context ), node, directDependencies );
overrideNodes( map( this.effMessages, context ), node, directMessages );
overrideNodes( map( this.effProperties, context ), node, directProperties );
overrideNodes( map( this.effJaxbElements, context ), node, directJaxbElements );
overrideNodes( map( this.effXmlElements, context ), node, directXmlElements );
this.addClassDeclarationNodes( context, node );
final Map<String, Set<Node<SpecificationReference>>> ancestorSpecificationReferences =
getEffectiveNodes( this.effSpecReferences, context, node.getModelObject().getIdentifier() );
final Map<String, Set<Node<Dependency>>> ancestorDependencies =
getEffectiveNodes( this.effDependencies, context, node.getModelObject().getIdentifier() );
final Map<String, Set<Node<Message>>> ancestorMessages =
getEffectiveNodes( this.effMessages, context, node.getModelObject().getIdentifier() );
final Map<String, Set<Node<Property>>> ancestorProperties =
getEffectiveNodes( this.effProperties, context, node.getModelObject().getIdentifier() );
final Map<String, Set<Node<ImplementationReference>>> ancestorImplementationReferences =
getEffectiveNodes( this.effImplReferences, context, node.getModelObject().getIdentifier() );
final Map<QName, Set<Node<Element>>> ancestorXmlElements =
getEffectiveNodes( this.effXmlElements, context, node.getModelObject().getIdentifier() );
final Map<QName, Set<Node<JAXBElement<?>>>> ancestorJaxbElements =
getEffectiveNodes( this.effJaxbElements, context, node.getModelObject().getIdentifier() );
if ( node.getDescendant() != null )
{
if ( ancestorSpecificationReferences != null )
{
inheritNodes( map( this.effSpecReferences, context ), ancestorSpecificationReferences,
node.getDescendant() );
}
if ( ancestorDependencies != null )
{
inheritNodes( map( this.effDependencies, context ), ancestorDependencies,
node.getDescendant() );
}
if ( ancestorProperties != null )
{
inheritNodes( map( this.effProperties, context ), ancestorProperties, node.getDescendant() );
}
if ( ancestorMessages != null )
{
inheritNodes( map( this.effMessages, context ), ancestorMessages, node.getDescendant() );
}
if ( ancestorImplementationReferences != null )
{
inheritNodes( map( this.effImplReferences, context ), ancestorImplementationReferences,
node.getDescendant() );
}
if ( ancestorXmlElements != null )
{
inheritNodes( map( this.effXmlElements, context ), ancestorXmlElements,
node.getDescendant() );
}
if ( ancestorJaxbElements != null )
{
inheritNodes( map( this.effJaxbElements, context ), ancestorJaxbElements,
node.getDescendant() );
}
collectEffectiveNodes( context, node.getDescendant() );
}
}
private void addClassDeclarationNodes( final String context, final Node<Implementation> node )
{
final Implementation classDeclaration = this.getClassDeclaration( node.getModelObject() );
if ( classDeclaration != null )
{
this.prepareContext( classDeclaration.getIdentifier() );
Map<String, Set<Node<Dependency>>> effectiveDependencies =
getEffectiveNodes( this.effDependencies, context, node.getModelObject().getIdentifier() );
Map<String, Set<Node<Message>>> effectiveMessages =
getEffectiveNodes( this.effMessages, context, node.getModelObject().getIdentifier() );
Map<String, Set<Node<Property>>> effectiveProperties =
getEffectiveNodes( this.effProperties, context, node.getModelObject().getIdentifier() );
Map<String, Set<Node<SpecificationReference>>> effectiveSpecificationReferences =
getEffectiveNodes( this.effSpecReferences, context, node.getModelObject().getIdentifier() );
Map<QName, Set<Node<Element>>> effectiveXmlElements =
getEffectiveNodes( this.effXmlElements, context, node.getModelObject().getIdentifier() );
Map<QName, Set<Node<JAXBElement<?>>>> effectiveJaxbElements =
getEffectiveNodes( this.effJaxbElements, context, node.getModelObject().getIdentifier() );
final Map<String, Set<Node<Dependency>>> declDependencies =
getEffectiveNodes( this.effDependencies, classDeclaration.getIdentifier(),
classDeclaration.getIdentifier() );
final Map<String, Set<Node<Message>>> declMessages =
getEffectiveNodes( this.effMessages, classDeclaration.getIdentifier(),
classDeclaration.getIdentifier() );
final Map<String, Set<Node<Property>>> declProperties =
getEffectiveNodes( this.effProperties, classDeclaration.getIdentifier(),
classDeclaration.getIdentifier() );
final Map<String, Set<Node<SpecificationReference>>> declSpecReferences =
getEffectiveNodes( this.effSpecReferences, classDeclaration.getIdentifier(),
classDeclaration.getIdentifier() );
final Map<QName, Set<Node<Element>>> declXmlElements =
getEffectiveNodes( this.effXmlElements, classDeclaration.getIdentifier(),
classDeclaration.getIdentifier() );
final Map<QName, Set<Node<JAXBElement<?>>>> declJaxbElements =
getEffectiveNodes( this.effJaxbElements, classDeclaration.getIdentifier(),
classDeclaration.getIdentifier() );
if ( declDependencies != null )
{
if ( effectiveDependencies == null )
{
effectiveDependencies = newMap();
map( this.effDependencies, context ).
put( node.getModelObject().getIdentifier(), effectiveDependencies );
}
for ( final Map.Entry<String, Set<Node<Dependency>>> e : declDependencies.entrySet() )
{
final Set<Node<Dependency>> set = newSet( e.getValue().size() );
for ( final Node<Dependency> n : e.getValue() )
{
final Node<Dependency> effNode = new Node<Dependency>(
node.getModelObject(), n.getSpecification(), classDeclaration, null, n.getModelObject(),
n.isFinal(), n.isOverride() );
effNode.getModifiablePath().addAll( n.getPath() );
set.add( effNode );
addNode( map( this.dependencies, context ), effNode, e.getKey() );
}
if ( effectiveDependencies.containsKey( e.getKey() ) )
{
for ( final Node<Dependency> effNode : effectiveDependencies.get( e.getKey() ) )
{
effNode.getModifiableOverriddenNodes().addAll( set );
}
}
else
{
effectiveDependencies.put( e.getKey(), set );
}
}
}
if ( declSpecReferences != null )
{
if ( effectiveSpecificationReferences == null )
{
effectiveSpecificationReferences = newMap();
map( this.effSpecReferences, context ).
put( node.getModelObject().getIdentifier(), effectiveSpecificationReferences );
}
for ( final Map.Entry<String, Set<Node<SpecificationReference>>> e : declSpecReferences.entrySet() )
{
final Set<Node<SpecificationReference>> set = newSet( e.getValue().size() );
for ( final Node<SpecificationReference> n : e.getValue() )
{
final Node<SpecificationReference> effNode = new Node<SpecificationReference>(
node.getModelObject(), n.getSpecification(), classDeclaration, null, n.getModelObject(),
n.isFinal(), n.isOverride() );
effNode.getModifiablePath().addAll( n.getPath() );
set.add( effNode );
addNode( map( this.specReferences, context ), effNode, e.getKey() );
}
if ( effectiveSpecificationReferences.containsKey( e.getKey() ) )
{
for ( final Node<SpecificationReference> effNode
: effectiveSpecificationReferences.get( e.getKey() ) )
{
effNode.getModifiableOverriddenNodes().addAll( set );
}
}
else
{
effectiveSpecificationReferences.put( e.getKey(), set );
}
}
}
if ( declMessages != null )
{
if ( effectiveMessages == null )
{
effectiveMessages = newMap();
map( this.effMessages, context ).
put( node.getModelObject().getIdentifier(), effectiveMessages );
}
for ( final Map.Entry<String, Set<Node<Message>>> e : declMessages.entrySet() )
{
final Set<Node<Message>> set = newSet( e.getValue().size() );
for ( final Node<Message> n : e.getValue() )
{
final Node<Message> effNode = new Node<Message>(
node.getModelObject(), n.getSpecification(), classDeclaration, null, n.getModelObject(),
n.isFinal(), n.isOverride() );
effNode.getModifiablePath().addAll( n.getPath() );
set.add( effNode );
addNode( map( this.messages, context ), effNode, e.getKey() );
}
if ( effectiveMessages.containsKey( e.getKey() ) )
{
for ( final Node<Message> effNode : effectiveMessages.get( e.getKey() ) )
{
effNode.getModifiableOverriddenNodes().addAll( set );
}
}
else
{
effectiveMessages.put( e.getKey(), set );
}
}
}
if ( declProperties != null )
{
if ( effectiveProperties == null )
{
effectiveProperties = newMap();
map( this.effProperties, context ).
put( node.getModelObject().getIdentifier(), effectiveProperties );
}
for ( final Map.Entry<String, Set<Node<Property>>> e : declProperties.entrySet() )
{
final Set<Node<Property>> set = newSet( e.getValue().size() );
for ( final Node<Property> n : e.getValue() )
{
final Node<Property> effNode = new Node<Property>(
node.getModelObject(), n.getSpecification(), classDeclaration, null, n.getModelObject(),
n.isFinal(), n.isOverride() );
effNode.getModifiablePath().addAll( n.getPath() );
set.add( effNode );
addNode( map( this.properties, context ), effNode, e.getKey() );
}
if ( effectiveProperties.containsKey( e.getKey() ) )
{
for ( final Node<Property> effNode : effectiveProperties.get( e.getKey() ) )
{
effNode.getModifiableOverriddenNodes().addAll( set );
}
}
else
{
effectiveProperties.put( e.getKey(), set );
}
}
}
if ( declXmlElements != null )
{
if ( effectiveXmlElements == null )
{
effectiveXmlElements = newMap();
map( this.effXmlElements, context ).
put( node.getModelObject().getIdentifier(), effectiveXmlElements );
}
for ( final Map.Entry<QName, Set<Node<Element>>> e : declXmlElements.entrySet() )
{
final Set<Node<Element>> set = newSet( e.getValue().size() );
for ( final Node<Element> n : e.getValue() )
{
final Node<Element> effNode = new Node<Element>(
node.getModelObject(), n.getSpecification(), classDeclaration, null, n.getModelObject(),
n.isFinal(), n.isOverride() );
effNode.getModifiablePath().addAll( n.getPath() );
set.add( effNode );
addNode( map( this.xmlElements, context ), effNode, e.getKey() );
}
if ( effectiveXmlElements.containsKey( e.getKey() ) )
{
for ( final Node<Element> effNode : effectiveXmlElements.get( e.getKey() ) )
{
effNode.getModifiableOverriddenNodes().addAll( set );
}
}
else
{
effectiveXmlElements.put( e.getKey(), set );
}
}
}
if ( declJaxbElements != null )
{
if ( effectiveJaxbElements == null )
{
effectiveJaxbElements = newMap();
map( this.effJaxbElements, context ).
put( node.getModelObject().getIdentifier(), effectiveJaxbElements );
}
for ( final Map.Entry<QName, Set<Node<JAXBElement<?>>>> e : declJaxbElements.entrySet() )
{
final Set<Node<JAXBElement<?>>> set = newSet( e.getValue().size() );
for ( final Node<JAXBElement<?>> n : e.getValue() )
{
final Node<JAXBElement<?>> effNode = new Node<JAXBElement<?>>(
node.getModelObject(), n.getSpecification(), classDeclaration, null, n.getModelObject(),
n.isFinal(), n.isOverride() );
effNode.getModifiablePath().addAll( n.getPath() );
set.add( effNode );
addNode( map( this.jaxbElements, context ), effNode, e.getKey() );
}
if ( effectiveJaxbElements.containsKey( e.getKey() ) )
{
for ( final Node<JAXBElement<?>> effNode : effectiveJaxbElements.get( e.getKey() ) )
{
effNode.getModifiableOverriddenNodes().addAll( set );
}
}
else
{
effectiveJaxbElements.put( e.getKey(), set );
}
}
}
}
}
private Implementation getClassDeclaration( final Implementation implementation )
{
Implementation declaration = null;
if ( implementation.getClazz() != null && !implementation.isClassDeclaration() )
{
find:
for ( int i = 0, s0 = this.modules.getModule().size(); i < s0; i++ )
{
final Module candidateModule = this.modules.getModule().get( i );
if ( candidateModule.getImplementations() != null )
{
for ( int j = 0, s1 = candidateModule.getImplementations().getImplementation().size(); j < s1; j++ )
{
final Implementation candidate =
candidateModule.getImplementations().getImplementation().get( j );
if ( candidate.isClassDeclaration()
&& candidate.getClazz().equals( implementation.getClazz() ) )
{
declaration = candidate;
break find;
}
}
}
}
}
return declaration;
}
private static <T, K> void addNode( final Map<K, Set<Node<T>>> map, final Node<T> node, final K key )
{
Set<Node<T>> set = map.get( key );
if ( set == null )
{
set = newSet();
map.put( key, set );
}
set.add( node );
}
private static <T, K> void overrideNodes( final Map<String, Map<K, Set<Node<T>>>> effective,
final Node<Implementation> implementation,
final Map<K, Set<Node<T>>> directNodes )
{
for ( final Map.Entry<K, Set<Node<T>>> e : directNodes.entrySet() )
{
final Set<Node<T>> effectiveNodes =
effectiveNodes( effective, implementation.getModelObject().getIdentifier(), e.getKey() );
final Set<Node<T>> overridingNodes = newSet();
for ( final Node<T> directNode : e.getValue() )
{
for ( final Iterator<Node<T>> it = effectiveNodes.iterator(); it.hasNext(); )
{
final Node<T> effectiveNode = it.next();
if ( isOverriding( effectiveNode, directNode ) )
{
it.remove();
if ( directNode != effectiveNode )
{
directNode.getModifiableOverriddenNodes().add( effectiveNode );
}
}
}
boolean overriddenByAncestor = false;
if ( directNode.getSpecification() != null )
{
for ( final Node<T> effectiveNode : effectiveNodes )
{
if ( effectiveNode.getSpecification() == null )
{
overriddenByAncestor = true;
effectiveNode.getModifiableOverriddenNodes().add( directNode );
}
}
}
if ( !overriddenByAncestor )
{
overridingNodes.add( directNode );
}
}
effectiveNodes.addAll( overridingNodes );
}
}
private static <K, V, T> Map<K, V> map( final Map<T, Map<K, V>> map, final T context )
{
Map<K, V> contextMap = map.get( context );
if ( contextMap == null )
{
contextMap = newMap();
map.put( context, contextMap );
}
return contextMap;
}
private static <K, V> Set<Node<V>> nodes( final Map<K, Set<Node<V>>> map, final K key )
{
Set<Node<V>> nodes = map.get( key );
if ( nodes == null )
{
nodes = newSet();
map.put( key, nodes );
}
return nodes;
}
private static <K, V> Set<Node<V>> effectiveNodes( final Map<String, Map<K, Set<Node<V>>>> map,
final String context, final K key )
{
return nodes( map( map, context ), key );
}
private static <T, K> void inheritNodes(
final Map<String, Map<K, Set<Node<T>>>> effective, final Map<K, Set<Node<T>>> ancestor,
final Node<Implementation> descendant )
{
for ( Map.Entry<K, Set<Node<T>>> e : ancestor.entrySet() )
{
for ( final Node<T> inherit : e.getValue() )
{
if ( isInheritableNode( inherit ) )
{
effectiveNodes( effective, descendant.getModelObject().getIdentifier(), e.getKey() ).add( inherit );
}
}
}
}
private static <T, K> Map<K, Set<Node<T>>> getDirectEffectiveNodes( final Map<K, Set<Node<T>>> map,
final String origin )
{
final Map<K, Set<Node<T>>> declarationMap = newMap( map.size() );
for ( final Map.Entry<K, Set<Node<T>>> e : map.entrySet() )
{
final Set<Node<T>> set = nodes( declarationMap, e.getKey() );
for ( final Node<T> n : e.getValue() )
{
if ( isDirectEffectiveNode( n, origin ) )
{
set.add( n );
}
}
for ( final Node<T> n : e.getValue() )
{
if ( isDirectSpecifiedNode( n, origin ) )
{
boolean add = true;
for ( final Node<T> override : set )
{
if ( override.getSpecification() == null )
{
override.getModifiableOverriddenNodes().add( n );
add = false;
}
}
if ( add )
{
set.add( n );
}
}
}
}
return declarationMap;
}
private static <T, K> Map<K, Set<Node<T>>> getEffectiveNodes(
final Map<String, Map<String, Map<K, Set<Node<T>>>>> effective, final String context,
final String implementation )
{
return map( effective, context ).get( implementation );
}
private static boolean isDirectNode( final Node<?> node, final String implementation )
{
return implementation.equals( node.getImplementation().getIdentifier() );
}
private static boolean isDirectEffectiveNode( final Node<?> node, final String implementation )
{
return isDirectNode( node, implementation ) && node.getClassDeclaration() == null
&& node.getSpecification() == null;
}
private static boolean isDirectSpecifiedNode( final Node<?> node, final String implementation )
{
return isDirectNode( node, implementation ) && node.getClassDeclaration() == null
&& node.getSpecification() != null;
}
private static boolean isOverriding( final Node<?> node, final Node<?> override )
{
if ( override.getSpecification() != null )
{
if ( node.getSpecification() == null )
{
return false;
}
else if ( !override.getSpecification().getIdentifier().equals( node.getSpecification().getIdentifier() ) )
{
return false;
}
}
return true;
}
private static boolean isInheritableNode( final Node<?> node )
{
return node.getClassDeclaration() == null;
}
private static <K, V> Map<K, V> newMap()
{
return new HashMap<K, V>();
}
private static <K, V> Map<K, V> newMap( final int initialCapacity )
{
return new HashMap<K, V>( initialCapacity );
}
private static <T> Set<T> newSet()
{
return new HashSet<T>();
}
private static <T> Set<T> newSet( final int initialCapacity )
{
return new HashSet<T>( initialCapacity );
}
private static <T> Set<T> newSet( final Collection<? extends T> col )
{
return new HashSet<T>( col );
}
private static <T> Set<T> unmodifiableSet( final Set<T> set )
{
return set != null ? Collections.unmodifiableSet( set ) : Collections.<T>emptySet();
}
private static QName getXmlElementName( final Element element )
{
if ( element.getNamespaceURI() != null )
{
return new QName( element.getNamespaceURI(), element.getLocalName() );
}
else
{
return new QName( element.getLocalName() );
}
}
}