/* * 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.workspace; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.ResourceAttributes; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.InternalEObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.xsd.XSDPackage; import org.eclipse.xsd.util.XSDResourceImpl; import org.teiid.core.designer.CoreModelerPlugin; import org.teiid.core.designer.TeiidDesignerException; import org.teiid.core.designer.util.CoreArgCheck; import org.teiid.core.designer.util.CoreStringUtil; import org.teiid.core.designer.util.FileSeparatorUtil; import org.teiid.core.designer.util.FileUtil; import org.teiid.core.designer.util.FileUtils; import org.teiid.core.designer.util.I18nUtil; import org.teiid.core.designer.util.StringConstants; import org.teiid.designer.common.xsd.XsdHeader; import org.teiid.designer.common.xsd.XsdHeaderReader; import org.teiid.designer.core.ModelEditor; import org.teiid.designer.core.ModelerCore; import org.teiid.designer.core.container.ResourceFinder; import org.teiid.designer.core.extension.EmfModelObjectExtensionAssistant; import org.teiid.designer.core.index.IndexUtil; import org.teiid.designer.core.reader.ZipReader; import org.teiid.designer.core.reader.ZipReaderCallback; import org.teiid.designer.core.resource.EmfResource; import org.teiid.designer.core.resource.MMXmiResource; import org.teiid.designer.core.xmi.XMIHeader; import org.teiid.designer.core.xmi.XMIHeaderReader; import org.teiid.designer.extension.ExtensionPlugin; import org.teiid.designer.extension.registry.ModelExtensionRegistry; import org.teiid.designer.metamodels.core.CoreMetamodelPlugin; import org.teiid.designer.metamodels.core.ModelType; import org.teiid.designer.metamodels.core.extension.ExtensionPackage; import org.teiid.designer.runtime.spi.ITeiidVdb; /** * @since 8.0 */ public class ModelUtil implements StringConstants { /** * Path to vdb.xml located in vdb files */ public static final String META_INF_VDB_XML = "META-INF/vdb.xml"; //$NON-NLS-1$ private static final String I18N_PREFIX = I18nUtil.getPropertyPrefix(ModelUtil.class); public static final String MODEL_CLASS_RELATIONAL = "Relational"; //$NON-NLS-1$ public static final String MODEL_CLASS_XML = XML; public static final String MODEL_CLASS_XML_SCHEMA = "XML Schema (XSD)"; //$NON-NLS-1$ public static final String MODEL_CLASS_WEB_SERVICE = "Web Service"; //$NON-NLS-1$ public static final String MODEL_CLASS_FUNCTION = "Function (Deprecated)"; //$NON-NLS-1$ public static final String MODEL_CLASS_MODEL_EXTENSION = "Model Extension (Deprecated)"; //$NON-NLS-1$ public static final String MODEL_CLASS_UNKNOWN = "Unknown"; //$NON-NLS-1$ public static final String URI_XML_VIEW_MODEL = "http://www.metamatrix.com/metamodels/XmlDocument"; //$NON-NLS-1$ public static final String URI_WEB_SERVICES_VIEW_MODEL = "http://www.metamatrix.com/metamodels/WebService"; //$NON-NLS-1$ public static final String URI_FUNCTION_MODEL = "http://www.metamatrix.com/metamodels/MetaMatrixFunction"; //$NON-NLS-1$ public static final String URI_EXTENSION_MODEL = ExtensionPackage.eNS_URI; public static final String URI_RELATIONAL_MODEL = "http://www.metamatrix.com/metamodels/Relational"; //$NON-NLS-1$ public static final String URI_XML_SCHEMA_MODEL = XSDPackage.eNS_URI; /** * The extension property key for vdb-name */ private static String VDB_NAME_KEY = "core:vdb-name"; //$NON-NLS-1$ private static String LOCKED_NAME_KEY = "core:locked"; //$NON-NLS-1$ private static final String[] EXTENSIONS = new String[] {XML, XMI}; private static XmiHeaderCache cache; /** * Add all IFile instances found within the specified IContainer to the result list * * @param iContainer * @param result * @since 4.3 */ public static void collectModelIFiles( final IContainer iContainer, final Collection<IResource> result ) { if (iContainer != null) { try { IResource[] iResources = iContainer.members(); for (int i = 0; i != iResources.length; ++i) { IResource r = iResources[i]; if (r.exists()) { if (r.getType() == IResource.FILE) { if( ModelUtil.isModelFile(r) || ModelUtil.isXsdFile(r) ) { result.add(r); } } else if (r.getType() == IResource.FOLDER) { collectModelIFiles((IContainer)r, result); } } } } catch (CoreException e) { CoreMetamodelPlugin.Util.log(e); } } } /** * Add all ModelResource instances found within the specified IContainer to the result list * * @param iContainer * @param result * @since 4.3 */ public static void collectModelResources( final IContainer iContainer, final Collection<ModelResource> result ) { if (iContainer != null) { try { IResource[] iResources = iContainer.members(); for (int i = 0; i != iResources.length; ++i) { IResource r = iResources[i]; if (r.exists()) { if (r.getType() == IResource.FILE) { if( ModelUtil.isModelFile(r) || ModelUtil.isXsdFile(r) ) { ModelResource mr = getModelResource((IFile)r, true); if( mr != null ) { result.add(mr); } } } else if (r.getType() == IResource.FOLDER) { collectModelResources((IContainer)r, result); } } } } catch (CoreException e) { CoreMetamodelPlugin.Util.log(e); } } } /** * Add all Resource instances found within the specified IContainer to the result list * * @param iContainer * @param result * @since 4.3 */ public static void collectResources( final IContainer iContainer, final Collection<Resource> result ) { if (iContainer != null) { try { IResource[] iResources = iContainer.members(); for (int i = 0; i != iResources.length; ++i) { IResource r = iResources[i]; if (r.exists()) { if (r.getType() == IResource.FILE) { if( ModelUtil.isModelFile(r) || ModelUtil.isXsdFile(r) ) { ModelResource mr = getModelResource((IFile)r, true); if( mr != null ) { result.add(mr.getEmfResource()); } } } else if (r.getType() == IResource.FOLDER) { collectResources((IContainer)r, result); } } } } catch (CoreException e) { CoreMetamodelPlugin.Util.log(e); } } } /** * Returns the lowest-level workspace container in the specified object's hierarchy, which may be the object itself. The * container can only be determined if the specified object is an {@link EObject} or {@link IResource}. * * @param object The object whose hierarchy is to be searched for a workspace container; may not be null. * @return The lowest-level workspace container in the specified object's hierarchy, or null if the container cannot be * determined. * @since 4.0 */ public static IContainer getContainer( final Object object ) { CoreArgCheck.isNotNull(object); Object obj = object; if (obj instanceof EObject) { final ModelResource resource = ModelerCore.getModelEditor().findModelResource((EObject)obj); if (resource != null) obj = resource.getResource(); } if (obj instanceof IResource && !(obj instanceof IContainer)) obj = ((IResource)obj).getParent(); if (obj instanceof IContainer) { final IContainer ctnr = (IContainer)obj; return (ctnr.isAccessible() ? ctnr : null); } return null; } /** * Returns the file extension portion of this file, or an empty string if there is none. * <p> * The file extension portion is defined as the string following the last period (".") character in the file name. If there is * no period in the file name, the file has no file extension portion. If the name ends in a period, the file extension * portion is the empty string. * </p> * * @param resource * @return the file extension or <code>null</code> * @since 4.3 */ public static String getFileExtension( final File resource ) { return FileUtil.getExtension(resource); } /** * Returns the model for the specified object, which may be the object itself. The model can only be determined if the * specified object is a {@link ModelResource}, {@link EObject}, {@link IFile} or {@link Resource}. * * @param object The object whose hierarchy is to be searched for a model; may not be null. * @return The model for the specified object, or null if the model cannot be determined. * @since 4.0 */ public static ModelResource getModel( final Object object ) throws ModelWorkspaceException { CoreArgCheck.isNotNull(object); if (object instanceof ModelResource) return (ModelResource)object; if (object instanceof EObject) return ModelerCore.getModelEditor().findModelResource((EObject)object); if (object instanceof IFile) return ModelerCore.getModelEditor().findModelResource((IFile)object); if (object instanceof Resource) return ModelerCore.getModelEditor().findModelResource((Resource)object); return null; } public static String getModelClass(final Object object) throws ModelWorkspaceException { CoreArgCheck.isNotNull(object); ModelResource mr = getModel(object); if( mr != null ) { String mmURI = mr.getPrimaryMetamodelUri(); if (mmURI != null) { if (mmURI.equals(URI_RELATIONAL_MODEL)) return MODEL_CLASS_RELATIONAL; if (mmURI.equals(URI_FUNCTION_MODEL)) return MODEL_CLASS_FUNCTION; if (mmURI.equals(URI_EXTENSION_MODEL)) return MODEL_CLASS_MODEL_EXTENSION; if (mmURI.equals(URI_XML_VIEW_MODEL)) return MODEL_CLASS_XML; if (mmURI.equals(URI_WEB_SERVICES_VIEW_MODEL)) return MODEL_CLASS_WEB_SERVICE; if (mmURI.equals(URI_XML_SCHEMA_MODEL)) return MODEL_CLASS_XML_SCHEMA; } } return MODEL_CLASS_UNKNOWN; } /** * Get a ModelResource for a model file. * * @param modelFile * @param forceOpen true if the ModelResource should open in responce to this call, false if it is okay to lazily open the * resource. * @return * @throws ModelWorkspaceException */ public static ModelResource getModelResource( final IFile modelFile, final boolean forceOpen ) throws ModelWorkspaceException { if (modelFile == null) return null; return ModelerCore.getModelEditor().findModelResource(modelFile); } private static void getDependentModelResources( ModelResource modelResource, Collection<ModelResource> resources, Collection<ModelResource> modelsProcessed, boolean includeVirtualModels ) throws ModelWorkspaceException { if (!modelsProcessed.contains(modelResource)) { modelsProcessed.add(modelResource); Collection dependents = getDependentResources(modelResource); for (Iterator i = dependents.iterator(); i.hasNext();) { ModelResource model = (ModelResource)i.next(); if (model.getModelType().getValue() == ModelType.PHYSICAL) { if (!resources.contains(model)) { resources.add(model); } } else if (model.getModelType().getValue() == ModelType.VIRTUAL) { if (includeVirtualModels && !resources.contains(model)) { resources.add(model); } getDependentModelResources(model, resources, modelsProcessed, includeVirtualModels); } } } } public static void getDependentModelResources( ModelResource modelResource, Collection<ModelResource> resources, boolean includeVirtualModels ) throws ModelWorkspaceException { getDependentModelResources(modelResource, resources, new ArrayList(), includeVirtualModels); } /** * Convenience method to obtain a list of ModelResource instances which the input model resource depends upon * * @param resource * @return Collection of ModelResource's * @since 4.2 */ public static Collection getDependentResources( ModelResource resource ) throws ModelWorkspaceException { Collection result = Collections.EMPTY_LIST; IResource theResource = resource.getResource(); // Get the array of resources that this resource depends upon List<IFile> dependents = WorkspaceResourceFinderUtil.getDependentResources(theResource); ModelResource mo = null; for (IFile dependentResource : dependents) { mo = getModelResource(dependentResource, true); if (mo != null) { if (result.isEmpty()) { result = new ArrayList(); } result.add(mo); } } return result; } /** * @param iFile the model file * @param key the property key including ns prefix (i.e. core:vdb-name) * @return the string property value * @throws ModelWorkspaceException if problem finding model resource or finding property value */ public static String getModelAnnotationPropertyValue(final IFile iFile, final String key) throws ModelWorkspaceException { ModelResource mr = getModelResource(iFile, true); if( mr != null ) { ResourceAnnotationHelper helper = new ResourceAnnotationHelper(); return (String)helper.getPropertyValue(mr, key); } return null; } /** * Get a Model Annotation property value * @param modelResource the model resource * @param propertyKey the property key including ns prefix (i.e. core:vdb-name) * @return the string property value * @throws ModelWorkspaceException if problem finding property value */ public static String getModelAnnotationPropertyValue(final ModelResource modelResource, final String propertyKey) throws ModelWorkspaceException { CoreArgCheck.isNotNull(modelResource, "modelResource"); //$NON-NLS-1$ CoreArgCheck.isNotEmpty(propertyKey, "propertyKey"); //$NON-NLS-1$ ResourceAnnotationHelper helper = new ResourceAnnotationHelper(); return (String)helper.getPropertyValue(modelResource, propertyKey); } /** * Set a Model Annotation property value * @param modelResource the model resource * @param propertyKey the property key including ns prefix (i.e. core:vdb-name) * @param propertyValue the property value * @throws ModelWorkspaceException if problem setting property value */ public static void setModelAnnotationPropertyValue( ModelResource modelResource, String propertyKey, String propertyValue ) throws ModelWorkspaceException { CoreArgCheck.isNotNull(modelResource, "modelResource"); //$NON-NLS-1$ CoreArgCheck.isNotEmpty(propertyKey, "propertyKey"); //$NON-NLS-1$ ResourceAnnotationHelper helper = new ResourceAnnotationHelper(); helper.setProperty(modelResource, propertyKey, propertyValue); } /** * Returns the models for the specified objects, which may be the objects themselves. The model can only be determined if the * specified object is a {@link ModelResource}, {@link EObject}, {@link IFile} or {@link Resource}. * * @param objects The list of objects whose hierarchy is to be searched for a model; may not be null. * @return The Collection of models for the specified objects. May be empty if no models can be determined. * @since 4.0 */ public static Collection getModels( final List objects ) throws ModelWorkspaceException { CoreArgCheck.isNotNull(objects); final Collection<Object> modelResourceSet = new HashSet<Object>(); for (final Iterator i = objects.iterator(); i.hasNext();) { final Object nextObj = i.next(); if (nextObj instanceof ModelResource) modelResourceSet.add(nextObj); if (nextObj instanceof EObject) { final Object mr = ModelerCore.getModelEditor().findModelResource((EObject)nextObj); if (mr != null) modelResourceSet.add(mr); } if (nextObj instanceof IFile) { final Object mr = ModelerCore.getModelEditor().findModelResource((IFile)nextObj); if (mr != null) modelResourceSet.add(mr); } if (nextObj instanceof Resource) { final Object mr = ModelerCore.getModelEditor().findModelResource((Resource)nextObj); if (mr != null) modelResourceSet.add(mr); } } return modelResourceSet; } /** * Returns the modifiable model for the specified object, which may be the object itself. The model can only be determined if * the specified object is an {@link EObject} or {@link IFile}. * * @param object The object whose hierarchy is to be searched for a model; may not be null. * @return The modifiable model for the specified object, or null if the model cannot be determined or is not modifiable. * @since 4.0 */ public static ModelResource getModifiableModel( final Object object ) throws ModelWorkspaceException { final ModelResource model = getModel(object); if (model != null && !model.isReadOnly()) return model; return null; } /** * This method currently looks for a feature with a name that case-insensitively matches "name". * @param eObject * * @return feature * */ public static EStructuralFeature getNameFeature(final EObject eObject) { CoreArgCheck.isNotNull(eObject); final EClass eClass = eObject.eClass(); for (Iterator iter = eClass.getEAllStructuralFeatures().iterator(); iter.hasNext();) { final EStructuralFeature feature = (EStructuralFeature)iter.next(); if (ModelEditor.NAME_FEATURE_NAME.equalsIgnoreCase(feature.getName())) { return feature; } } return null; } /** * @param eObject * @return name of the object */ public static String getName( final EObject eObject ) { CoreArgCheck.isNotNull(eObject); final EStructuralFeature nameFeature = getNameFeature(eObject); if (nameFeature == null) { return null; } final Object value = eObject.eGet(nameFeature); return value != null ? value.toString() : null; } public static String getName( final ModelResource modelResource ) { String name = modelResource.getItemName(); try { name = modelResource.getCorrespondingResource().getFullPath().removeFileExtension().lastSegment(); } catch (ModelWorkspaceException e) { ModelerCore.Util.log(e); } return name; } /** * Determines the location of the given {@link IResource}. * It first tries {@link IResource#getRawLocation()} and if * null then tries {@link IResource#getLocation()}. * * @param resource * * @return {@link IPath} of resource location * * @throws CoreException if location cannot be determined */ public static IPath getLocation(final IResource resource) throws CoreException { if (resource == null) { String message = getString("location.nullResource"); //$NON-NLS-1$ IStatus errStatus = new Status(IStatus.ERROR, ModelerCore.PLUGIN_ID, message); throw new CoreException(errStatus); } IPath location = resource.getRawLocation(); if (location == null) location = resource.getLocation(); if (location == null) { String message = getString("location.indeterminateResource", resource.getName()); //$NON-NLS-1$ IStatus errStatus = new Status(IStatus.ERROR, ModelerCore.PLUGIN_ID, message); throw new CoreException(errStatus); } return location; } /** * Method returns a relative path URI value between a baseResourceURI and an importedResourceURI * * @param baseResourceURI * @param importedResourceURI * @return relative URI * @since 5.0 */ public static URI getRelativeLocation( final URI baseResourceURI, final URI importedResourceURI ) { URI uri = importedResourceURI; if (importedResourceURI.isFile()) { final boolean deresolve = (baseResourceURI != null && !baseResourceURI.isRelative() && baseResourceURI.isHierarchical()); if (deresolve && !importedResourceURI.isRelative()) { final URI deresolvedURI = importedResourceURI.deresolve(baseResourceURI, true, true, false); if (deresolvedURI.hasRelativePath()) uri = deresolvedURI; } } return uri; } public static String getRelativePath( final IPath source, final IPath base ) { final StringBuffer upPath = new StringBuffer(); final int baseSegments = base.segmentCount(); final int matchingSegments = source.matchingFirstSegments(base); int upSegments = baseSegments - matchingSegments; final String fileSep = FileSeparatorUtil.getFileSeparator(source.toString()); if (base.getFileExtension() != null) upSegments--; if (upSegments > 0) for (int i = 0; i < upSegments; i++) upPath.append(".." + fileSep);//$NON-NLS-1$ final IPath sourceRelativePath = source.removeFirstSegments(matchingSegments).makeRelative(); return upPath + sourceRelativePath.toString(); } /** * @since 4.0 */ static String getString( final String id ) { return ModelerCore.Util.getString(I18N_PREFIX + id); } /** * @since 5.0 */ private static String getString( final String id, final String arg ) { return ModelerCore.Util.getString(I18N_PREFIX + id, arg); } /** * Assuming the resource is a vdb, read its vdb.xml and pass it to the * given callback, which will process it in its custom manner. * * @param resource * @param callback * * @throws Exception */ public static void readVdbHeader( final File resource, ZipReaderCallback callback) throws Exception { if (resource == null || ! resource.isFile() || ! resource.exists()) return; if (! ModelFileUtil.isVdbArchiveFile(resource)) return; ZipReader reader = new ZipReader(resource); reader.readEntry(META_INF_VDB_XML, callback); } /** * Method returns a VDB project file system path based on a resource within a VDB. Example: * E:\Apps\Designer\workspace\.metadata\.plugins\com.metamatrix.vdb.edit\vdbWorkingFolder\1055014098_111203908 If the * "vdbWorkingFolder" is NOT found, then the method returns NULL. * * @param baseResource * @return * @since 5.0 */ public static IPath getVdbProjectPathURI( final MMXmiResource baseResource ) { if (baseResource.getURI().isFile() && baseResource.getURI().hasAbsolutePath()) { final String[] pathSegments = baseResource.getURI().segments(); final String baseURI = baseResource.getURI().toString(); final String fileSep = FileSeparatorUtil.getFileSeparator(baseURI); String deviceLocation = CoreStringUtil.Constants.EMPTY_STRING; // find vdbWorkingFolder index int vdbFolderIndex = -1; IPath projectPath = null; for (int i = 0; i < pathSegments.length; i++) { if (projectPath == null) { projectPath = new Path(pathSegments[i]); final int index = baseURI.indexOf(pathSegments[i]); // Defect 24918 - Platform may be LINUX/UNIX so the device location may NOT always be available. // So, we do a quick check, and if NOT WINDOWS, just set the default "root" to '/' if (Platform.getOS().equals(Platform.OS_WIN32)) { deviceLocation = baseURI.substring(0, index - 1); if (deviceLocation.startsWith(FILE_COLON)) deviceLocation = deviceLocation.substring(6) + fileSep; } else deviceLocation = File.separator; } else projectPath = projectPath.append(FileUtils.normalizeFileName(pathSegments[i])); if (pathSegments[i].equalsIgnoreCase(ResourceFinder.VDB_WORKING_FOLDER)) { vdbFolderIndex = i; break; } } if (vdbFolderIndex > -1) // increment the index to get to the temp-directory projectPath = projectPath.append(pathSegments[vdbFolderIndex + 1]); // Now final IPath finalPath = new Path(deviceLocation).append(projectPath); return finalPath; } return null; } /** * * @param modelResource the target model resource * @return the vdb name * @throws Exception */ public static String getVdbName(final ModelResource modelResource) throws Exception { if (modelResource != null ) { ModelExtensionRegistry registry = ExtensionPlugin.getInstance().getRegistry(); EmfModelObjectExtensionAssistant assistant = (EmfModelObjectExtensionAssistant)registry.getModelExtensionAssistant("core"); //$NON-NLS-1$ if( assistant != null ) { return assistant.getPropertyValue(modelResource.getModelAnnotation(), "core:vdb-name"); //$NON-NLS-1$ } } return null; } /** * Return the XMIHeader for the specified File or null if the file does not represent a MetaMatrix model file. * * @param resource The file of a metamatrix model file. * @return The XMIHeader for the model file */ public static XMIHeader getXmiHeader( final File resource ) { if (resource != null && resource.isFile() && resource.exists() && resource.canRead()) { // check cache if (cache != null) { final XMIHeader header = cache.getCachedXmiHeader(resource); if (header != null) return header; } try { final XMIHeader header = XMIHeaderReader.readHeader(resource); // add to cache if (cache != null) cache.setXmiHeaderToCache(resource, header); return header; } catch (final TeiidDesignerException e) { CoreModelerPlugin.Util.log(e); } catch (final IllegalArgumentException iae) { // Swallowing this exception because we're doing all three checks that would produce it. // If this exception is caught, it's because the files really were closed/deleted in another thread and this // thread didn't know about it. // Fixes Defect 22117 } } return null; } /** * Return the XMIHeader for the specified IResource or null if the file does not represent a Teiid Designer model file. * * @param resource The IResource of a Teiid Designer model file. * @return The XMIHeader for the model file */ public static XMIHeader getXmiHeader( final IResource resource ) { if (resource != null && resource.getType() == IResource.FILE) { final IPath path = ((IFile)resource).getLocation(); if (path != null) return getXmiHeader(path.toFile()); } return null; } /** * Return the XsdHeader for the specified xsd file or null if the file does not represent a XSD. * * @param resource The file of a Teiid Designer xsd file. * @return The XsdHeader for the model file */ public static XsdHeader getXsdHeader( final File resource ) { if (resource != null && resource.isFile() && resource.exists()) if (ModelFileUtil.isXsdFile(resource)) try { return XsdHeaderReader.readHeader(resource); } catch (final TeiidDesignerException e) { ModelerCore.Util.log(e); } return null; } /** * Return the XsdHeader for the specified IResource or null if the file does not represent an XSD file. * * @param resource The IResource of a XSD file. * @return The XsdHeader for the model file */ public static XsdHeader getXsdHeader( final IResource resource ) { if (resource != null && resource.getType() == IResource.FILE) { final IPath path = ((IFile)resource).getLocation(); if (path != null) return getXsdHeader(path.toFile()); } return null; } private static boolean isIndexFileLastModifiedAfterResourceFile( final ModelResource targetModelResource ) { final File rsrcIndexFile = new File(IndexUtil.INDEX_PATH, IndexUtil.getRuntimeIndexFileName(targetModelResource)); if (!rsrcIndexFile.exists()) return false; final IPath path = ((IFile)targetModelResource.getResource()).getLocation(); final long resourceLastModified = path.toFile().lastModified(); final long indexLastModified = rsrcIndexFile.lastModified(); return (indexLastModified < resourceLastModified); } /** * @param iResource the IResource * @return true if resource is read-only */ public static boolean isIResourceReadOnly( final IResource iResource ) { if(ModelUtil.isLockedSourceObject(iResource)) { return true; } final ResourceAttributes attributes = iResource.getResourceAttributes(); return attributes == null ? false : attributes.isReadOnly(); } /** * Return true if the IPath represents a Teiid Designer model file, * * @param path The file that may be a model file * @return true if it is a has a model file extension */ public static boolean isModelFile( final IPath path ) { final String extension = path.getFileExtension(); return ModelFileUtil.isModelFileExtension(extension, true); } /** * Return true if the IResource represents a Teiid Designer model file, this method also check if the file exists in a project * with model nature. * * @param resource The file that may be a model file * @return true if it is a ModelFile and part of a ModelProject */ public static boolean isModelFile( final IResource resource ) { return isModelFile(resource, true); } /** * Return true if the IResource represents a Teiid Designer model file, this method may also check if the file exists in a * project with model nature. * * @param resource The file that may be a model file * @param projectCheck A boolean to determine to perform 'model part of model project' check. * @return true if it is a ModelFile may/not be part of a ModelProject */ public static boolean isModelFile( final IResource resource, final boolean projectCheck ) { if (projectCheck) if (!isModelProjectResource(resource)) return false; if (resource.getType() == IResource.FILE) { final IPath path = ((IFile)resource).getLocation(); if (path != null) return ModelFileUtil.isModelFile(path.toFile()); } return false; } /** * Return true if the File represents a Teiid Designer model file, this method does not check if the file exists in a project * with model nature. * * @param resource The file that may be a model file * @return true if it is a ModelFile. */ public static boolean isModelFile( final Resource resource ) { if (resource == null) return false; final String extension = resource.getURI().fileExtension(); return ModelFileUtil.isModelFileExtension(extension, true); } /** * Helper method that determines that the given resource is a IFile and exists in a modeling project. */ private static boolean isModelProjectResource( final IResource resource ) { if (resource != null) { final IProject proj = resource.getProject(); if (proj != null && ModelerCore.hasModelNature(proj)) return true; } return false; } /** * Return the virtual model state of the specified model object. * * @param eObject * @return true if model object is in virtual model. */ public static boolean isPhysical( final Object obj ) { if (obj != null && obj instanceof EObject) { final EObject eObject = (EObject)obj; final Resource resource = eObject.eResource(); if (resource instanceof EmfResource) return ModelType.PHYSICAL_LITERAL.equals(((EmfResource)resource).getModelAnnotation().getModelType()); else if (resource == null && eObject.eIsProxy()) { final URI theUri = ((InternalEObject)eObject).eProxyURI().trimFragment(); if (theUri.isFile()) { final File newFile = new File(theUri.toFileString()); final XMIHeader header = getXmiHeader(newFile); if (header != null && ModelType.PHYSICAL_LITERAL.equals(ModelType.get(header.getModelType()))) return true; } } } else if (obj != null && obj instanceof EmfResource) { if( ((EmfResource)obj).getModelAnnotation() == null ) { return false; } return ModelType.PHYSICAL_LITERAL.equals(((EmfResource)obj).getModelAnnotation().getModelType()); } return false; } // /** // * @param iResource the IResource // * @return true if resource is read-only // */ // public static boolean isReadOnly(final IResource iResource) { // if(ModelUtil.isVdbSourceObject(iResource)) { // return true; // } // return ModelUtil.isIResourceReadOnly(iResource); // } /** * @since 4.0 */ public static boolean isValidFolderNameForPackage( final String name ) { return validateFolderName(name).getSeverity() != IStatus.ERROR; } /** * @since 4.0 */ public static boolean isValidModelFileName( final String name ) { return validateModelFileName(name).getSeverity() != IStatus.ERROR; } /** * @since 4.0 */ public static boolean isVdbArchiveFile( final IPath path ) { // Check that the resource has the correct lower-case extension if (path != null && path.getFileExtension() != null) if (ITeiidVdb.VDB_EXTENSION.equals(path.getFileExtension())) return true; return false; } /** * Return true if the IResource represents a Teiid Designer vdb file. * * @param resource The file that may be a vdb file * @return true if it is a vdb File. */ public static boolean isVdbArchiveFile( final IResource resource ) { // Check that the resource has the correct lower-case extension if (ITeiidVdb.VDB_EXTENSION.equals(resource.getFileExtension())) return true; return false; } /** * Return true if the Resource represents a vdb archive file. * * @param resource The file that may be a vdb file * @return true if it is a xsd */ public static boolean isVdbArchiveFile( final Resource resource ) { if (resource != null) { // Check that the resource has the correct lower-case extension final URI uri = resource.getURI(); if (uri != null) { final String fileName = uri.lastSegment(); if (fileName.endsWith(ITeiidVdb.VDB_EXTENSION)) return true; } } return false; } /** * Returns whether or not * @param obj the target object * @return true if the source object is within a vdb source model or is a source model */ public static boolean isVdbSourceObject( final Object obj) { ModelResource mr = null; if( obj instanceof EObject ) { mr = ModelerCore.getModelEditor().findModelResource((EObject)obj); } else if( obj instanceof ModelResource ) { mr = (ModelResource)obj; } else if( obj instanceof IFile ) { try { mr = ModelUtil.getModelResource((IFile)obj, true); } catch (ModelWorkspaceException ex) { // Do nothing } } if( mr != null ) { try { if( !mr.isLoaded() ) { mr.open(new NullProgressMonitor()); } String vdbSourceModelName = ModelUtil.getModelAnnotationPropertyValue((IFile)mr.getUnderlyingResource(), VDB_NAME_KEY); return vdbSourceModelName != null; } catch (ModelWorkspaceException ex) { CoreMetamodelPlugin.Util.log(IStatus.ERROR, ex, ex.getMessage()); } } return false; } /** * Returns whether or not * @param obj the target object * @return true if the source object is within a vdb source model or is a source model */ public static boolean isLockedSourceObject( final Object obj) { ModelResource mr = null; if( obj instanceof EObject ) { mr = ModelerCore.getModelEditor().findModelResource((EObject)obj); } else if( obj instanceof ModelResource ) { mr = (ModelResource)obj; } else if( obj instanceof IFile ) { try { mr = ModelUtil.getModelResource((IFile)obj, true); } catch (ModelWorkspaceException ex) { // Do nothing } } if( mr != null && mr.isLoaded()) { try { String lockedValue = ModelUtil.getModelAnnotationPropertyValue((IFile)mr.getUnderlyingResource(), LOCKED_NAME_KEY); return lockedValue != null; } catch (ModelWorkspaceException ex) { CoreMetamodelPlugin.Util.log(IStatus.ERROR, ex, ex.getMessage()); } } return false; } /** * Return the virtual model state of the specified model object. * * @param eObject * @return true if model object is in virtual model. */ public static boolean isVirtual( final Object obj ) { if (obj != null) { if (obj instanceof EObject) { final EObject eObject = (EObject)obj; final Resource resource = eObject.eResource(); if (resource instanceof EmfResource) return ModelType.VIRTUAL_LITERAL.equals(((EmfResource)resource).getModelAnnotation().getModelType()); else if (resource == null && eObject.eIsProxy()) { final URI theUri = ((InternalEObject)eObject).eProxyURI().trimFragment(); if (theUri.isFile()) { final File newFile = new File(theUri.toFileString()); final XMIHeader header = getXmiHeader(newFile); if (header != null && ModelType.VIRTUAL_LITERAL.equals(ModelType.get(header.getModelType()))) return true; } } } else if (obj instanceof EmfResource) { return ModelType.VIRTUAL_LITERAL.equals(((EmfResource)obj).getModelAnnotation().getModelType()); } } return false; } /** * Return true if the IResource represents a Teiid Designer xmi model file. * * @param resource The file that may be a Teiid Designer xmi model file * @return true if it is a Teiid Designer xmi model */ public static boolean isXmiFile( final File resource ) { // Check that the resource has the correct lower-case extension if (XMI.equals(getFileExtension(resource))) { // If the file does not yet exist then the only thing // we can do is to check the name and extension. if (resource != null && !resource.exists()) return true; final XMIHeader header = getXmiHeader(resource); // If the header is not null then we know the file is, at least, // a well formed xml document. if (header != null) { // If the XMI version for the header is not null, then return // false if the file represents an older 1.X model file if (header.getXmiVersion() != null && header.getXmiVersion().startsWith("1.")) return false; //$NON-NLS-1$ // If the UUID for the header is not null, then the file is a // Teiid Designer model file containing a ModelAnnotation element. if (header.getUUID() != null) return true; } } return false; } /** * Return true if the IResource represents a Teiid Designer xmi model file. * * @param resource The file that may be a Teiid Designer xmi model file * @return true if it is a Teiid Designer xmi model */ public static boolean isXmiFile( final IResource resource ) { // Check that the resource has the correct lower-case extension if (XMI.equals(resource.getFileExtension())) { final XMIHeader header = getXmiHeader(resource); // If the header is not null then we know the file is, at least, // a well formed xml document. if (header != null) { // If the XMI version for the header is not null, then return // false if the file represents an older 1.X model file if (header.getXmiVersion() != null && header.getXmiVersion().startsWith("1.")) return false; //$NON-NLS-1$ // If the UUID for the header is not null, then the file is a // Teiid Designer model file containing a ModelAnnotation element. if (header.getUUID() != null) return true; } } return false; } /** * Return true if the Resource represents a Teiid Designer xmi model file. * * @param resource The file that may be a Teiid Designer xmi model file * @return true if it is a Teiid Designer xmi model */ public static boolean isXmiFile( final Resource resource ) { if (resource != null) if (resource instanceof EmfResource) return true; return false; } // Refactored/moved from ModelUtilities in modeler.ui /** * Return true if the IPath represents a xsd file. * * @param path The path to a file that may be a xsd file * @return true if it is a xsd */ public static boolean isXsdFile( final IPath path ) { // Check that the resource has the correct lower-case extension if (XSD.equals(path.getFileExtension())) return true; return false; } /** * Return true if the IResource represents a xsd file. * * @param resource The file that may be a xsd file * @return true if it is a xsd */ public static boolean isXsdFile( final IResource resource ) { // Check that the resource has the correct lower-case extension if (XSD.equals(resource.getFileExtension())) return true; return false; } /** * Return true if the Resource represents a xsd file. * * @param resource The file that may be a xsd file * @return true if it is a xsd */ public static boolean isXsdFile( final Resource resource ) { if (resource != null) { if (resource instanceof XSDResourceImpl) return true; // Check that the resource has the correct lower-case extension final URI uri = resource.getURI(); if (uri != null) { final String fileName = uri.lastSegment(); if (fileName.endsWith(XSD)) return true; } } return false; } public static boolean isXsdFile( final File file ) { if (file != null) { // Check that the resource has the correct lower-case extension final String fileName = file.getName(); if (fileName != null) { if (fileName.endsWith(XSD)) return true; } } return false; } /** * @param obj the target object * @return the uuid string * @throws ModelWorkspaceException if issues finding <code>ModelResource</code> */ public static String getUuidString(Object obj) { ModelResource mr = null; String uuid = null; try { if (obj instanceof ModelResource) { mr = (ModelResource)obj; } else if (obj instanceof IFile) { mr = ModelUtil.getModelResource((IFile)obj, false); } else if (obj instanceof Resource) { mr = ModelerCore.getModelEditor().findModelResource((Resource)obj); } if( mr != null ) { uuid = mr.getUuid(); } } catch (ModelWorkspaceException ex) { ModelerCore.Util.log(IStatus.ERROR, ex, ex.getMessage()); } return uuid; } /** * @since 4.0 */ private static IStatus newErrorStatus( final String msg ) { return new Status(IStatus.ERROR, ModelerCore.PLUGIN_ID, -1, msg, null); } /** * Method returns a boolean value (true or false) for whether or not a IFile requires validation. The model may be have been * saved with auto-build off. * * @param targetModelResource * @return true if requires validation, false if not. * @since 4.2 */ public static boolean requiresValidation( final IFile file ) { ModelResource mr = null; // Find Model Resource try { mr = getModelResource(file, false); } catch (final ModelWorkspaceException err) { final String message = getString(Constants.MODEL_RESOURCE_NOT_FOUND_MSG_KEY, file.toString()); ModelerCore.Util.log(IStatus.ERROR, err, message); } if (mr != null) return requiresValidation(mr); // If we ever get here it's an error, so let's return false; } /** * Method returns a boolean value (true or false) for whether or not a model resource requires validation. The model may be * have been saved with auto-build off. * * @param targetModelResource * @return true if requires validation, false if not. * @since 4.2 */ public static boolean requiresValidation( final ModelResource targetModelResource ) { if (targetModelResource == null) return false; // TODO: (BML 12/14/04) This check is currently required because XSD files are always tagged with a NOT_INDEXED during // the build process because they need to be unloaded and reloaded. Sucks, but that's the way it is. // There will be another defect defining that and pointing to this place to remove the next two lines!! if (ModelUtil.isXsdFile(targetModelResource.getResource())) return false; // sz - added the code to fix defect 15948. final boolean isIndexModified = isIndexFileLastModifiedAfterResourceFile(targetModelResource); if ((targetModelResource.getIndexType() == ModelResource.NOT_INDEXED) || isIndexModified) return true; return false; } public static boolean setIResourceReadOnly( final IResource iResource, final boolean isReadOnly ) { final ResourceAttributes attributes = iResource.getResourceAttributes(); if (attributes == null) return false; attributes.setReadOnly(isReadOnly); return true; } public static void setModelWorkspaceManagerInitialized() { cache = ModelWorkspaceManager.getModelWorkspaceManager(); } /** * @since 4.0 */ public static IStatus validateFolderName( final String name ) { if (name == null) return newErrorStatus(ModelerCore.Util.getString("ModelUtil.folder_must_have_a_non-null_name")); //$NON-NLS-1$ if (name.trim().length() == 0) return newErrorStatus(ModelerCore.Util.getString("ModelUtil.folder_must_have_a_non-empty_name")); //$NON-NLS-1$ // Ensure the file name is a valid file name return validateName(name, IResource.FOLDER); } /** * @since 4.0 */ public static IStatus validateModelFileName( final String name ) { if (name == null) return newErrorStatus(ModelerCore.Util.getString("ModelUtil.model_file_name_may_not_be_null")); //$NON-NLS-1$ if (name.trim().length() == 0) return newErrorStatus(ModelerCore.Util.getString("ModelUtil.model_file_name_may_not_be_zero_length")); //$NON-NLS-1$ boolean validExtension = false; // Try exact match (likely) for (final String element : EXTENSIONS) if (name.endsWith(element)) { validExtension = true; break; } if (!validExtension) return newErrorStatus(ModelerCore.Util.getString("ModelUtil.model_file_name_does_not_have_a_valid_extension")); //$NON-NLS-1$ // Ensure the file name is a valid file name return validateName(name, IResource.FILE); } /** * This is a re-implementation of {@link IWorkspace#validateName(java.lang.String, int)}, which only works if inside Eclipse. * * @see IWorkspace#validateName * @since 4.0 */ private static IStatus validateName( final String segment, final int type ) { /* segment must not begin or end with a whitespace */ if (Character.isWhitespace(segment.charAt(0)) || Character.isWhitespace(segment.charAt(segment.length() - 1))) { final String message = ModelerCore.Util.getString("ModelUtil.resources.invalidWhitespace", segment); //$NON-NLS-1$ return newErrorStatus(message); } /* segment must not end with a dot */ if (segment.endsWith(".")) { //$NON-NLS-1$ final String message = ModelerCore.Util.getString("ModelUtil.resources.invalidDot", segment); //$NON-NLS-1$ return newErrorStatus(message); } return ModelStatusImpl.VERIFIED_OK; } /** * Prevents instantiation outside of this class. * * @since 4.0 */ private ModelUtil() { } public static interface Constants { String MODEL_NOT_PHYSICAL_MESSAGE = getString("modelNotPhysicalMessage"); //$NON-NLS-1$ String MODEL_RESOURCE_NOT_FOUND_MSG_KEY = "modelResourceNotFoundMessageKey"; //$NON-NLS-1$ } public interface XmiHeaderCache { XMIHeader getCachedXmiHeader( File resource ); void setXmiHeaderToCache( File resource, XMIHeader header ); } }