/*
* 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.core.resource;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.xsd.XSDComponent;
import org.eclipse.xsd.XSDSchema;
import org.eclipse.xsd.XSDSimpleTypeDefinition;
import org.eclipse.xsd.util.XSDConstants;
import org.eclipse.xsd.util.XSDResourceImpl;
import org.teiid.core.designer.util.CoreArgCheck;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.core.types.DatatypeConstants;
import org.teiid.designer.core.util.ModelObjectCollector;
/**
* @since 8.0
*/
public class BuiltInTypesHrefConverter implements EObjectHrefConverter {
/** Delimiter used to separate the URI string from the URI fragment */
protected static final String URI_REFERENCE_DELIMITER = "#"; //$NON-NLS-1$
protected static final String SCHEMA_FOR_SCHEMA_URI_2001_SUFFIX = "www.w3.org/2001/XMLSchema.xsd"; //$NON-NLS-1$
protected static final String SCHEMA_INSTANCE_URI_2001_SUFFIX = "www.w3.org/2001/XMLSchema-instance.xsd"; //$NON-NLS-1$
protected static final String MAGIC_SCHEMA_URI_2001_SUFFIX = "www.w3.org/2001/MagicXMLSchema.xsd"; //$NON-NLS-1$
protected static final URI SCHEMA_FOR_SCHEMA_URI = URI.createURI(XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001);
protected static final URI SCHEMA_INSTANCE_URI = URI.createURI(XSDConstants.SCHEMA_INSTANCE_URI_2001);
protected static final URI XML_MAGIC_SCHEMA_URI = URI.createURI("http://www.w3.org/2001/MagicXMLSchema"); //$NON-NLS-1$
protected static final URI XML_SCHEMA_URI = URI.createURI("http://www.w3.org/2001/xml.xsd"); //$NON-NLS-1$
protected static final URI BUILTIN_DATATYPES_URI = URI.createURI(DatatypeConstants.BUILTIN_DATATYPES_URI);
private static final boolean DEBUG = false;
private Map logicalUriMap = null;
private Map physicalUriMap = null;
private ResourceSet eResourceSet = null;
// ==================================================================================
// C O N S T R U C T O R S
// ==================================================================================
/**
* @since 5.0
*/
public BuiltInTypesHrefConverter( final ResourceSet theResourceSet ) {
CoreArgCheck.isNotNull(theResourceSet);
this.eResourceSet = theResourceSet;
this.logicalUriMap = new HashMap();
this.physicalUriMap = new HashMap();
doInit();
}
// ==================================================================================
// I N T E R F A C E M E T H O D S
// ==================================================================================
/**
* @see org.teiid.designer.core.resource.EObjectHrefConverter#getLogicalURI(org.eclipse.emf.ecore.EObject)
* @since 5.0
*/
@Override
public URI getLogicalURI( final EObject eObject ) {
CoreArgCheck.isNotNull(eObject);
URI physicalURI = createPhysicalURI(eObject);
return (URI)this.logicalUriMap.get(physicalURI);
}
/**
* @see org.teiid.designer.core.resource.EObjectHrefConverter#getLogicalURI(org.eclipse.emf.common.util.URI)
* @since 5.0
*/
@Override
public URI getLogicalURI( final URI physicalURI ) {
CoreArgCheck.isNotNull(physicalURI);
return (URI)this.logicalUriMap.get(physicalURI);
}
/**
* @see org.teiid.designer.core.resource.EObjectHrefConverter#getPhysicalURI(org.eclipse.emf.ecore.EObject)
* @since 5.0
*/
@Override
public URI getPhysicalURI( final EObject eObject ) {
CoreArgCheck.isNotNull(eObject);
URI logicalURI = createLogicalURI(eObject);
return (URI)this.physicalUriMap.get(logicalURI);
}
/**
* @see org.teiid.designer.core.resource.EObjectHrefConverter#getPhysicalURI(org.eclipse.emf.common.util.URI)
* @since 5.0
*/
@Override
public URI getPhysicalURI( final URI logicalURI ) {
CoreArgCheck.isNotNull(logicalURI);
return (URI)this.physicalUriMap.get(logicalURI);
}
// ==================================================================================
// P R O T E C T E D M E T H O D S
// ==================================================================================
/**
* Populate the URI map with the logical to physical URI EObject mappings for all built-in datatypes along with the inverse
* mappings of physical to logical URI.
*/
protected synchronized void doInit() {
// Create URI mappings for the Teiid Designer built-in datatypes resource
// "http://www.metamatrix.com/metamodels/SimpleDatatypes-instance"
XSDResourceImpl xsdResource = getBuiltInTypesResource(BUILTIN_DATATYPES_URI);
if (xsdResource != null) {
XSDSchema schema = xsdResource.getSchema();
CoreArgCheck.isNotNull(schema);
addMappings(getXsdComponents(schema));
} else {
String msg = ModelerCore.Util.getString("BuiltInTypesHrefConverter.BuiltInTypes_resource_not_loaded", BUILTIN_DATATYPES_URI); //$NON-NLS-1$
ModelerCore.Util.log(msg);
}
// Create URI mappings for the XML schema for schema resource
// "http://www.w3.org/2001/XMLSchema"
xsdResource = getBuiltInTypesResource(SCHEMA_FOR_SCHEMA_URI);
if (xsdResource != null) {
XSDSchema schema = xsdResource.getSchema();
CoreArgCheck.isNotNull(schema);
addMappings(getXsdComponents(schema));
} else {
String msg = ModelerCore.Util.getString("BuiltInTypesHrefConverter.BuiltInTypes_resource_not_loaded", SCHEMA_FOR_SCHEMA_URI); //$NON-NLS-1$
ModelerCore.Util.log(msg);
}
// Create URI mappings for the XML schema instance resource
// "http://www.w3.org/2001/XMLSchema-instance"
xsdResource = getBuiltInTypesResource(SCHEMA_INSTANCE_URI);
if (xsdResource != null) {
XSDSchema schema = xsdResource.getSchema();
CoreArgCheck.isNotNull(schema);
addMappings(getXsdComponents(schema));
} else {
String msg = ModelerCore.Util.getString("BuiltInTypesHrefConverter.BuiltInTypes_resource_not_loaded", SCHEMA_INSTANCE_URI); //$NON-NLS-1$
ModelerCore.Util.log(msg);
}
// Create URI mappings for the xml.xsd resource
// "http://www.w3.org/2001/xml.xsd"
xsdResource = getBuiltInTypesResource(XML_SCHEMA_URI);
if (xsdResource != null) {
XSDSchema schema = xsdResource.getSchema();
CoreArgCheck.isNotNull(schema);
addMappings(getXsdComponents(schema));
} else {
String msg = ModelerCore.Util.getString("BuiltInTypesHrefConverter.BuiltInTypes_resource_not_loaded", XML_SCHEMA_URI); //$NON-NLS-1$
ModelerCore.Util.log(msg);
}
// Create URI mappings for the XML magic schema resource (contains xs:anyType, xs:anySimpleType)
// "http://www.w3.org/2001/MagicXMLSchema"
xsdResource = getBuiltInTypesResource(XML_MAGIC_SCHEMA_URI);
if (xsdResource != null) {
XSDSchema schema = xsdResource.getSchema();
CoreArgCheck.isNotNull(schema);
addMappings(getXsdComponents(schema));
} else {
String msg = ModelerCore.Util.getString("BuiltInTypesHrefConverter.BuiltInTypes_resource_not_loaded", XML_MAGIC_SCHEMA_URI); //$NON-NLS-1$
ModelerCore.Util.log(msg);
}
if (DEBUG) {
ModelerCore.Util.log("BuiltInTypesHrefConverter.doInit(): uriMap.size() = " + this.logicalUriMap.size()); //$NON-NLS-1$
}
}
/**
* Return the built-in type resource specified by the URI
*
* @param logicalUri
* @return
* @since 5.0
*/
protected XSDResourceImpl getBuiltInTypesResource( final URI logicalUri ) {
CoreArgCheck.isNotNull(logicalUri);
XSDResourceImpl r = (XSDResourceImpl)eResourceSet.getResource(logicalUri, false);
if (r != null && !r.isLoaded()) {
try {
r.load(eResourceSet.getLoadOptions());
} catch (Throwable e) {
ModelerCore.Util.log(e);
}
}
return r;
}
/**
* Create URI mappings for the apecified array of XSDComponent instances
*
* @param components
* @since 5.0
*/
protected void addMappings( final XSDComponent[] components ) {
CoreArgCheck.isNotNull(components);
for (int i = 0; i != components.length; ++i) {
final URI logicalURI = createLogicalURI(components[i]);
final URI physicalURI = createPhysicalURI(components[i]);
this.physicalUriMap.put(logicalURI, physicalURI);
this.logicalUriMap.put(physicalURI, logicalURI);
if (DEBUG) {
ModelerCore.Util.log("BuiltInTypesHrefConverter.addMappings(): " + logicalURI + " -> " + physicalURI); //$NON-NLS-1$ //$NON-NLS-2$
}
}
}
/**
* Return an array of all XSDComponent instances found in the specified schema
*
* @param schema
* @return
* @since 5.0
*/
protected XSDComponent[] getXsdComponents( final XSDSchema schema ) {
CoreArgCheck.isNotNull(schema);
// Collect all the EObject instances in this resource using the
// ModelObjectCollector class to avoid a ConcurrentModificationException
// that may occur when using the TreeIterator (i.e. super.getAllContents())
CoreArgCheck.isNotNull(schema.eResource());
final ModelObjectCollector moc = new ModelObjectCollector(schema.eResource());
final List result = moc.getEObjects();
for (final Iterator i = result.iterator(); i.hasNext();) {
final EObject eObject = (EObject)i.next();
if (!(eObject instanceof XSDComponent)) {
i.remove();
}
}
return (XSDComponent[])result.toArray(new XSDComponent[result.size()]);
}
/**
* Return the logical URI for the specified XSD component. The URIs are derived in a manner that is consistent with the
* EResourceXmiSaveImpl method of writing href values representing references to these XSD components
*
* @param component
* @return
* @since 5.0
*/
protected URI createLogicalURI( final EObject eObject ) {
URI logicalURI = null;
if (eObject instanceof XSDSimpleTypeDefinition) {
logicalURI = URI.createURI(((XSDSimpleTypeDefinition)eObject).getURI());
} else {
// Get the URI for the object (this works if it's a proxy) ...
final URI uri = EcoreUtil.getURI(eObject);
final String uriString = uri.trimFragment().toString();
// MagicXMLSchema.xsd suffix on the resource URI
if (uriString.endsWith(MAGIC_SCHEMA_URI_2001_SUFFIX)) {
logicalURI = XML_MAGIC_SCHEMA_URI.appendFragment(uri.fragment());
}
// XMLSchema.xsd suffix on the resource URI
else if (uriString.endsWith(SCHEMA_FOR_SCHEMA_URI_2001_SUFFIX)) {
logicalURI = SCHEMA_FOR_SCHEMA_URI.appendFragment(uri.fragment());
}
// XMLSchema-instance.xsd suffix on the resource URI
else if (uriString.endsWith(SCHEMA_INSTANCE_URI_2001_SUFFIX)) {
logicalURI = SCHEMA_INSTANCE_URI.appendFragment(uri.fragment());
}
}
return logicalURI;
}
/**
* Return the physical URI for the specified EObject.
*
* @param eObject
* @return
* @since 5.0
*/
protected URI createPhysicalURI( final EObject eObject ) {
return EcoreUtil.getURI(eObject);
}
}