/*
* 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.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.zip.Checksum;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.xsd.XSDPackage;
import org.eclipse.xsd.XSDSchema;
import org.eclipse.xsd.util.XSDResourceImpl;
import org.teiid.core.designer.TeiidDesignerException;
import org.teiid.core.designer.util.ChecksumUtil;
import org.teiid.core.designer.util.CoreArgCheck;
import org.teiid.core.designer.util.CoreStringUtil;
import org.teiid.designer.common.xmi.ModelImportInfo;
import org.teiid.designer.common.xmi.XMIHeader;
import org.teiid.designer.common.xmi.XMIHeaderReader;
import org.teiid.designer.common.xsd.XsdHeader;
import org.teiid.designer.common.xsd.XsdHeaderReader;
import org.teiid.designer.core.ModelerCore;
import org.teiid.designer.core.container.DuplicateResourceException;
import org.teiid.designer.core.metamodel.MetamodelDescriptor;
import org.teiid.designer.core.resource.EmfResource;
import org.teiid.designer.core.util.ModelContents;
import org.teiid.designer.metamodels.core.CoreFactory;
import org.teiid.designer.metamodels.core.ModelAnnotation;
import org.teiid.designer.metamodels.core.ModelImport;
import org.teiid.designer.metamodels.core.ModelType;
/**
* ModelResourceImpl
*
* @since 8.0
*/
public class ModelResourceImpl extends OpenableImpl implements ModelResource {
private int indexType;
private XMIHeader xmiHeader;
private XsdHeader xsdHeader;
private ModelType mdlType = null;
private IStatus errors = null;
private long checkSumForIndexType = 0;
private long fileSizeForIndexType = 0;
/**
* Constructor needed for test cases.
*/
ModelResourceImpl() {
super(MODEL_RESOURCE, null, null);
this.xmiHeader = null;
this.xsdHeader = null;
this.setIndexType(NOT_INDEXED);
ModelWorkspaceManager.getModelWorkspaceManager().setIndexType(NOT_INDEXED);
}
/**
* Construct an instance of ModelProjectImpl.
*
* @since 4.0
*/
public ModelResourceImpl( final ModelWorkspaceItem parent,
final String name ) {
this(parent, name, true);
}
/**
* Construct an instance of ModelProjectImpl. Added boolean for ability to create non-pde tests
*
* @since 4.0
*/
ModelResourceImpl( final ModelWorkspaceItem parent,
final String name,
boolean createEmfResource ) {
super(MODEL_RESOURCE, parent, name);
if (createEmfResource) {
try {
IResource iResource = getResource();
IPath path = iResource.getLocation();
final URI uri = URI.createFileURI(path.toOSString());
ResourceSet resourceSet = super.getBufferManager().getResourceSetFinder().getResourceSet(iResource);
if (resourceSet.getResource(uri, false) == null) {
resourceSet.createResource(uri);
}
} catch (DuplicateResourceException dre) {
ModelerCore.Util.log(dre);
} catch (ModelWorkspaceException mwe) {
ModelerCore.Util.log(mwe);
}
}
}
/* (non-Javadoc)
* @see org.teiid.designer.core.workspace.OpenableImpl#createItemInfo()
*/
@Override
protected OpenableModelWorkspaceItemInfo createItemInfo() {
return new ModelResourceInfo();
}
/**
* Return true if an open buffer exists for this ModelResource
*/
@Override
public boolean isLoaded() {
return getBufferManager().getOpenBuffer(this) != null;
}
/**
* @see org.teiid.designer.core.workspace.ModelResource#hasErrors()
* @since 4.2
*/
@Override
public boolean hasErrors() {
if (this.errors == null) {
try {
getBuffer(); // may record errors
} catch (ModelWorkspaceException err) {
final Throwable nested = err.getException();
if (!(nested instanceof DuplicateResourceException)) {
ModelerCore.Util.log(err);
}
}
}
if (this.errors == null || this.errors.isOK()) {
return false;
}
return true;
}
/**
* @see org.teiid.designer.core.workspace.ModelResource#getErrors()
* @since 4.2
*/
@Override
public IStatus getErrors() {
try {
final ModelBuffer buffer = getBuffer();
if (buffer != null) {
return buffer.getErrors();
}
} catch (ModelWorkspaceException err) {
final Throwable nested = err.getException();
if (nested instanceof DuplicateResourceException) {
return this.errors;
}
ModelerCore.Util.log(err);
}
return new Status(IStatus.OK, ModelerCore.PLUGIN_ID, 0, "", null); //$NON-NLS-1$
}
/**
* Return true if the ModelResource represents an XSD Resource
*
* @see org.teiid.designer.core.workspace.ModelResource#isXsd()
*/
@Override
public boolean isXsd() {
return ModelUtil.isXsdFile(getResource());
}
/**
* Returns the value of the '<em><b>Target Namespace</b></em>' attribute if the ModelResource represents an XSD resource
* otherwise null is returned.
*
* @see org.teiid.designer.core.workspace.ModelResource#getTargetNamespace()
*/
@Override
public String getTargetNamespace() throws ModelWorkspaceException {
String targetNamespace = null;
// If the model resource has not been opened then retrieve the
// description information by reading the XMI header
if (!this.isResourceOpenAndLoaded()) {
final XsdHeader header = this.getXsdHeader();
if (header != null) {
targetNamespace = header.getTargetNamespaceURI();
}
}
// The model resource is already open in the workspace so look for
// the model annotation node
else {
final Resource resource = this.getEmfResource();
if (resource instanceof XSDResourceImpl) {
final XSDSchema xsdSchema = ((XSDResourceImpl)resource).getSchema();
if (xsdSchema != null) {
targetNamespace = xsdSchema.getTargetNamespace();
}
}
}
return targetNamespace;
}
/**
* @see org.teiid.designer.core.workspace.ModelResource#unload()
*/
@Override
public void unload() {
final ModelBuffer modelBuffer = getBufferManager().getOpenBuffer(this);
if (modelBuffer != null) {
closeBuffer(null);
// throw out the current buffer and cause the creation of a new one ...
ModelWorkspaceManager.getModelWorkspaceManager().removeInfo(this);
// modelBuffer.unload();
this.xmiHeader = null;
this.xsdHeader = null;
this.mdlType = null;
}
}
/* (non-Javadoc)
* @See org.teiid.designer.core.workspace.ModelResource#getIndexType()
*/
@Override
public int getIndexType() {
return this.indexType;
}
/* (non-Javadoc)
* @See org.teiid.designer.core.workspace.ModelResource#refreshIndexType()
*/
@Override
public void refreshIndexType() {
try {
final ModelBuffer buf = getBuffer();
if (buf != null) {
IResource iResource = getResource();
if (iResource instanceof IFile) {
if (this.indexType == ModelResource.NOT_INDEXED) {
return;
}
// Compare the file sizes ...
boolean fileSizeDifference = false;
final IPath rawLocation = ModelUtil.getLocation(iResource);
if (rawLocation != null) {
final File rawFile = new File(rawLocation.toString());
if (rawFile.exists()) {
long fileSize = rawFile.length();
if (fileSize != this.fileSizeForIndexType) {
this.fileSizeForIndexType = fileSize;
fileSizeDifference = true;
}
}
}
// Compare checksum sizes
boolean checksumDifference = false;
InputStream stream = null;
try {
stream = ((IFile)iResource).getContents();
final Checksum checksum = ChecksumUtil.computeChecksum(stream);
final long checksumValue = checksum.getValue();
if (checksumValue != this.checkSumForIndexType) {
this.checkSumForIndexType = checksumValue;
checksumDifference = true;
}
} catch (Exception e) {
// System.out.println("eeee> Marking ModelResource as NOT_INDEXED "+this.getResource().getFullPath());
this.indexType = ModelResource.NOT_INDEXED;
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException ignore) {
}
}
}
if (fileSizeDifference || checksumDifference) {
// System.out.println("====> Marking ModelResource as NOT_INDEXED "+this.getResource().getFullPath());
this.indexType = ModelResource.NOT_INDEXED;
}
}
}
} catch (Exception e) {
// ModelerCore.Util.log(err); // okay to eat, since no buffer, nothing to unload/reload?
}
}
/* (non-Javadoc)
* @See org.teiid.designer.core.workspace.ModelResource#setIndexType(int)
*/
@Override
public void setIndexType( int indexType ) {
// if (indexType == ModelResource.NOT_INDEXED) {
// System.out.println("----> Marking ModelResource as NOT_INDEXED "+this.getResource().getFullPath());
// }
this.indexType = indexType;
}
/**
* @see org.teiid.designer.core.workspace.ModelWorkspaceItem
*/
@Override
public boolean isReadOnly() {
if (this.isLoaded() && this.hasErrors()) {
// If the model has errors, then consider as read only to turn off some functionality.
// There are never errors if not opened ...
return true;
}
if( this.isLoaded() && ModelUtil.isLockedSourceObject(this)) {
return true;
}
return ModelUtil.isIResourceReadOnly(getResource());
}
/**
* Returns true if this represents a source element. Openable source elements have an associated buffer created when they are
* opened.
*/
@Override
protected boolean isSourceElement() {
return true;
}
/* (non-Javadoc)
* @see org.teiid.designer.core.OpenableImpl#generateInfos(org.teiid.designer.core.OpenableModelWorkspaceItemInfo, org.eclipse.core.runtime.IProgressMonitor, java.util.Map, org.eclipse.core.resources.IResource)
*/
@Override
protected boolean generateInfos( final OpenableModelWorkspaceItemInfo info,
final IProgressMonitor pm,
final IResource underlyingResource ) throws ModelWorkspaceException {
boolean validInfo = false;
try {
// put the info now, because getting the contents requires it
ModelWorkspaceManager.getModelWorkspaceManager().putInfo(this, info);
// generate structure
validInfo = this.updateModelContents();
} finally {
if (!validInfo) {
ModelWorkspaceManager.getModelWorkspaceManager().removeInfo(this);
}
}
return validInfo;
}
/* (non-Javadoc)
* @See org.teiid.designer.core.ModelResource#getEObjects()
*/
@Override
public List getEObjects() throws ModelWorkspaceException {
// They want the objects, so force the buffer to be loaded ...
final ModelBufferImpl buffer = (ModelBufferImpl)super.getBuffer();
return (buffer.getModelContents() != null ? buffer.getModelContents().getEObjects() : Collections.EMPTY_LIST);
}
/* (non-Javadoc)
* @See org.teiid.designer.core.ModelResource#getEObjects()
*/
@Override
public List getAllRootEObjects() throws ModelWorkspaceException {
// They want the objects, so force the buffer to be loaded ...
final ModelBufferImpl buffer = (ModelBufferImpl)super.getBuffer();
return (buffer.getModelContents() != null ? buffer.getModelContents().getAllRootEObjects() : Collections.EMPTY_LIST);
}
/* (non-Javadoc)
* @See org.teiid.designer.core.ModelResource#getEmfResource()
*/
@Override
public synchronized Resource getEmfResource() throws ModelWorkspaceException {
final Resource resource = super.getBuffer().getEmfResource();
CoreArgCheck.isNotNull(resource);
return resource;
}
/* (non-Javadoc)
* @See org.teiid.designer.core.ModelWorkspaceItem#getResource()
*/
@Override
public IResource getResource() {
final ModelWorkspaceItem parent = this.getParent();
if (parent == null) {
return null;
}
final IContainer parentResource = (IContainer)parent.getResource();
final IPath path = new Path(this.getItemName());
return parentResource.getFile(path);
}
/* (non-Javadoc)
* @See org.teiid.designer.core.ModelWorkspaceItem#getPath()
*/
@Override
public IPath getPath() {
final ModelWorkspaceItem parent = this.getParent();
if (parent == null) {
return null;
}
return parent.getPath().append(this.getItemName());
}
/* (non-Javadoc)
* @see org.teiid.designer.core.workspace.OpenableImpl#hasBuffer()
*/
@Override
protected boolean hasBuffer() {
return true;
}
/* (non-Javadoc)
* @see org.teiid.designer.core.workspace.OpenableImpl#openBuffer(org.eclipse.core.runtime.IProgressMonitor)
*/
@Override
protected ModelBuffer openBuffer( final IProgressMonitor pm ) throws ModelWorkspaceException {
this.opening = true;
ModelBuffer buffer = null;
try {
// create buffer
ModelBufferManager bufManager = getBufferManager();
buffer = bufManager.createBuffer(this);
if (buffer == null) return null;
// Open the buffer
if (buffer instanceof ModelBufferImpl) {
final ModelBufferImpl theBuffer = (ModelBufferImpl)buffer;
try {
theBuffer.open(pm);
} catch (DuplicateResourceException err) {
throw new ModelWorkspaceException(err, err.getMessage());
} finally {
this.errors = theBuffer.getErrors();
}
}
// add buffer to buffer cache
bufManager.addBuffer(buffer);
} finally {
this.opening = false;
}
return buffer;
}
/**
* A model resource has a corresponding resource unless it is contained in a jar.
*
* @see ModelWorkspaceItem#getCorrespondingResource()
*/
@Override
public IResource getCorrespondingResource() {
return getUnderlyingResource();
}
/* (non-Javadoc)
* @See org.teiid.designer.core.workspace.ModelWorkspaceItem#getUnderlyingResource()
*/
@Override
public IResource getUnderlyingResource() {
return getResource();
}
/* (non-Javadoc)
* @See org.teiid.designer.core.workspace.ModelResource#getModelDiagramContainer()
*/
@Override
public ModelDiagrams getModelDiagrams() throws ModelWorkspaceException {
return (ModelDiagrams)this.getFirstChildrenOfType(DIAGRAMS);
}
/* (non-Javadoc)
* @See org.teiid.designer.core.workspace.ModelResource#getModelTransformations()
*/
@Override
public ModelTransformations getModelTransformations() throws ModelWorkspaceException {
return (ModelTransformations)this.getFirstChildrenOfType(TRANSFORMATIONS);
}
/* (non-Javadoc)
* @See org.teiid.designer.core.workspace.ModelResource#getModelTransformations()
*/
@Override
public ModelObjectAnnotations getAnnotations() throws ModelWorkspaceException {
return (ModelObjectAnnotations)this.getFirstChildrenOfType(ANNOTATIONS);
}
/**
* @see org.teiid.designer.core.workspace.ModelResource#getModelMappingClassSets()
*/
@Override
public ModelMappingClassSets getModelMappingClassSets() throws ModelWorkspaceException {
return (ModelMappingClassSets)this.getFirstChildrenOfType(MAPPING_CLASS_SETS);
}
/**
* @see org.teiid.designer.core.workspace.ModelResource#getModelType()
*/
@Override
public ModelType getModelType() throws ModelWorkspaceException {
if (this.mdlType != null) {
return this.mdlType;
}
// If the model resource has not been opened then retrieve the
// model type information by reading the XMI header
if (!this.isResourceOpenAndLoaded()) {
final XMIHeader header = this.getXmiHeader();
if (header != null && header.getModelType() != null) {
this.mdlType = ModelType.get(header.getModelType());
}
}
// The model resource is already open in the workspace so look for
// the model annotation node
else {
final ModelAnnotation annotation = this.getModelAnnotation();
this.mdlType = (annotation != null ? annotation.getModelType() : null);
if (this.mdlType == ModelType.UNKNOWN_LITERAL) {
this.mdlType = null; // don't cache ...
}
}
// If the model type is unknown but this model is an XSD resource ...
if (this.mdlType == null && this.isXsd()) {
this.mdlType = ModelType.TYPE_LITERAL;
}
return (mdlType != null ? mdlType : ModelType.PHYSICAL_LITERAL);
}
/**
* @since 4.2
*/
public void setModelType( final ModelType type ) {
this.mdlType = type;
}
/**
* @see org.teiid.designer.core.workspace.ModelResource#getDescription()
*/
@Override
public String getDescription() throws ModelWorkspaceException {
String description = null;
// If the model resource has not been opened then retrieve the
// description information by reading the XMI header
if (!this.isResourceOpenAndLoaded()) {
final XMIHeader header = this.getXmiHeader();
if (header != null) {
description = header.getDescription();
}
}
// The model resource is already open in the workspace so look for
// the model annotation node
else {
final ModelAnnotation annotation = this.getModelAnnotation();
description = (annotation != null ? annotation.getDescription() : null);
}
return description;
}
/**
* @see org.teiid.designer.core.workspace.ModelResource#getUuid()
*/
@Override
public String getUuid() throws ModelWorkspaceException {
String uuidString = null;
// If the model resource has not been opened then retrieve the
// description information by reading the XMI header
if (!this.isResourceOpenAndLoaded()) {
final XMIHeader header = this.getXmiHeader();
if (header != null) {
uuidString = header.getUUID();
}
}
// The model resource is already open in the workspace so look for
// the model annotation node
else {
final ModelAnnotation annotation = this.getModelAnnotation();
if (annotation != null) {
String uuid = ModelerCore.getObjectIdString(annotation);
if (uuid != null) {
return uuid;
}
}
}
return uuidString;
}
@Override
public String getPrimaryMetamodelUri() throws ModelWorkspaceException {
String uriString = null;
// If the model resource has not been opened then retrieve the
// description information by reading the XMI header
if (!this.isResourceOpenAndLoaded()) {
final XMIHeader header = this.getXmiHeader();
if (header != null) {
uriString = header.getPrimaryMetamodelURI();
}
}
// The model resource is already open in the workspace so look for
// the model annotation node
else {
final ModelAnnotation annotation = this.getModelAnnotation();
if (annotation != null) {
uriString = annotation.getPrimaryMetamodelUri();
}
}
return uriString;
}
/* (non-Javadoc)
* @See org.teiid.designer.core.workspace.ModelResource#getModelAnnotation()
*/
@Override
public synchronized ModelAnnotation getModelAnnotation() throws ModelWorkspaceException {
// This is either loaded with no errors or unloaded ...
final ModelBufferImpl buffer = (ModelBufferImpl)getBufferHack();
final ModelContents contents = buffer.getModelContents();
return (contents != null ? contents.getModelAnnotation() : null);
}
/**
* Convenience method that returns the specific type of info for a ModelResource.
*/
protected ModelResourceInfo getModelResourceInfo() throws ModelWorkspaceException {
return (ModelResourceInfo)getItemInfo();
}
/**
* Reset the collection of package fragment roots (local ones) - only if opened. Need to check *all* package fragment roots in
* order to reset NameLookup
*
* @since 4.0
*/
public boolean updateModelContents() throws ModelWorkspaceException {
if (this.isOpen()) {
boolean failed = false;
try {
ModelResourceInfo info = getModelResourceInfo();
info.setChildren(computeModelContents());
return true;
} catch (ModelWorkspaceException e) {
failed = true;
throw e;
} catch (RuntimeException e) {
failed = true;
throw e;
} finally {
if (failed) {
try {
close(); // could not do better
} catch (ModelWorkspaceException ex) {
}
}
}
}
return false;
}
public ModelWorkspaceItem[] computeModelContents() {
if (ModelUtil.isXsdFile(this.getCorrespondingResource())) {
return new ModelWorkspaceItem[] {};
}
// Create a ModelDiagrams ...
final ModelDiagrams diagramContainer = new ModelDiagramsImpl(this);
// Create a ModelTransformations ...
final ModelTransformations transformationContainer = new ModelTransformationsImpl(this);
// Create a ModelAnnotations ...
final ModelObjectAnnotations annotationContainer = new ModelObjectAnnotationsImpl(this);
// Create a ModelMappingClassSets ...
final ModelMappingClassSets mcSets = new ModelMappingClassSetsImpl(this);
// Return the children
return new ModelWorkspaceItem[] {diagramContainer, transformationContainer, annotationContainer, mcSets};
}
/**
* @see org.teiid.designer.core.workspace.ModelResource#getPrimaryMetamodelDescriptor()
*/
@Override
public MetamodelDescriptor getPrimaryMetamodelDescriptor() throws ModelWorkspaceException {
String primaryMetamodelUri = null;
// defect 19183 - prevent undo stack filling when selecting XSD models.
// ... mainly by checking XSDness right away, instead of after pulling
// the header.
if (ModelUtil.isXsdFile(getResource())) {
primaryMetamodelUri = XSDPackage.eNS_URI;
}
// If the model resource has not been opened then retrieve the
// metamodel information by reading the XMI header
else if (!this.isResourceOpenAndLoaded()) {
final XMIHeader header = this.getXmiHeader();
if (header != null) {
primaryMetamodelUri = header.getPrimaryMetamodelURI();
}
}
// The model resource is already open in the workspace so look for
// the model annotation root node
else {
final ModelAnnotation annotation = this.getModelAnnotation();
primaryMetamodelUri = (annotation != null ? annotation.getPrimaryMetamodelUri() : null);
}
if (primaryMetamodelUri == null) {
return null; // unknown metamodel
}
// MyDefect : 18566 just for reference.
// Look up the descriptor in the metamodels ...
final MetamodelDescriptor descriptor = ModelerCore.getMetamodelRegistry().getMetamodelDescriptor(primaryMetamodelUri);
// Log an error if there is no metamodel with this primary metamodel URI. There may be
// an inconsistency between the metamodel extenion URIs and the primary metamodel URI
// in the resource.
if (descriptor == null) {
final StringBuffer sb = new StringBuffer();
final MetamodelDescriptor[] descriptors = ModelerCore.getMetamodelRegistry().getMetamodelDescriptors();
for (int i = 0; i < descriptors.length; i++) {
final MetamodelDescriptor mmd = descriptors[i];
if (mmd.isPrimary() && !CoreStringUtil.isEmpty(mmd.getNamespaceURI())) {
sb.append(mmd.getNamespaceURI());
sb.append(CoreStringUtil.Constants.SPACE);
}
} // for
final Object[] params = new Object[] {primaryMetamodelUri, sb.toString()};
final String msg = ModelerCore.Util.getString("ModelResourceImpl.no_metamodel_found_for_primary_metamodel_URI", params); //$NON-NLS-1$
ModelerCore.Util.log(IStatus.ERROR, msg);
}
return descriptor;
}
/**
* @see org.teiid.designer.core.workspace.ModelResource#getAllMetamodelDescriptors()
*/
@Override
public List getAllMetamodelDescriptors() throws ModelWorkspaceException {
// If the model resource has not been opened then retrieve the
// metamodel information by reading the XMI header
if (!this.isResourceOpenAndLoaded()) {
final XMIHeader header = this.getXmiHeader();
if (header != null) {
final String primaryMetamodelUri = header.getPrimaryMetamodelURI();
final String[] namespaceURIs = header.getNamespaceURIs();
final List result = new ArrayList(namespaceURIs.length);
for (int i = 0; i < namespaceURIs.length; i++) {
final String nsUri = namespaceURIs[i];
final MetamodelDescriptor desc = ModelerCore.getMetamodelRegistry().getMetamodelDescriptor(nsUri);
if (desc != null) {
if (nsUri.equals(primaryMetamodelUri)) {
result.add(0, desc);
} else {
result.add(desc);
}
}
}
return result;
}
}
// The model resource is already open in the workspace so look for
// namespace URIs in the model annotation node
else {
final Resource resource = this.getEmfResource();
if (resource instanceof EmfResource) {
// Get the primary metamodel ...
final ModelAnnotation annotation = this.getModelAnnotation();
final String primaryMetamodelUri = (annotation != null ? annotation.getPrimaryMetamodelUri() : null);
final List result = new ArrayList(9);
final List nsPrefixToUri = ((EmfResource)resource).getNamespacePrefixToUris();
final Iterator iter = nsPrefixToUri.iterator();
while (iter.hasNext()) {
final String nsUri = (String)iter.next();
// Look up the descriptor in the metamodels ...
final MetamodelDescriptor desc = ModelerCore.getMetamodelRegistry().getMetamodelDescriptor(nsUri);
if (desc != null) {
if (nsUri.equals(primaryMetamodelUri)) {
result.add(0, desc);
} else {
result.add(desc);
}
}
}
return result;
}
}
return Collections.EMPTY_LIST;
}
/**
* @see org.teiid.designer.core.workspace.ModelResource#getModelImports()
*/
@Override
public List getModelImports() throws ModelWorkspaceException {
// If the model resource has not been opened then retrieve the
// model import information by reading the XMI header
if (!this.isResourceOpenAndLoaded()) {
final XMIHeader header = this.getXmiHeader();
if (header != null) {
ModelImportInfo[] infos = header.getModelImportInfos();
final List result = new ArrayList(infos.length);
for (int i = 0; i < infos.length; i++) {
final ModelImport modelImport = CoreFactory.eINSTANCE.createModelImport();
modelImport.setModelType(ModelType.get(infos[i].getModelType()));
modelImport.setName(infos[i].getName());
modelImport.setPrimaryMetamodelUri(infos[i].getPrimaryMetamodelURI());
modelImport.setUuid(infos[i].getUUID());
String location = infos[i].getLocation();
String path = infos[i].getPath();
if (!CoreStringUtil.isEmpty(location)) {
modelImport.setModelLocation(location);
} else if (!CoreStringUtil.isEmpty(path)) {
if (WorkspaceResourceFinderUtil.isGlobalResource(path)) {
modelImport.setModelLocation(location);
} else {
IResource iResource = WorkspaceResourceFinderUtil.findIResource(path);
if (iResource != null) {
URI importURI = URI.createFileURI(iResource.getLocation().toFile().getAbsolutePath());
URI modelURI = URI.createFileURI(this.getUnderlyingResource().getLocation().toFile().getAbsolutePath());
if (importURI.isFile()) {
boolean deresolve = (modelURI != null && !modelURI.isRelative() && modelURI.isHierarchical());
if (deresolve && !importURI.isRelative()) {
URI deresolvedURI = importURI.deresolve(modelURI, true, true, false);
if (deresolvedURI.hasRelativePath()) {
importURI = deresolvedURI;
}
}
modelImport.setModelLocation(URI.decode(importURI.toString()));
}
}
}
}
result.add(modelImport);
}
return result;
}
}
// The model resource is already open in the workspace so retrieve
// model imports from the model annotation node
else {
final Resource resource = this.getEmfResource();
if (resource instanceof EmfResource) {
// Get the primary metamodel ...
final ModelAnnotation annotation = this.getModelAnnotation();
return annotation.getModelImports();
}
}
return Collections.EMPTY_LIST;
}
@Override
public boolean hasChildren() {
return true;
}
private XMIHeader getXmiHeader() throws ModelWorkspaceException {
if (this.xmiHeader == null) {
try {
final IPath modelPath = this.getUnderlyingResource().getLocation();
final File modelFile = new File(modelPath.toOSString());
if (modelFile.exists()) {
this.xmiHeader = XMIHeaderReader.readHeader(modelFile);
}
} catch (TeiidDesignerException e) {
// do nothing
} catch (Throwable e) {
throw new ModelWorkspaceException(
e,
ModelerCore.Util.getString("ModelResourceImpl.Error_reading_XMI_header_from_resource_1", this.getUnderlyingResource())); //$NON-NLS-1$
}
}
return this.xmiHeader;
}
private XsdHeader getXsdHeader() throws ModelWorkspaceException {
if (this.xsdHeader == null) {
try {
final IPath modelPath = this.getUnderlyingResource().getLocation();
final File modelFile = new File(modelPath.toOSString());
if (modelFile.exists() && ModelFileUtil.isXsdFile(modelFile)) {
this.xsdHeader = XsdHeaderReader.readHeader(modelFile);
}
} catch (TeiidDesignerException e) {
// do nothing
} catch (Throwable e) {
throw new ModelWorkspaceException(
e,
ModelerCore.Util.getString("ModelResourceImpl.Error_reading_Xsd_header_from_resource_1", this.getUnderlyingResource())); //$NON-NLS-1$
}
}
return this.xsdHeader;
}
private boolean isResourceOpenAndLoaded() {
return (!this.isOpening() && this.isOpen() && this.isLoaded());
}
/**
* Process the contents change notification to see whether the EMF resource needs to be unloaded. This method looks at the old
* and new
*
* @param notification
* @since 4.2
*/
protected boolean processContentsChange( final ModelWorkspaceNotification notification ) {
boolean reloaded = false;
try {
final ModelBuffer buf = getBuffer();
if (buf != null && !buf.isClosed()) {
// Found a buffer, so it might be loaded
final IResourceDelta delta = notification.getDelta();
final IResource resource = delta.getResource();
if (resource instanceof IFile) {
final long newModStamp = resource.getModificationStamp();
final long lastModStamp = buf.getLastModificationStamp();
final boolean bufferIsInProcessOfSaving = buf.isInProcessOfSaving();
if (newModStamp != ModelBuffer.INITIAL_MOD_STAMP && newModStamp != lastModStamp && !bufferIsInProcessOfSaving) {
// The file has been changed on the file system by something other than this ModelBuffer ...
// Check the file size ...
final IPath rawLocation = ModelUtil.getLocation(resource);
long fileSize = 0;
if (rawLocation != null) {
final File rawFile = new File(rawLocation.toString());
if (rawFile.exists()) {
fileSize = rawFile.length();
}
}
boolean askToReload = true;
if (fileSize == buf.getLastFileSize()) {
// The file sizes are the same, so compare the checksum ...
InputStream stream = null;
try {
stream = ((IFile)resource).getContents();
final Checksum checksum = ChecksumUtil.computeChecksum(stream);
final long checksumValue = checksum.getValue();
if (checksumValue == buf.getLastChecksum()) {
// The size is the same and the checksums are the same, so assume no need to reload ...
// (see defect 15065)
askToReload = false;
}
} catch (CoreException err1) {
// don't log, but treat as files are different ...
askToReload = true;
} catch (IOException err1) {
// don't log, but treat as files are different ...
askToReload = true;
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException ignore) {
}
}
}
}
if (askToReload) {
setIndexType(ModelResource.NOT_INDEXED);
final boolean reload = ModelWorkspaceManager.getModelWorkspaceManager().canReload(this);
if (reload) {
// throw out the current buffer and cause the creation of a new one ...
this.unload();
// Get a new buffer and cause it to be opened ...
this.getBufferHack();
reloaded = true;
}
}
}
}
}
} catch (Exception err) {
// ModelerCore.Util.log(err); // okay to eat, since no buffer, nothing to unload/reload?
}
return reloaded;
}
/**
* @see org.teiid.designer.core.workspace.Openable#save(org.eclipse.core.runtime.IProgressMonitor, boolean)
* @since 5.0
*/
@Override
public void save( final IProgressMonitor pm,
final boolean force ) throws ModelWorkspaceException {
super.save(pm, force);
refreshIndexType();
}
@Override
public synchronized void close() throws ModelWorkspaceException {
super.close();
// we only want to remove the emf resource from the resourceset
// (container) when it's containing model project is closing
if (getModelProject().isClosing()) {
removeEmfResource();
}
}
public synchronized void removeEmfResource() {
IResource iResource = getResource();
if (iResource != null) {
IPath path = iResource.getLocation();
if (path != null) {
final URI uri = URI.createFileURI(path.toString());
try {
ResourceSet resourceSet = ModelerCore.getModelContainer();
// If, in the future, we support multiple containers in the workspace, we can use the resource set finder to
// locate the appropriate resource set
// ResourceSet resourceSet = super.getBufferManager().getResourceSetFinder().getResourceSet(iResource);
Resource resource = resourceSet.getResource(uri, false);
if (resource != null) {
if (resource.isLoaded()) {
resource.unload();
}
resourceSet.getResources().remove(resource);
}
} catch (CoreException err) {
ModelerCore.Util.log(err);
}
}
}
}
}