blob: b0e3161c08617f5e8457c60bee745ef0882fd87c [file] [log] [blame]
/**
* Copyright (c) 2002-2006 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* IBM - Initial API and implementation
*/
package org.eclipse.xsd.impl;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import org.w3c.dom.Element;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.emf.ecore.util.EObjectEList;
import org.eclipse.emf.ecore.xml.type.util.XMLTypeUtil;
import org.eclipse.xsd.XSDComplexTypeDefinition;
import org.eclipse.xsd.XSDConcreteComponent;
import org.eclipse.xsd.XSDNamedComponent;
import org.eclipse.xsd.XSDPackage;
import org.eclipse.xsd.XSDPlugin;
import org.eclipse.xsd.XSDSchema;
import org.eclipse.xsd.XSDSimpleTypeDefinition;
import org.eclipse.xsd.XSDVariety;
import org.eclipse.xsd.util.XSDConstants;
/**
* <!-- begin-user-doc -->
* An implementation of the model object '<em><b>Named Component</b></em>'.
* <!-- end-user-doc -->
* <p>
* The following features are implemented:
* </p>
* <ul>
* <li>{@link org.eclipse.xsd.impl.XSDNamedComponentImpl#getName <em>Name</em>}</li>
* <li>{@link org.eclipse.xsd.impl.XSDNamedComponentImpl#getTargetNamespace <em>Target Namespace</em>}</li>
* <li>{@link org.eclipse.xsd.impl.XSDNamedComponentImpl#getAliasName <em>Alias Name</em>}</li>
* <li>{@link org.eclipse.xsd.impl.XSDNamedComponentImpl#getURI <em>URI</em>}</li>
* <li>{@link org.eclipse.xsd.impl.XSDNamedComponentImpl#getAliasURI <em>Alias URI</em>}</li>
* <li>{@link org.eclipse.xsd.impl.XSDNamedComponentImpl#getQName <em>QName</em>}</li>
* </ul>
*
* @generated
*/
public abstract class XSDNamedComponentImpl
extends XSDComponentImpl
implements XSDNamedComponent
{
/**
* The default value of the '{@link #getName() <em>Name</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getName()
* @generated
* @ordered
*/
protected static final String NAME_EDEFAULT = null;
/**
* The cached value of the '{@link #getName() <em>Name</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getName()
* @generated
* @ordered
*/
protected String name = NAME_EDEFAULT;
/**
* The default value of the '{@link #getTargetNamespace() <em>Target Namespace</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getTargetNamespace()
* @generated
* @ordered
*/
protected static final String TARGET_NAMESPACE_EDEFAULT = null;
/**
* The cached value of the '{@link #getTargetNamespace() <em>Target Namespace</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getTargetNamespace()
* @generated
* @ordered
*/
protected String targetNamespace = TARGET_NAMESPACE_EDEFAULT;
/**
* The default value of the '{@link #getAliasName() <em>Alias Name</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getAliasName()
* @generated
* @ordered
*/
protected static final String ALIAS_NAME_EDEFAULT = null;
/**
* The default value of the '{@link #getURI() <em>URI</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getURI()
* @generated
* @ordered
*/
protected static final String URI_EDEFAULT = null;
/**
* The default value of the '{@link #getAliasURI() <em>Alias URI</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getAliasURI()
* @generated
* @ordered
*/
protected static final String ALIAS_URI_EDEFAULT = null;
/**
* The default value of the '{@link #getQName() <em>QName</em>}' attribute.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @see #getQName()
* @generated
* @ordered
*/
protected static final String QNAME_EDEFAULT = null;
public static List<XSDNamedComponent> sortNamedComponents(Collection<XSDNamedComponent> xsdNamedComponents)
{
XSDNamedComponent [] objects = new XSDNamedComponent[xsdNamedComponents.size()];
xsdNamedComponents.toArray(objects);
Arrays.sort(objects, Comparator.getInstance());
return Arrays.asList(objects);
}
public static <T extends XSDNamedComponent> void addToSortedList(List<T> xsdNamedComponents, T xsdNamedComponent)
{
int index = Collections.binarySearch(xsdNamedComponents, xsdNamedComponent, Comparator.getInstance());
if (index < 0)
{
xsdNamedComponents.add(-(index + 1), xsdNamedComponent);
}
else if (xsdNamedComponents.get(index) != xsdNamedComponent)
{
xsdNamedComponents.add(index, xsdNamedComponent);
}
}
public static class XSDNamedComponentList<E extends Object & XSDNamedComponent> extends EObjectEList<E>
{
private static final long serialVersionUID = 1L;
protected Map<String, XSDNamedComponent> map;
protected XSDSchemaImpl xsdSchema;
public XSDNamedComponentList(Class<?> dataClass, XSDSchemaImpl owner, int featureID)
{
super(dataClass, owner, featureID);
xsdSchema = owner;
}
protected boolean isFromThisNamespace(XSDNamedComponent xsdNamedComponent)
{
String targetNamespace = xsdNamedComponent.getTargetNamespace();
return targetNamespace == null ? xsdSchema.getTargetNamespace() == null : targetNamespace.equals(xsdSchema.getTargetNamespace());
}
@Override
protected void didAdd(int index, Object newObject)
{
XSDNamedComponent xsdNamedComponent = (XSDNamedComponent)newObject;
if (isFromThisNamespace(xsdNamedComponent))
{
if (map == null)
{
map = new HashMap<String, XSDNamedComponent>();
}
map.put(xsdNamedComponent.getName(), xsdNamedComponent);
}
}
@Override
protected void didClear(int size, Object[] oldObjects)
{
map = null;
}
@Override
protected void didRemove(int index, Object oldObject)
{
if (map != null)
{
XSDNamedComponent xsdNamedComponent = (XSDNamedComponent)oldObject;
if (isFromThisNamespace(xsdNamedComponent))
{
map.values().remove(xsdNamedComponent);
}
}
}
@Override
protected void didSet(int index, Object newObject, Object oldObject)
{
didRemove(index, oldObject);
didAdd(index, newObject);
}
public XSDNamedComponent get(String targetNamespace, String localName)
{
// If the list is empty, there can't be a match.
//
if (isEmpty())
{
return null;
}
// If we are looking up a name in the owning schema's namespace...
//
if (targetNamespace == null ? xsdSchema.getTargetNamespace() == null : targetNamespace.equals(xsdSchema.getTargetNamespace()))
{
// Look up the result in the map if there is one.
//
if (map == null)
{
return null;
}
XSDNamedComponent result = map.get(localName);
return result;
}
int index =
Collections.binarySearch(this, new String [] { targetNamespace, localName}, StringPairComparator.getInstance());
if (index < 0)
{
return null;
}
else
{
return this.get(index);
}
}
}
public static XSDNamedComponent findInSortedList(List<? extends XSDNamedComponent> xsdNamedComponents, String targetNamespace, String localName)
{
if (xsdNamedComponents instanceof XSDNamedComponentList<?>)
{
return ((XSDNamedComponentList<? extends XSDNamedComponent>)xsdNamedComponents).get(targetNamespace, localName);
}
int index =
Collections.binarySearch(xsdNamedComponents, new String [] { targetNamespace, localName}, StringPairComparator.getInstance());
if (index < 0)
{
return null;
}
else
{
return xsdNamedComponents.get(index);
}
}
public static <T extends XSDNamedComponent> void mergeToSortedList(List<T> xsdNamedComponentsTarget, List<T> xsdNamedComponentsSource)
{
Iterator<T> sourceComponents = xsdNamedComponentsSource.iterator();
if (sourceComponents.hasNext())
{
Comparator comparator = Comparator.getInstance();
T sourceComponent = sourceComponents.next();
for (ListIterator<T> targetComponents = xsdNamedComponentsTarget.listIterator(); targetComponents.hasNext(); )
{
T targetComponent = targetComponents.next();
if (targetComponent == sourceComponent)
{
// Do nothing.
}
else if (comparator.compare(sourceComponent, targetComponent) < 0)
{
targetComponents.previous();
targetComponents.add(sourceComponent);
}
else
{
continue;
}
if (sourceComponents.hasNext())
{
sourceComponent = sourceComponents.next();
}
else
{
sourceComponent = null;
break;
}
}
if (sourceComponent != null)
{
xsdNamedComponentsTarget.add(sourceComponent);
while (sourceComponents.hasNext())
{
sourceComponent = sourceComponents.next();
xsdNamedComponentsTarget.add(sourceComponent);
}
}
}
}
public static class Comparator implements java.util.Comparator<XSDNamedComponent>
{
protected static Comparator instance = new Comparator();
public static Comparator getInstance()
{
if (instance == null)
{
instance = new Comparator();
}
return instance;
}
protected XSDPlugin.StringComparator collator = XSDPlugin.INSTANCE.getComparator();
public Comparator()
{
super();
}
@Override
public boolean equals(Object that)
{
return this == that;
}
public int compare(XSDNamedComponent xsdNamedComponent1, XSDNamedComponent xsdNamedComponent2)
{
String name1 = xsdNamedComponent1.getName();
String name2 = xsdNamedComponent2.getName();
if (name1 == null && name2 == null)
{
return xsdNamedComponent1.hashCode() - xsdNamedComponent2.hashCode();
}
else if (name1 == null)
{
return 1;
}
else if (name2 == null)
{
return -1;
}
else
{
int result = collator.compare(name1, name2);
if (result == 0)
{
String namespace1 = xsdNamedComponent1.getTargetNamespace();
String namespace2 = xsdNamedComponent2.getTargetNamespace();
if (namespace1 == null && namespace2 == null)
{
return xsdNamedComponent1.hashCode() - xsdNamedComponent2.hashCode();
}
else if (namespace1 == null)
{
return 1;
}
else if (namespace2 == null)
{
return -1;
}
else
{
result = collator.compare(namespace1, namespace2);
if (result == 0)
{
result = xsdNamedComponent1.hashCode() - xsdNamedComponent2.hashCode();
}
return result;
}
}
else
{
return result;
}
}
}
}
public static class StringPairComparator implements java.util.Comparator<Object>
{
protected static StringPairComparator instance = new StringPairComparator();
public static StringPairComparator getInstance()
{
if (instance == null)
{
instance = new StringPairComparator();
}
return instance;
}
protected XSDPlugin.StringComparator collator = XSDPlugin.INSTANCE.getComparator();
public StringPairComparator()
{
super();
}
@Override
public boolean equals(Object that)
{
return this == that;
}
public int compare(Object o1, Object o2)
{
XSDNamedComponent xsdNamedComponent = (XSDNamedComponent)o1;
String [] strings = (String [])o2;
String name1 = xsdNamedComponent.getName();
String name2 = strings[1];
if (name1 == null && name2 == null)
{
return 0;
}
else if (name1 == null)
{
return 1;
}
else if (name2 == null)
{
return -1;
}
else
{
int result = collator.compare(name1, name2);
if (result == 0)
{
String namespace1 = xsdNamedComponent.getTargetNamespace();
String namespace2 = strings[0];
if (namespace1 == null && namespace2 == null)
{
return 0;
}
else if (namespace1 == null)
{
return 1;
}
else if (namespace2 == null)
{
return -1;
}
else
{
return collator.compare(namespace1, namespace2);
}
}
else
{
return result;
}
}
}
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected XSDNamedComponentImpl()
{
super();
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
protected EClass eStaticClass()
{
return XSDPackage.Literals.XSD_NAMED_COMPONENT;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public String getName()
{
return name;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setName(String newName)
{
String oldName = name;
name = newName;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, XSDPackage.XSD_NAMED_COMPONENT__NAME, oldName, name));
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public String getTargetNamespace()
{
return targetNamespace;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public void setTargetNamespace(String newTargetNamespace)
{
String oldTargetNamespace = targetNamespace;
targetNamespace = newTargetNamespace;
if (eNotificationRequired())
eNotify(new ENotificationImpl(this, Notification.SET, XSDPackage.XSD_NAMED_COMPONENT__TARGET_NAMESPACE, oldTargetNamespace, targetNamespace));
}
@Override
protected String getURIReferenceLabel()
{
return getName();
}
public String getAliasName()
{
String result = getName();
if (result == null)
{
XSDConcreteComponent container = getContainer();
if (container instanceof XSDNamedComponent)
{
XSDNamedComponent xsdNamedComponent = (XSDNamedComponent)container;
String baseName = xsdNamedComponent.getAliasName();
if (container instanceof XSDSimpleTypeDefinition)
{
XSDSimpleTypeDefinition xsdSimpleTypeDefinition = (XSDSimpleTypeDefinition)container;
switch (xsdSimpleTypeDefinition.getVariety().getValue())
{
case XSDVariety.ATOMIC:
{
result = baseName + "_._base";
break;
}
case XSDVariety.LIST:
{
result = baseName + (XSDConstants.isURType(xsdSimpleTypeDefinition.getBaseTypeDefinition()) ? "_._item" : "_._base");
break;
}
case XSDVariety.UNION:
{
result =
baseName +
(XSDConstants.isURType(xsdSimpleTypeDefinition.getBaseTypeDefinition()) ?
"_._member" + "_._" + xsdSimpleTypeDefinition.getMemberTypeDefinitions().indexOf((XSDSimpleTypeDefinition)this) :
"_._base");
break;
}
}
}
else if (container instanceof XSDComplexTypeDefinition)
{
result = baseName + "_._base";
}
else
{
result = baseName + "_._type";
}
}
}
return result;
}
public String getURI()
{
String theTargetNamespace = getTargetNamespace();
if (theTargetNamespace == null)
{
theTargetNamespace = "";
}
String theName = getName();
if (theName == null)
{
theName = getAliasName();
}
return theTargetNamespace + "#" + theName;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated modifiable
*/
public String getAliasURI()
{
XSDSchema xsdSchema = getSchema();
String theTargetNamespace = xsdSchema == null ? getTargetNamespace() : xsdSchema.getTargetNamespace();
if (theTargetNamespace == null)
{
theTargetNamespace = "";
}
String theName = getAliasName();
if (theName == null)
{
theName = getAliasName();
}
return theTargetNamespace + "#" + theName;
}
public String getQName(XSDConcreteComponent relativeToComponent)
{
String theName = getName();
if (theName != null && relativeToComponent != null)
{
Element theElement = relativeToComponent.getElement();
if (theElement != null)
{
String qualifier = XSDConstants.lookupQualifier(theElement, getTargetNamespace());
if (qualifier != null && qualifier.length() != 0)
{
return qualifier + ":" + theName;
}
}
}
return theName;
}
public String getQName()
{
return getQName(this);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public Object eGet(int featureID, boolean resolve, boolean coreType)
{
switch (featureID)
{
case XSDPackage.XSD_NAMED_COMPONENT__NAME:
return getName();
case XSDPackage.XSD_NAMED_COMPONENT__TARGET_NAMESPACE:
return getTargetNamespace();
case XSDPackage.XSD_NAMED_COMPONENT__ALIAS_NAME:
return getAliasName();
case XSDPackage.XSD_NAMED_COMPONENT__URI:
return getURI();
case XSDPackage.XSD_NAMED_COMPONENT__ALIAS_URI:
return getAliasURI();
case XSDPackage.XSD_NAMED_COMPONENT__QNAME:
return getQName();
}
return super.eGet(featureID, resolve, coreType);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public void eSet(int featureID, Object newValue)
{
switch (featureID)
{
case XSDPackage.XSD_NAMED_COMPONENT__NAME:
setName((String)newValue);
return;
case XSDPackage.XSD_NAMED_COMPONENT__TARGET_NAMESPACE:
setTargetNamespace((String)newValue);
return;
}
super.eSet(featureID, newValue);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public void eUnset(int featureID)
{
switch (featureID)
{
case XSDPackage.XSD_NAMED_COMPONENT__NAME:
setName(NAME_EDEFAULT);
return;
case XSDPackage.XSD_NAMED_COMPONENT__TARGET_NAMESPACE:
setTargetNamespace(TARGET_NAMESPACE_EDEFAULT);
return;
}
super.eUnset(featureID);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public boolean eIsSet(int featureID)
{
switch (featureID)
{
case XSDPackage.XSD_NAMED_COMPONENT__NAME:
return NAME_EDEFAULT == null ? name != null : !NAME_EDEFAULT.equals(name);
case XSDPackage.XSD_NAMED_COMPONENT__TARGET_NAMESPACE:
return TARGET_NAMESPACE_EDEFAULT == null ? targetNamespace != null : !TARGET_NAMESPACE_EDEFAULT.equals(targetNamespace);
case XSDPackage.XSD_NAMED_COMPONENT__ALIAS_NAME:
return ALIAS_NAME_EDEFAULT == null ? getAliasName() != null : !ALIAS_NAME_EDEFAULT.equals(getAliasName());
case XSDPackage.XSD_NAMED_COMPONENT__URI:
return URI_EDEFAULT == null ? getURI() != null : !URI_EDEFAULT.equals(getURI());
case XSDPackage.XSD_NAMED_COMPONENT__ALIAS_URI:
return ALIAS_URI_EDEFAULT == null ? getAliasURI() != null : !ALIAS_URI_EDEFAULT.equals(getAliasURI());
case XSDPackage.XSD_NAMED_COMPONENT__QNAME:
return QNAME_EDEFAULT == null ? getQName() != null : !QNAME_EDEFAULT.equals(getQName());
}
return super.eIsSet(featureID);
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public String toString()
{
if (eIsProxy()) return super.toString();
StringBuilder result = new StringBuilder(super.toString());
result.append(" (name: ");
result.append(name);
result.append(", targetNamespace: ");
result.append(targetNamespace);
result.append(')');
return result.toString();
}
@Override
protected void patch()
{
patchTargetNamespaceAttribute();
super.patch();
}
protected void patchTargetNamespaceAttribute()
{
XSDSchema xsdSchema = getSchema();
if (xsdSchema != null)
{
patchTargetNamespaceAttribute(xsdSchema);
}
}
protected void patchTargetNamespaceAttribute(XSDSchema xsdSchema)
{
String newTargetNamespace = xsdSchema.getTargetNamespace();
if (newTargetNamespace == null ? getTargetNamespace() != null : !newTargetNamespace.equals(getTargetNamespace()))
{
setTargetNamespace(newTargetNamespace);
}
}
@Override
protected void adoptBy(XSDSchema xsdSchema)
{
patchTargetNamespaceAttribute(xsdSchema);
super.adoptBy(xsdSchema);
}
@Override
protected void reconcileAttributes(Element changedElement)
{
super.reconcileAttributes(changedElement);
if (changedElement == getElement())
{
reconcileNameAttribute();
}
}
protected void reconcileNameAttribute()
{
Element theElement = getElement();
if (theElement.hasAttributeNS(null, XSDConstants.NAME_ATTRIBUTE))
{
String newName = XMLTypeUtil.normalize(theElement.getAttributeNS(null, XSDConstants.NAME_ATTRIBUTE), true);
if (!newName.equals(getName()))
{
setName(newName);
}
}
else if (getName() != null)
{
setName(null);
}
}
@Override
protected void changeAttribute(EAttribute eAttribute)
{
super.changeAttribute(eAttribute);
if (!isNamedComponentReference())
{
if (eAttribute == null || eAttribute == XSDPackage.Literals.XSD_NAMED_COMPONENT__NAME)
{
if (eAttribute != null)
{
XSDSchemaImpl xsdSchema = (XSDSchemaImpl)getSchema();
if (xsdSchema != null)
{
xsdSchema.updateSortedList(this);
}
}
Element theElement = getElement();
if (theElement != null)
{
niceSetAttribute(theElement, XSDConstants.NAME_ATTRIBUTE, getName());
}
if (eAttribute != null)
{
traverseToRootForPatching();
}
}
}
}
public boolean isNamedComponentReference()
{
return false;
}
public XSDNamedComponent getResolvedNamedComponent()
{
return this;
}
public boolean hasSameNameAndTargetNamespace(XSDNamedComponent xsdNamedComponent)
{
return
(getTargetNamespace() == null ?
xsdNamedComponent.getTargetNamespace() == null :
getTargetNamespace().equals(xsdNamedComponent.getTargetNamespace())) &&
(getName() == null ?
xsdNamedComponent.getName() == null :
getName().equals(xsdNamedComponent.getName()));
}
public boolean hasNameAndTargetNamespace(String name, String targetNamespace)
{
return
(targetNamespace == null ?
getTargetNamespace() == null :
targetNamespace.equals(getTargetNamespace())) &&
(name == null ?
getName() == null :
name.equals(getName()));
}
public boolean hasURI(String uri)
{
String theTargetNamespace = getTargetNamespace();
if (theTargetNamespace == null)
{
theTargetNamespace = "";
}
String theName = getName();
if (theName == null)
{
theName = "";
}
return
uri.startsWith(theTargetNamespace) &&
uri.endsWith(theName) &&
uri.length() == theName.length() + theTargetNamespace.length() + 1;
}
}