/* * 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.sdt.types; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IStatus; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.xsd.XSDSimpleTypeDefinition; import org.eclipse.xsd.XSDTypeDefinition; import org.eclipse.xsd.XSDVariety; import org.teiid.core.designer.ModelerCoreException; import org.teiid.core.designer.id.IDGenerator; import org.teiid.core.designer.id.ObjectID; import org.teiid.core.designer.id.UUID; import org.teiid.core.designer.util.CoreArgCheck; import org.teiid.designer.core.ModelerCore; import org.teiid.designer.core.container.Container; import org.teiid.designer.core.metamodel.aspect.AspectManager; import org.teiid.designer.core.metamodel.aspect.sql.SqlAspect; import org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect; import org.teiid.designer.core.types.DatatypeManager; import org.teiid.designer.core.types.DatatypeManagerLifecycle; import org.teiid.designer.core.workspace.ModelResource; import org.teiid.designer.core.workspace.ModelUtil; import org.teiid.designer.metamodels.xsd.aspects.sql.XsdSimpleTypeDefinitionAspect; import org.teiid.designer.sdt.ModelerSdtPlugin; /** * DatatypeManagerImpl * * @since 8.0 */ public abstract class AbstractDatatypeManager implements DatatypeManager, DatatypeManagerLifecycle { private static SqlDatatypeAspect sqlDatatypeAspect; private static final Comparator TYPE_NAME_COMPARATOR = new DatatypeNameComparator(); private ResourceSet container; // ================================================================================== // C O N S T R U C T O R S // ================================================================================== /** * Construct an instance of DatatypeManagerImpl. */ public AbstractDatatypeManager() { } /** * @see org.teiid.designer.core.types.DatatypeManagerLifecycle#initialize(org.teiid.designer.core.container.Container) * @since 4.2 */ @Override public void initialize( final ResourceSet container ) throws ModelerCoreException { this.container = container; doInitialize(); } protected abstract void doInitialize() throws ModelerCoreException; @Override public ResourceSet getContainer() { return this.container; } // ================================================================================== // P R O T E C T E D M E T H O D S // ================================================================================== /** * Return true if the identifier string includes a ObjectID string */ protected static boolean containsUuidPattern( final String id ) { return (id != null && id.indexOf(UUID.PROTOCOL) >= 0); } /** * Extract the UUID String from the identifier * * @param id * @return * @throws ModelerCoreException */ protected static String extractUuidString( final String id ) { if (containsUuidPattern(id)) { int beginIndex = id.indexOf(UUID.PROTOCOL); return id.substring(beginIndex); } return null; } protected static ObjectID getObjectIDFromString( final String idString ) throws ModelerCoreException { try { return IDGenerator.getInstance().stringToObject(idString); } catch (Throwable e) { throw new ModelerCoreException( e, ModelerSdtPlugin.Util.getString("DatatypeManagerImpl.Error_finding_the_EObject_with_UUID_11", idString)); //$NON-NLS-1$ } } protected static void sortByName( final List eObjs ) { Collections.sort(eObjs, TYPE_NAME_COMPARATOR); } protected static SqlDatatypeAspect getSqlAspect( final EObject eObject ) { if (eObject != null && eObject instanceof XSDSimpleTypeDefinition) { if (ModelerCore.getPlugin() == null) { if (AbstractDatatypeManager.sqlDatatypeAspect == null) { AbstractDatatypeManager.sqlDatatypeAspect = new XsdSimpleTypeDefinitionAspect(null); } return AbstractDatatypeManager.sqlDatatypeAspect; } // Defect 23839 - rather than calling the metamodel registry to get aspect, use the AspectManager which is caching // these aspects!!!! SqlAspect sqlAspect = AspectManager.getSqlAspect(eObject); if (sqlAspect instanceof SqlDatatypeAspect) { return (SqlDatatypeAspect)sqlAspect; } } return null; } protected static void removeDuplicates( final List eObjs ) { List tmp = new ArrayList(eObjs.size()); for (Iterator iter = eObjs.iterator(); iter.hasNext();) { EObject eObj = (EObject)iter.next(); if (!tmp.contains(eObj)) { tmp.add(eObj); } else { iter.remove(); } } } /** * Return an array of EMF Resource instances representing all user-defined datatype models known within the model workspace * * @return * @throws ModelerCoreException */ protected List getDatatypeResources() { /* * Defect 16802 - Goal: Improve this method so that no resources from closed projects * will be included in the returned list. * Strategy: * - First part (if in Eclipse and container is a ModelContainer) * 1. retrieve the set of all resources in open projects * 2. loop through the set doing the tests the old Resourcevisitor did * to determine if the resource is either an XSD file * OR if it contains user-defined datatypes. * - Second part (Not in Eclipse or not a model container) * Leave this to work as before. */ final ResourceSet container = this.getContainer(); if (container == null) { return Collections.EMPTY_LIST; } // Container is never null from this point on ... if (ModelerSdtPlugin.getDefault() != null && (container instanceof Container) && // this is in the Eclipse environment ... ModelerCore.isModelContainer((Container)container)) { // the container is the ModelContainer List lstResultResources = new ArrayList(); try { // get the set of resources that are in open projects ModelResource[] mrResources = ModelerCore.getModelWorkspace().getModelResources(); // walk the list and capture the resources that are related to datatypes for (int i = 0; i < mrResources.length; i++) { ModelResource mrResource = mrResources[i]; IResource irResource = mrResource.getResource(); // If the IResource represents a model file or XSD ... if (ModelUtil.isModelFile(irResource) && irResource.exists()) { // If the resource is an XSD, automatically add it to the list of EMF resources ... if (ModelUtil.isXsdFile(irResource)) { final Resource xsdResource = mrResource.getEmfResource(); if (xsdResource != null) { lstResultResources.add(xsdResource); } } // } else { // final IPath resourcePath = irResource.getLocation(); // final File resourceFile = resourcePath.toFile(); // final XMIHeader header = ModelUtil.getXmiHeader(resourceFile); // // // Check if the primary metamodel URI is the user-defined datatype metamodel // if (header != null && DatatypeConstants.DATATYPE_METAMODEL_URI.equals(header.getPrimaryMetamodelURI())) // { // final Resource xsdResource = mrResource.getEmfResource(); // if (xsdResource != null) { // lstResultResources.add(xsdResource); // } // } // } } } } catch (CoreException ce) { ModelerCore.Util.log(ce); } return lstResultResources; } // Otherwise it is not the model container, so get the list of resources from the resource set ... final List resources = container.getResources(); final List datatypeResources = new ArrayList(); final Iterator iter = resources.iterator(); while (iter.hasNext()) { final Resource resource = (Resource)iter.next(); // If the resource is an XSD, automatically add it to the list of EMF resources ... if (ModelUtil.isXsdFile(resource)) { datatypeResources.add(resource); } // } else { // // Looking for DATATYPE models ... // String metamodelUri = null; // if ( resource instanceof EmfResource ) { // final ModelAnnotation annotation = ((EmfResource)resource).getModelAnnotation(); // if ( annotation != null ) { // metamodelUri = annotation.getPrimaryMetamodelUri(); // } // } else { // final URI resourceUri = resource.getURI(); // if ( resourceUri.isFile() ) { // final String location = resourceUri.toFileString(); // final File resourceFile = new File(location); // if ( resourceFile.exists() ) { // try { // final XMIHeader header = XMIHeaderReader.readHeader(resourceFile); // metamodelUri = header.getPrimaryMetamodelURI(); // } catch (CoreException e) { // ModelerCore.Util.log(e); // } // } // } // } // // // Check if the primary metamodel URI is the user-defined datatype metamodel // if (DatatypeConstants.DATATYPE_METAMODEL_URI.equals(metamodelUri)) { // datatypeResources.add(resource); // } // } } return datatypeResources; } /** * Return an array of EObject instances representing the type hierarchy for this simple datatype. The array is ordered such * that the first entry is the datatype itself and the last entry is the ur-type of "anySimpleType". If the specified EObject * is a XSDSimpleTypeDefinition instance of variety union or list then only the datatype itself is returned in the array. * * @param type * @return EObject[] */ @Override public EObject[] getTypeHierarchy( final EObject type ) { CoreArgCheck.isInstanceOf(XSDSimpleTypeDefinition.class, type); // If the simple type is not atomic then cannot navigate the hierarchy if (((XSDSimpleTypeDefinition)type).getVariety() != XSDVariety.ATOMIC_LITERAL) { return new EObject[] {type}; } // Construct a list to hold the type hierarchy final List tmp = new ArrayList(); tmp.add(type); // Navigate up the basetype hierarchy until we reach "anySimpleType" try { EObject simpleType = type; while (simpleType != this.getAnySimpleType()) { final EObject baseType = this.getBaseType(simpleType); if (baseType == null) { break; } else if (baseType == this.getAnyType()) { break; } else if (simpleType == baseType) { break; // this would end up being recursion ... } tmp.add(baseType); simpleType = baseType; } } catch (ModelerCoreException e) { ModelerSdtPlugin.Util.log(IStatus.ERROR, e, e.getMessage()); } return (EObject[])tmp.toArray(new EObject[tmp.size()]); } // ================================================================================== // I N N E R C L A S S // ================================================================================== protected static class DatatypeNameComparator implements Comparator { @Override public int compare( Object obj1, Object obj2 ) { if (obj1 == null && obj2 == null) { return 0; } else if (obj1 == null && obj2 != null) { return -1; } else if (obj1 != null && obj2 == null) { return 1; } XSDTypeDefinition dt1 = (XSDTypeDefinition)obj1; XSDTypeDefinition dt2 = (XSDTypeDefinition)obj2; String value1 = dt1.getName(); String value2 = dt2.getName(); return value1.compareToIgnoreCase(value2); // return value1.compareTo(value2); } } }