/* * JBoss, Home of Professional Open Source. * * See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing. * * See the AUTHORS.txt file distributed with this work for a full listing of individual contributors. */ package org.teiid.designer.metamodels.xsd.aspects.sql; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.InternalEObject; import org.eclipse.emf.ecore.impl.ENotificationImpl; import org.eclipse.emf.ecore.impl.EObjectImpl; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.xsd.XSDAnnotation; import org.eclipse.xsd.XSDPackage; import org.eclipse.xsd.XSDSchema; import org.eclipse.xsd.XSDSimpleTypeDefinition; import org.eclipse.xsd.XSDVariety; import org.eclipse.xsd.impl.XSDSchemaImpl; import org.eclipse.xsd.util.XSDConstants; import org.teiid.core.designer.id.IDGenerator; import org.teiid.core.designer.id.InvalidIDException; import org.teiid.core.designer.id.UUID; import org.teiid.core.designer.util.CoreArgCheck; import org.teiid.core.designer.util.CoreStringUtil; import org.teiid.designer.core.ModelerCore; import org.teiid.designer.core.index.IndexConstants; import org.teiid.designer.core.metamodel.aspect.AbstractMetamodelAspect; import org.teiid.designer.core.metamodel.aspect.MetamodelEntity; import org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect; import org.teiid.designer.core.types.DatatypeConstants; import org.teiid.designer.core.types.EnterpriseDatatypeInfo; import org.teiid.designer.metadata.runtime.MetadataConstants; import org.teiid.designer.metamodels.xsd.XsdConstants; import org.teiid.designer.metamodels.xsd.XsdPlugin; import org.teiid.designer.metamodels.xsd.XsdUtil; import org.teiid.designer.type.IDataTypeManagerService; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; /** * XsdSimpleTypeDefinitionAspect * * @since 8.0 */ public class XsdSimpleTypeDefinitionAspect extends AbstractMetamodelAspect implements SqlDatatypeAspect { public static final String ASPECT_ID = ModelerCore.EXTENSION_POINT.SQL_ASPECT.ID; public static final URI BUILTIN_DATATYPES_URI = URI.createURI(DatatypeConstants.BUILTIN_DATATYPES_URI); public static final String UUID_ATTRIBUTE_NAME = "UUID"; //$NON-NLS-1$ public static final String RUNTIME_TYPE_ATTRIBUTE_NAME = "runtimeDataType"; //$NON-NLS-1$ public static final String RUNTIME_TYPE_FIXED_ATTRIBUTE_NAME = "runtimeDataTypeFixed"; //$NON-NLS-1$ // platform:/plugin/org.eclipse.xsd_1.1.1/cache/www.w3.org/2001/MagicXMLSchema.xsd#//anySimpleType;XSDSimpleTypeDefinition=1 protected static final String ANY_SIMPLE_TYPE_URI_STRING = ModelerCore.XML_MAGIC_SCHEMA_ECLIPSE_PLATFORM_URI + "#//anySimpleType;XSDSimpleTypeDefinition=1"; //$NON-NLS-1$ protected static final URI ANY_SIMPLE_TYPE_URI = URI.createURI(ANY_SIMPLE_TYPE_URI_STRING); // Map, keyed on datatype name, of built-in datatypes as defined in the modeler.sdt plugin. private Map mmDatatypeMap; // References to the ur-types private EObject anySimpleType; public XsdSimpleTypeDefinitionAspect( MetamodelEntity entity ) { super.setMetamodelEntity(entity); super.setID(ASPECT_ID); init(); } /** * Load a map of Teiid Designer built-in datatype instances to use when retrieving UUID or runtime type information. Since * there is only one XsdSimpleTypeDefinitionAspect ever created the overhead of creating the map is acceptable. */ private void init() { this.mmDatatypeMap = new HashMap(); this.initializeMmDatatypeMap(); } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlAspect#getName(org.eclipse.emf.ecore.EObject) */ @Override public String getName( EObject eObject ) { CoreArgCheck.isInstanceOf(XSDSimpleTypeDefinition.class, eObject); XSDSimpleTypeDefinition entity = (XSDSimpleTypeDefinition)eObject; return entity.getName(); } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlAspect#getNameInSource(org.eclipse.emf.ecore.EObject) */ @Override public String getNameInSource( EObject eObject ) { CoreArgCheck.isInstanceOf(XSDSimpleTypeDefinition.class, eObject); XSDSimpleTypeDefinition entity = (XSDSimpleTypeDefinition)eObject; return entity.getName(); } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlAspect#getObjectID(org.eclipse.emf.ecore.EObject) */ @Override public Object getObjectID( EObject eObject ) { CoreArgCheck.isInstanceOf(XSDSimpleTypeDefinition.class, eObject); // If the datatype is a built-in datatype then use the Teiid Designer // instance since the instance found in the org.eclipse.xsd plugin // does not have UUID information. If the datatype is not a // built-in datatype then the original EObject reference is used. EObject type = this.getMmType(eObject); XSDSimpleTypeDefinition entity = (XSDSimpleTypeDefinition)type; XsdUtil.checkForEnterpriseConversion(entity); String uuidString = null; if (isEnterpriseDataType(entity)) { uuidString = getEnterpriseAttributeValue(entity, UUID_ATTRIBUTE_NAME); } if (!CoreStringUtil.isEmpty(uuidString)) { try { return IDGenerator.getInstance().stringToObject(uuidString, UUID.PROTOCOL); } catch (InvalidIDException e) { // Log error and then proceed by trying to get the UUID in other ways final String msg = XsdPlugin.Util.getString("XsdSimpleTypeDefinitionAspect.error_parsing_objectid", uuidString); //$NON-NLS-1$ XsdPlugin.Util.log(IStatus.ERROR, e, msg); } } return super.getObjectID(eObject); } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlAspect#getParentObjectID(org.eclipse.emf.ecore.EObject) */ @Override public Object getParentObjectID( EObject eObject ) { return null; } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlAspect#getPath(org.eclipse.emf.ecore.EObject) */ @Override public IPath getPath( final EObject eObject ) { return null; } /** * @see org.teiid.designer.core.metamodel.aspect.AbstractMetamodelAspect#getFullName(org.eclipse.emf.ecore.EObject) */ @Override public String getFullName( EObject eObject ) { CoreArgCheck.isInstanceOf(XSDSimpleTypeDefinition.class, eObject); XSDSimpleTypeDefinition entity = (XSDSimpleTypeDefinition)eObject; return this.getURI(entity); } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlAspect#isRecordType(char) */ @Override public boolean isRecordType( char recordType ) { return (recordType == IndexConstants.RECORD_TYPE.DATATYPE); } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlAspect#isQueryable(org.eclipse.emf.ecore.EObject) */ @Override public boolean isQueryable( final EObject eObject ) { // If the EObject is a simple datatype but it is not a global datatype then return false if ((eObject instanceof XSDSimpleTypeDefinition) && !(eObject.eContainer() instanceof XSDSchema)) { return false; } return true; } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect#getLength(org.eclipse.emf.ecore.EObject) */ @Override public int getLength( EObject eObject ) { return 0; } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect#getPrecisionLength(org.eclipse.emf.ecore.EObject) */ @Override public int getPrecisionLength( EObject eObject ) { return 0; } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect#getRadix(org.eclipse.emf.ecore.EObject) */ @Override public int getRadix( EObject eObject ) { return 0; } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect#getScale(org.eclipse.emf.ecore.EObject) */ @Override public int getScale( EObject eObject ) { return 0; } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect#isAutoIncrement(org.eclipse.emf.ecore.EObject) */ @Override public boolean isAutoIncrement( EObject eObject ) { return false; } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect#isCaseSensitive(org.eclipse.emf.ecore.EObject) */ @Override public boolean isCaseSensitive( EObject eObject ) { return false; } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect#isSigned(org.eclipse.emf.ecore.EObject) */ @Override public boolean isSigned( EObject eObject ) { return false; } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect#getType(org.eclipse.emf.ecore.EObject) */ @Override public short getType( EObject eObject ) { return MetadataConstants.DATATYPE_TYPES.USER_DEFINED; } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect#getSearchType(org.eclipse.emf.ecore.EObject) */ @Override public short getSearchType( EObject eObject ) { return MetadataConstants.SEARCH_TYPES.SEARCHABLE; } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect#getNullType(org.eclipse.emf.ecore.EObject) */ @Override public short getNullType( EObject eObject ) { return MetadataConstants.NULL_TYPES.NOT_NULL; } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect#getUuidString(org.eclipse.emf.ecore.EObject) */ @Override public String getUuidString( EObject eObject ) { CoreArgCheck.isInstanceOf(XSDSimpleTypeDefinition.class, eObject); // If the datatype is a built-in datatype then use the Teiid Designer // instance since the instance found in the org.eclipse.xsd plugin // does not have UUID information. If the datatype is not a // built-in datatype then the original EObject reference is used. EObject type = this.getMmType(eObject); XSDSimpleTypeDefinition entity = (XSDSimpleTypeDefinition)type; XsdUtil.checkForEnterpriseConversion(entity); String uuid = null; if (isEnterpriseDataType(entity)) { uuid = getEnterpriseAttributeValue(entity, UUID_ATTRIBUTE_NAME); } return uuid; } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect#getJavaClassName(org.eclipse.emf.ecore.EObject) */ @Override public String getJavaClassName( EObject eObject ) { CoreArgCheck.isInstanceOf(XSDSimpleTypeDefinition.class, eObject); XSDSimpleTypeDefinition entity = (XSDSimpleTypeDefinition)eObject; // Retrieve the runtime type name from the appInfo String runtimeTypeName = this.getRuntimeTypeName(entity); if (runtimeTypeName != null) { IDataTypeManagerService service = ModelerCore.getTeiidDataTypeManagerService(); Class<?> javaClassName = service.getDataTypeClass(runtimeTypeName); if (javaClassName != null) { return javaClassName.getName(); } } // Return Object as the default return Object.class.getName(); } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect#getRuntimeTypeName(org.eclipse.emf.ecore.EObject) */ @Override public String getRuntimeTypeName( EObject eObject ) { CoreArgCheck.isInstanceOf(XSDSimpleTypeDefinition.class, eObject); // If the datatype is a ur-type return a predefined runtime type if (this.isURType(eObject)) { return DatatypeConstants.RuntimeTypeNames.OBJECT; } // If the datatype is a built-in datatype then use the Teiid Designer // instance since the instance found in the org.eclipse.xsd plugin // does not have runtime type information. If the datatype is not a // built-in datatype then the original EObject reference is used. EObject type = this.getMmType(eObject); XSDSimpleTypeDefinition entity = (XSDSimpleTypeDefinition)type; XsdUtil.checkForEnterpriseConversion(entity); String runtimeType = null; if (isEnterpriseDataType(entity)) { runtimeType = getEnterpriseAttributeValue(entity, RUNTIME_TYPE_ATTRIBUTE_NAME); } if (runtimeType == null || runtimeType.length() == 0) { // Retrieve the runtime type from the basetype ... entity = (XSDSimpleTypeDefinition)getBasetype(eObject); runtimeType = (entity == null) ? DatatypeConstants.RuntimeTypeNames.OBJECT : getRuntimeTypeName(entity); } return runtimeType; } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect#getRuntimeTypeFixed(org.eclipse.emf.ecore.EObject) */ @Override public Boolean getRuntimeTypeFixed( EObject eObject ) { CoreArgCheck.isInstanceOf(XSDSimpleTypeDefinition.class, eObject); Boolean fixed = Boolean.FALSE; // If the datatype is a ur-type return a predefined runtime type if (!this.isURType(eObject)) { // If the datatype is a built-in datatype then use the Teiid Designer // instance since the instance found in the org.eclipse.xsd plugin // does not have runtime type information. If the datatype is not a // built-in datatype then the original EObject reference is used. EObject type = this.getMmType(eObject); XSDSimpleTypeDefinition entity = (XSDSimpleTypeDefinition)type; XsdUtil.checkForEnterpriseConversion(entity); String runtimeTypeFixedValue = null; if (isEnterpriseDataType(entity)) { runtimeTypeFixedValue = getEnterpriseAttributeValue(entity, RUNTIME_TYPE_ATTRIBUTE_NAME); } if (runtimeTypeFixedValue == null) { // Retrieve the runtime type from the basetype ... entity = (XSDSimpleTypeDefinition)getBasetype(eObject); if (entity != null) { fixed = getRuntimeTypeFixed(entity); } } } return fixed; } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect#getDatatypeID(org.eclipse.emf.ecore.EObject) */ @Override public String getDatatypeID( EObject eObject ) { CoreArgCheck.isInstanceOf(XSDSimpleTypeDefinition.class, eObject); XSDSimpleTypeDefinition entity = (XSDSimpleTypeDefinition)eObject; return this.getURI(entity); } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect#getBasetypeID(org.eclipse.emf.ecore.EObject) */ @Override public String getBasetypeID( EObject eObject ) { CoreArgCheck.isInstanceOf(XSDSimpleTypeDefinition.class, eObject); XSDSimpleTypeDefinition basetype = (XSDSimpleTypeDefinition)getBasetype(eObject); if (basetype != null) { return this.getURI(basetype); } return null; } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect#getBasetype(org.eclipse.emf.ecore.EObject) */ @Override public Object getBasetype( EObject eObject ) { CoreArgCheck.isInstanceOf(XSDSimpleTypeDefinition.class, eObject); XSDSimpleTypeDefinition type = (XSDSimpleTypeDefinition)eObject; XSDSimpleTypeDefinition basetype = null; // If the datatype is of a list variety then return the itemtype as the basetype final XSDVariety variety = type.getVariety(); if (variety == XSDVariety.LIST_LITERAL) { basetype = type.getItemTypeDefinition(); // If the datatype is of a union variety then return "anySimpleType" as the basetype } else if (variety == XSDVariety.UNION_LITERAL) { basetype = (XSDSimpleTypeDefinition)this.getAnySimpleType(); // If the datatype is of a atomic variety then return it's referenced basetype } else { basetype = type.getBaseTypeDefinition(); if (basetype != null && isPrimitiveType(type) && isPrimitiveType(basetype)) { // If the type is a Teiid Designer built-in primitive type // (e.g. "http://www.metamatrix.com/metamodels/SimpleDatatypes-instance#string") // and its basetype is the XSD built-in primitive type // (e.g. "http://www.w3.org/2001/XMLSchema#string") // then return the UR-type of "anySimpleType" as the basetype if (DatatypeConstants.BUILTIN_DATATYPES_URI.equals(type.getTargetNamespace())) { basetype = (XSDSimpleTypeDefinition)this.getAnySimpleType(); } } } // If the basetype is anonymous then return "anySimpleType" as the basetype if (basetype != null && basetype.getName() == null) { basetype = (XSDSimpleTypeDefinition)this.getAnySimpleType(); } return basetype; } private boolean isPrimitiveType( EObject eObject ) { CoreArgCheck.isInstanceOf(XSDSimpleTypeDefinition.class, eObject); XSDSimpleTypeDefinition type = (XSDSimpleTypeDefinition)eObject; if (isBuiltInDatatype(type) && DatatypeConstants.getPrimitivedBuiltInTypeNames().contains(type.getName())) { return true; } return false; } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect#getPrimitiveType(org.eclipse.emf.ecore.EObject) * @since 4.3 */ @Override public Object getPrimitiveType( EObject eObject ) { CoreArgCheck.isInstanceOf(XSDSimpleTypeDefinition.class, eObject); // While the datatype type is not a built-in primitive type ... EObject simpleType = eObject; EObject baseType = null; while (simpleType != null) { baseType = (EObject)getBasetype(simpleType); if (baseType == null) { break; } if (XSDConstants.isURType((XSDSimpleTypeDefinition)baseType)) { return simpleType; } if (simpleType == baseType) { break; } simpleType = baseType; } return null; } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect#getPrimitiveTypeID(org.eclipse.emf.ecore.EObject) * @since 4.3 */ @Override public String getPrimitiveTypeID( EObject eObject ) { CoreArgCheck.isInstanceOf(XSDSimpleTypeDefinition.class, eObject); XSDSimpleTypeDefinition primitiveType = (XSDSimpleTypeDefinition)getPrimitiveType(eObject); if (primitiveType != null) { return this.getURI(primitiveType); } return null; } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect#getEnterpriseExtensionsMap(org.eclipse.emf.ecore.EObject) */ @Override public Map getEnterpriseExtensionsMap( EObject eObject ) { CoreArgCheck.isInstanceOf(XSDSimpleTypeDefinition.class, eObject); // If the datatype is a built-in datatype then use the Teiid Designer // instance since the instance found in the org.eclipse.xsd plugin // does not have extension map information. If the datatype is not a // built-in datatype then the original EObject reference is used. EObject type = this.getMmType(eObject); XSDSimpleTypeDefinition entity = (XSDSimpleTypeDefinition)type; XsdUtil.checkForEnterpriseConversion(entity); return getEnterpriseAttributes(entity); } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect#getDescription(org.eclipse.emf.ecore.EObject) */ @Override public String getDescription( EObject eObject ) { CoreArgCheck.isInstanceOf(XSDSimpleTypeDefinition.class, eObject); // If the datatype is a built-in datatype then use the Teiid Designer // instance since the instance found in the org.eclipse.xsd plugin // does not have description information. If the datatype is not a // built-in datatype then the original EObject reference is used. EObject type = this.getMmType(eObject); XSDSimpleTypeDefinition entity = (XSDSimpleTypeDefinition)type; XSDAnnotation annotation = entity.getAnnotation(); if (annotation != null) { final Iterator userInfos = annotation.getUserInformation().iterator(); while (userInfos.hasNext()) { final Element userInfo = (Element)userInfos.next(); final String value = XsdUtil.getChildText(userInfo); if (value != null) { return value; } } } return CoreStringUtil.Constants.EMPTY_STRING; } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect#isBuiltInDatatype(org.eclipse.emf.ecore.EObject) */ @Override public boolean isBuiltInDatatype( EObject eObject ) { CoreArgCheck.isInstanceOf(XSDSimpleTypeDefinition.class, eObject); XSDSimpleTypeDefinition entity = (XSDSimpleTypeDefinition)eObject; if (XSDConstants.isURType(entity)) { return true; } // if the entity is a proxy determine it is a built in data type based on the // proxy URI, this is to prevent the resource for the eObject being passed // to be loaded (Defect 13016) if (entity.eIsProxy()) { final URI eProxyURI = ((InternalEObject)eObject).eProxyURI(); if (eProxyURI != null) { String proxyURIString = eProxyURI.toString(); if (proxyURIString.startsWith(DatatypeConstants.BUILTIN_DATATYPES_URI) || proxyURIString.startsWith(XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001) || proxyURIString.startsWith(XSDConstants.SCHEMA_FOR_SCHEMA_URI_2000_10) || proxyURIString.startsWith(XSDConstants.SCHEMA_FOR_SCHEMA_URI_1999)) { return true; } return false; } } final String typeName = entity.getName(); if (typeName == null || this.mmDatatypeMap.get(typeName.toLowerCase()) == null) { return false; } final String namespaceUri = entity.getTargetNamespace(); if (DatatypeConstants.BUILTIN_DATATYPES_URI.equals(namespaceUri)) { return true; } if (XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001.equals(namespaceUri)) { return true; } if (XSDConstants.SCHEMA_FOR_SCHEMA_URI_2000_10.equals(namespaceUri)) { return true; } if (XSDConstants.SCHEMA_FOR_SCHEMA_URI_1999.equals(namespaceUri)) { return true; } return false; } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect#isComplexDatatype(org.eclipse.emf.ecore.EObject) */ @Override public boolean isComplexDatatype( EObject eObject ) { CoreArgCheck.isInstanceOf(XSDSimpleTypeDefinition.class, eObject); return false; } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect#isXSDSimpleTypeDefinition(org.eclipse.emf.ecore.EObject) */ @Override public boolean isSimpleDatatype( EObject eObject ) { CoreArgCheck.isInstanceOf(XSDSimpleTypeDefinition.class, eObject); return true; } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect#isURType(org.eclipse.emf.ecore.EObject) */ @Override public boolean isURType( EObject eObject ) { CoreArgCheck.isInstanceOf(XSDSimpleTypeDefinition.class, eObject); XSDSimpleTypeDefinition entity = (XSDSimpleTypeDefinition)eObject; return XSDConstants.isURType(entity); } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect#getVarietyType(org.eclipse.emf.ecore.EObject) */ @Override public short getVarietyType( EObject eObject ) { CoreArgCheck.isInstanceOf(XSDSimpleTypeDefinition.class, eObject); XSDSimpleTypeDefinition entity = (XSDSimpleTypeDefinition)eObject; XSDVariety variety = entity.getVariety(); if (variety.getValue() == XSDVariety.ATOMIC) { return MetadataConstants.DATATYPE_VARIETIES.ATOMIC; } else if (variety.getValue() == XSDVariety.LIST) { return MetadataConstants.DATATYPE_VARIETIES.LIST; } else if (variety.getValue() == XSDVariety.UNION) { return MetadataConstants.DATATYPE_VARIETIES.UNION; } return 0; } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect#getVarietyProps(org.eclipse.emf.ecore.EObject) */ @Override public List getVarietyProps( EObject eObject ) { CoreArgCheck.isInstanceOf(XSDSimpleTypeDefinition.class, eObject); XSDSimpleTypeDefinition entity = (XSDSimpleTypeDefinition)eObject; XSDVariety variety = entity.getVariety(); List varietyProps = new ArrayList(); if (variety.getValue() == XSDVariety.ATOMIC) { XSDSimpleTypeDefinition primitiveType = entity.getPrimitiveTypeDefinition(); if (primitiveType != null) { varietyProps.add(this.getURI(primitiveType)); } } else if (variety.getValue() == XSDVariety.LIST) { XSDSimpleTypeDefinition itemType = entity.getItemTypeDefinition(); if (itemType != null) { varietyProps.add(this.getURI(itemType)); } } else if (variety.getValue() == XSDVariety.UNION) { for (Iterator iter = entity.getMemberTypeDefinitions().iterator(); iter.hasNext();) { XSDSimpleTypeDefinition memberType = (XSDSimpleTypeDefinition)iter.next(); if (memberType != null) { varietyProps.add(this.getURI(memberType)); } } } return varietyProps; } /* * @See org.teiid.designer.core.metamodel.aspect.sql.SqlAspect#updateObject(org.eclipse.emf.ecore.EObject, org.eclipse.emf.ecore.EObject) */ @Override public void updateObject( EObject targetObject, EObject sourceObject ) { // do nothing } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlColumnAspect#isDatatypeFeature(org.eclipse.emf.ecore.EObject, * org.eclipse.emf.ecore.EStructuralFeature) */ @Override public boolean isDatatypeFeature( final EObject eObject, final EStructuralFeature eFeature ) { CoreArgCheck.isInstanceOf(XSDSimpleTypeDefinition.class, eObject); final EObjectImpl eObjectImpl = super.getEObjectImpl(eObject); if (eObjectImpl != null) { switch (eObjectImpl.eDerivedStructuralFeatureID(eFeature)) { case XSDPackage.XSD_SIMPLE_TYPE_DEFINITION__MEMBER_TYPE_DEFINITIONS: return true; case XSDPackage.XSD_SIMPLE_TYPE_DEFINITION__BASE_TYPE_DEFINITION: return true; case XSDPackage.XSD_SIMPLE_TYPE_DEFINITION__PRIMITIVE_TYPE_DEFINITION: return true; case XSDPackage.XSD_SIMPLE_TYPE_DEFINITION__ITEM_TYPE_DEFINITION: return true; } } return false; } /** * Check this <code>XSDSimpleTypeDefinition</code> to see if it contains the enterprise datatype attributes * * @param type * @return success true if this is an enterprise datatype */ @Override public boolean isEnterpriseDataType( final EObject type ) { CoreArgCheck.isNotNull(type); CoreArgCheckIsResolved(type); boolean success = false; if (type instanceof XSDSimpleTypeDefinition) { Map enterpriseAttributes = getEnterpriseAttributes((XSDSimpleTypeDefinition)type); if (!enterpriseAttributes.isEmpty()) { success = enterpriseAttributes.get(XsdSimpleTypeDefinitionAspect.UUID_ATTRIBUTE_NAME) != null && enterpriseAttributes.get(XsdSimpleTypeDefinitionAspect.RUNTIME_TYPE_ATTRIBUTE_NAME) != null && enterpriseAttributes.get(XsdSimpleTypeDefinitionAspect.RUNTIME_TYPE_FIXED_ATTRIBUTE_NAME) != null; } } return success; } /** * Set the attribute contents of <code>EnterpriseDatatypeInfo</code> on the <code>XSDSimpleTypeDefinition</code>. If the * schema for the enterprise datatype is not marked as an enterprise schema, it will be now marked with the namespace uri * import. These attrbiutes, which are prefixed with the enterprise namespace prefix, are validated correctly due to the XSD * specifications "lax" policy on qualified attrbutes names within complex types: <xs:complexType name="topLevelAttribute"> * <xs:complexContent> <xs:restriction base="xs:attribute"> <xs:sequence> <xs:element ref="xs:annotation" minOccurs="0"/> * <xs:element name="simpleType" type="xs:localSimpleType" minOccurs="0"/> </xs:sequence> <xs:attribute name="ref" * use="prohibited"/> <xs:attribute name="form" use="prohibited"/> <xs:attribute name="use" use="prohibited"/> <xs:attribute * name="name" type="xs:NCName" use="required"/> <xs:anyAttribute namespace="##other" processContents="lax"/> <---- * </xs:restriction> </xs:complexContent> </xs:complexType> * * @param type * @param edtInfo */ @Override public void setEnterpriseDataAttributes( final XSDSimpleTypeDefinition type, final EnterpriseDatatypeInfo edtInfo ) { CoreArgCheck.isNotNull(type); CoreArgCheckIsResolved(type); if (edtInfo.isValid()) { XsdUtil.setAsEnterpriseSchema(type.getSchema()); final Element element = type.getElement(); final Document doc = element.getOwnerDocument(); boolean isModified = false; Attr attribute; final String uuid = edtInfo.getUuid(); if ((uuid != null)) { attribute = doc.createAttributeNS(XsdConstants.SCHEMA_FOR_ENTERPRISE_DATATYPES_URI_2005, XsdSimpleTypeDefinitionAspect.UUID_ATTRIBUTE_NAME); attribute.setValue(uuid); attribute.setPrefix(XsdConstants.PREFIX_FOR_ENTERPRISE_DATATYPES_URI_2005); type.getElement().setAttributeNode(attribute); isModified = true; } final String runtimeType = edtInfo.getRuntimeType(); if ((runtimeType != null)) { attribute = doc.createAttributeNS(XsdConstants.SCHEMA_FOR_ENTERPRISE_DATATYPES_URI_2005, XsdSimpleTypeDefinitionAspect.RUNTIME_TYPE_ATTRIBUTE_NAME); attribute.setValue(runtimeType); attribute.setPrefix(XsdConstants.PREFIX_FOR_ENTERPRISE_DATATYPES_URI_2005); type.getElement().setAttributeNode(attribute); isModified = true; } final Boolean runtimeTypeFixed = edtInfo.getRuntimeTypeFixed(); if ((runtimeTypeFixed != null)) { attribute = doc.createAttributeNS(XsdConstants.SCHEMA_FOR_ENTERPRISE_DATATYPES_URI_2005, XsdSimpleTypeDefinitionAspect.RUNTIME_TYPE_FIXED_ATTRIBUTE_NAME); attribute.setValue(runtimeTypeFixed.toString()); attribute.setPrefix(XsdConstants.PREFIX_FOR_ENTERPRISE_DATATYPES_URI_2005); type.getElement().setAttributeNode(attribute); isModified = true; } type.eResource().setModified(isModified); } } /** * Remove the enterprise datatype attributes from the given <code>XSDSimpleTypeDefinition</code>. If there are no enterprise * datatypes left in the schema, remove the enterprise namespace declaration. * * @param type */ @Override public void unSetEnterpriseDataAttributes( final XSDSimpleTypeDefinition type ) { CoreArgCheck.isNotNull(type); CoreArgCheckIsResolved(type); final Element element = type.getElement(); element.removeAttributeNS(XsdConstants.SCHEMA_FOR_ENTERPRISE_DATATYPES_URI_2005, XsdSimpleTypeDefinitionAspect.UUID_ATTRIBUTE_NAME); element.removeAttributeNS(XsdConstants.SCHEMA_FOR_ENTERPRISE_DATATYPES_URI_2005, XsdSimpleTypeDefinitionAspect.RUNTIME_TYPE_ATTRIBUTE_NAME); element.removeAttributeNS(XsdConstants.SCHEMA_FOR_ENTERPRISE_DATATYPES_URI_2005, XsdSimpleTypeDefinitionAspect.RUNTIME_TYPE_FIXED_ATTRIBUTE_NAME); if (!containsEnterpriseDatatypes(type.getSchema())) { XsdUtil.unsetAsEnterpriseSchema(type.getSchema()); } type.eResource().setModified(true); } /** * Obtain the enterprise datatype attributes values from the given <code>XSDSimpleDefinitionType</code> and wrap them in an * <code>EnterpriseDatatypeInfo</code>. * * @param type * @return edtInfo */ @Override public EnterpriseDatatypeInfo getEnterpriseDatatypeInfo( final XSDSimpleTypeDefinition type ) { CoreArgCheck.isNotNull(type); CoreArgCheckIsResolved(type); XsdUtil.checkForEnterpriseConversion(type); EnterpriseDatatypeInfo edtInfo = new EnterpriseDatatypeInfo(); if (XsdUtil.isEnterpriseSchema(type.getSchema()) && isEnterpriseDataType(type)) { final Map attributes = getEnterpriseAttributes(type); edtInfo.setUuid((String)attributes.get(XsdSimpleTypeDefinitionAspect.UUID_ATTRIBUTE_NAME)); edtInfo.setRuntimeType((String)attributes.get(XsdSimpleTypeDefinitionAspect.RUNTIME_TYPE_ATTRIBUTE_NAME)); String runtimeTypeFixed = (String)attributes.get(XsdSimpleTypeDefinitionAspect.RUNTIME_TYPE_FIXED_ATTRIBUTE_NAME); edtInfo.setRuntimeTypeFixed(Boolean.valueOf(runtimeTypeFixed)); } return edtInfo; } /** * Non-interface method Convert a <code>XSDSimpleTypeDefinition</code> to an enterprise datatype if it has existing enterprise * parameters (uuid, runtimetype) in an appinfo tag * * @param type */ public void convertEnterpriseDatatype( final XSDSimpleTypeDefinition type ) { CoreArgCheck.isNotNull(type); CoreArgCheckIsResolved(type); if (!isEnterpriseDataType(type)) { EnterpriseDatatypeInfo edtInfo = getEnterpriseAttributesFromAppInfo(type); if (edtInfo.isValid()) { setEnterpriseDataAttributes(type, edtInfo); removeEnterpriseAttributesFromAppInfo(type); type.eNotify(new ENotificationImpl((InternalEObject)type, Notification.ADD, null, null, type)); } } } /** * @see org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect#setBasetype(org.eclipse.xsd.XSDSimpleTypeDefinition, * org.eclipse.xsd.XSDSimpleTypeDefinition) * @since 4.3 */ @Override public void setBasetype( final XSDSimpleTypeDefinition simpleType, final XSDSimpleTypeDefinition baseType ) { CoreArgCheck.isNotNull(simpleType); CoreArgCheck.isNotNull(baseType); CoreArgCheckIsResolved(simpleType); CoreArgCheckIsResolved(baseType); final XSDSchema schema = simpleType.getSchema(); if (simpleType.eResource() != baseType.eResource()) { if (!XSDConstants.isSchemaForSchemaNamespace(baseType.getTargetNamespace()) && !XsdUtil.containsImport(schema, baseType.getTargetNamespace())) { XsdUtil.addImport(simpleType, baseType); } } final String oldReferencedNamespace = simpleType.getBaseTypeDefinition().getTargetNamespace(); simpleType.setBaseTypeDefinition(baseType); // if the old basetype's namespace is // 1) not the target namespace // 2) no longer referenced in this schema // then remove it's declaration (and import, if one exists); if (oldReferencedNamespace != null && !oldReferencedNamespace.equals(schema.getTargetNamespace()) && !XsdUtil.containsReferenceToNamespace(schema, oldReferencedNamespace)) { XsdUtil.removeNamespaceRef(schema, oldReferencedNamespace); // if the old basetype's namespace is longer referenced in this schema, remove it's import if one exists; if (XsdUtil.containsImport(schema, oldReferencedNamespace)) { XsdUtil.removeImport(schema, oldReferencedNamespace); } } } private void CoreArgCheckIsResolved( EObject e ) { if (e.eIsProxy()) { throw new IllegalArgumentException( XsdPlugin.Util.getString("XsdSimpleTypeDefinitionAspect.Error_EObject_can_not_be_a_proxy", e.toString())); //$NON-NLS-1$ } } private void initializeMmDatatypeMap() { try { // Retrieve the Teiid Designer built-in datatype resource from the model container Resource resource = null; final List<ResourceSet> resourceSets = ModelerCore.getExternalResourceSets(); for (ResourceSet resourceSet : resourceSets) { resource = resourceSet.getResource(BUILTIN_DATATYPES_URI, false); if (resource != null) { break; // Found it!! } } if (resource == null) { final Object[] params = new Object[] {BUILTIN_DATATYPES_URI}; final String msg = XsdPlugin.Util.getString("XsdSimpleTypeDefinitionAspect.Error_obtain_the_built-in_datatypes_resource_from_the_container_using_URI_1", params); //$NON-NLS-1$ XsdPlugin.Util.log(IStatus.ERROR, msg); } if (resource != null) { // Populate the mmDatatypeMap map with all built-in datatypes // keyed by lower case name for (Iterator iter = resource.getContents().iterator(); iter.hasNext();) { EObject eObject = (EObject)iter.next(); if (eObject != null && eObject instanceof XSDSchema) { // Found the schema now gather all the global simple types ... for (Iterator iter2 = eObject.eContents().iterator(); iter2.hasNext();) { eObject = (EObject)iter2.next(); if (eObject != null && eObject instanceof XSDSimpleTypeDefinition) { final XSDSimpleTypeDefinition type = (XSDSimpleTypeDefinition)eObject; final String typeName = type.getName(); this.mmDatatypeMap.put(typeName.toLowerCase(), type); } } } } } } catch (Throwable e) { final Object[] params = new Object[] {BUILTIN_DATATYPES_URI}; final String msg = XsdPlugin.Util.getString("XsdSimpleTypeDefinitionAspect.Error_obtain_the_built-in_datatypes_resource_from_the_container_using_URI_1", params); //$NON-NLS-1$ XsdPlugin.Util.log(IStatus.ERROR, e, msg); } } private EObject getAnySimpleType() { if (this.anySimpleType == null) { this.anySimpleType = XSDSchemaImpl.getGlobalResourceSet().getEObject(ANY_SIMPLE_TYPE_URI, true); } return this.anySimpleType; } /** * If the specified XSDTypeDefinition is a built-in datatype then return the Teiid Designer built-in datatype as defined in * the modeler.sdt plugin. If specified type is not a built-in datatype then the original EObject reference is returned. * * @param type * @return */ private EObject getMmType( final EObject eObject ) { if (this.isURType(eObject)) { return eObject; } else if (this.isBuiltInDatatype(eObject)) { final XSDSimpleTypeDefinition type = (XSDSimpleTypeDefinition)eObject; final String typeName = type.getName(); final EObject mmdt = (EObject)this.mmDatatypeMap.get(typeName.toLowerCase()); return mmdt; } return eObject; } /** * Check the given <code>XSDSchema</code> to see if it has any enterprise datatypes. * * @param schema * @return success true if the schema contains at least one enterprise datatype */ private boolean containsEnterpriseDatatypes( final XSDSchema schema ) { boolean success = false; final EList contents = schema.getContents(); for (final Iterator it = new ArrayList(contents).iterator(); it.hasNext();) { final Object o = it.next(); if (o instanceof XSDSimpleTypeDefinition) { final XSDSimpleTypeDefinition sdt = (XSDSimpleTypeDefinition)o; if (isEnterpriseDataType(sdt)) { success = true; break; } } } return success; } /** * Obtain the old appinfo enterprise tag attributes. * * @param type */ public EnterpriseDatatypeInfo getEnterpriseAttributesFromAppInfo( final XSDSimpleTypeDefinition type ) { CoreArgCheck.isNotNull(type); EnterpriseDatatypeInfo edtInfo = new EnterpriseDatatypeInfo(); final XSDAnnotation annotation = type.getAnnotation(); if (annotation != null) { for (final Iterator it = annotation.getApplicationInformation().iterator(); it.hasNext();) { final Element appInfo = (Element)it.next(); if (appInfo.getAttributes() != null && appInfo.getAttributes().getLength() > 0) { edtInfo.setUuid(appInfo.getAttribute(XsdSimpleTypeDefinitionAspect.UUID_ATTRIBUTE_NAME)); edtInfo.setRuntimeType(appInfo.getAttribute(XsdSimpleTypeDefinitionAspect.RUNTIME_TYPE_ATTRIBUTE_NAME)); edtInfo.setRuntimeTypeFixed(Boolean.FALSE); } } } return edtInfo; } /** * Remove the old appinfo enterprise tag attributes. If this leaves the appinfo tag empty, remove it as well * * @param type */ private void removeEnterpriseAttributesFromAppInfo( final XSDSimpleTypeDefinition type ) { CoreArgCheck.isNotNull(type); final XSDAnnotation annotation = type.getAnnotation(); if (annotation != null) { for (final Iterator it = annotation.getApplicationInformation().iterator(); it.hasNext();) { final Element appInfo = (Element)it.next(); if (appInfo != null) { if (appInfo.getAttributes() != null && appInfo.getAttributes().getLength() > 0) { appInfo.removeAttribute(XsdSimpleTypeDefinitionAspect.UUID_ATTRIBUTE_NAME); appInfo.removeAttribute(XsdSimpleTypeDefinitionAspect.RUNTIME_TYPE_ATTRIBUTE_NAME); if (appInfo.getAttributes().getLength() == 0) { it.remove(); } } } } if (annotation.getApplicationInformation().size() == 0) { annotation.getApplicationInformation().clear(); } } } /** * Obtain the enterprise datatype attribute values from the given <code>XSDSimpleDefinitionType</code> and return them in a * map. * * @param type * @return results map which contains the enterprise attributes as keys */ private Map getEnterpriseAttributes( final XSDSimpleTypeDefinition type ) { CoreArgCheck.isNotNull(type); final Map results = new HashMap(); final Element typeElement = type.getElement(); if (typeElement != null) { if ((typeElement.getAttributes() == null) || (typeElement.getAttributes().getLength() == 0)) { return Collections.EMPTY_MAP; } results.put(XsdSimpleTypeDefinitionAspect.UUID_ATTRIBUTE_NAME, getEnterpriseAttributeValue(type, XsdSimpleTypeDefinitionAspect.UUID_ATTRIBUTE_NAME)); results.put(XsdSimpleTypeDefinitionAspect.RUNTIME_TYPE_ATTRIBUTE_NAME, getEnterpriseAttributeValue(type, XsdSimpleTypeDefinitionAspect.RUNTIME_TYPE_ATTRIBUTE_NAME)); results.put(XsdSimpleTypeDefinitionAspect.RUNTIME_TYPE_FIXED_ATTRIBUTE_NAME, getEnterpriseAttributeValue(type, XsdSimpleTypeDefinitionAspect.RUNTIME_TYPE_FIXED_ATTRIBUTE_NAME)); } return results; } /** * Helper method to extract the UUID string from the simple datatype definition's enterprise data * * @param type * @param name * @return the value of the UUID */ private String getEnterpriseAttributeValue( final XSDSimpleTypeDefinition type, final String name ) { Attr attrNS = type.getElement().getAttributeNodeNS(XsdConstants.SCHEMA_FOR_ENTERPRISE_DATATYPES_URI_2005, name); return attrNS != null ? attrNS.getValue() : null; } private String getURI( final XSDSimpleTypeDefinition type ) { CoreArgCheck.isNotNull(type); XSDSchema xsdSchema = type.getSchema(); String theTargetNamespace = xsdSchema == null ? type.getTargetNamespace() : xsdSchema.getTargetNamespace(); if (theTargetNamespace == null) { theTargetNamespace = CoreStringUtil.Constants.EMPTY_STRING; } if (theTargetNamespace.equals(DatatypeConstants.BUILTIN_DATATYPES_URI)) { // If this datatype is not one of the extended built-in types change the // target namespace from "http://www.metamatrix.com/metamodels/SimpleDatatypes-instance" // to "http://www.w3.org/2001/XMLSchema" final String typeName = type.getName(); if (!DatatypeConstants.getMetaMatrixExtendedBuiltInTypeNames().contains(typeName)) { theTargetNamespace = ModelerCore.XML_SCHEMA_GENERAL_URI; } } String theName = type.getName(); if (theName == null) { theName = type.getAliasName(); } return theTargetNamespace + "#" + theName; //$NON-NLS-1$ } }