/*
* 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;
import java.io.BufferedWriter;
import java.io.CharArrayWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
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.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.CommandWrapper;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.common.command.UnexecutableCommand;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EFactory;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.impl.ENotificationImpl;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.edit.command.AbstractOverrideableCommand;
import org.eclipse.emf.edit.command.AddCommand;
import org.eclipse.emf.edit.command.CommandParameter;
import org.eclipse.emf.edit.command.CopyCommand;
import org.eclipse.emf.edit.command.CopyToClipboardCommand;
import org.eclipse.emf.edit.command.CreateChildCommand;
import org.eclipse.emf.edit.command.CreateCopyCommand;
import org.eclipse.emf.edit.command.CutToClipboardCommand;
import org.eclipse.emf.edit.command.MoveCommand;
import org.eclipse.emf.edit.command.PasteFromClipboardCommand;
import org.eclipse.emf.edit.command.RemoveCommand;
import org.eclipse.emf.edit.command.SetCommand;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.provider.IItemLabelProvider;
import org.eclipse.emf.edit.provider.ItemPropertyDescriptor;
import org.eclipse.xsd.XSDAttributeUse;
import org.eclipse.xsd.XSDConcreteComponent;
import org.eclipse.xsd.XSDPackage;
import org.eclipse.xsd.XSDParticle;
import org.eclipse.xsd.XSDParticleContent;
import org.eclipse.xsd.XSDSchema;
import org.eclipse.xsd.XSDSimpleTypeDefinition;
import org.eclipse.xsd.impl.XSDSchemaImpl;
import org.eclipse.xsd.util.XSDConstants;
import org.eclipse.xsd.util.XSDResourceImpl;
import org.teiid.core.designer.ModelerCoreException;
import org.teiid.core.designer.ModelerCoreRuntimeException;
import org.teiid.core.designer.TeiidDesignerException;
import org.teiid.core.designer.TeiidDesignerRuntimeException;
import org.teiid.core.designer.id.IDGenerator;
import org.teiid.core.designer.id.InvalidIDException;
import org.teiid.core.designer.id.ObjectID;
import org.teiid.core.designer.id.ObjectIDFactory;
import org.teiid.core.designer.id.UUID;
import org.teiid.core.designer.util.CoreArgCheck;
import org.teiid.core.designer.util.CoreStringUtil;
import org.teiid.core.designer.util.DebuggingStopwatch;
import org.teiid.core.designer.util.StringConstants;
import org.teiid.designer.common.xmi.XMIHeader;
import org.teiid.designer.common.xmi.XMIHeaderReader;
import org.teiid.designer.core.association.AbstractAssociationDescriptor;
import org.teiid.designer.core.association.AssociationProvider;
import org.teiid.designer.core.container.CloneCommand;
import org.teiid.designer.core.container.Container;
import org.teiid.designer.core.container.ContainerEditingDomain;
import org.teiid.designer.core.container.ContainerImpl;
import org.teiid.designer.core.container.EObjectFinder;
import org.teiid.designer.core.container.ResourceFinder;
import org.teiid.designer.core.metamodel.MetamodelDescriptor;
import org.teiid.designer.core.metamodel.MetamodelRootClass;
import org.teiid.designer.core.metamodel.aspect.AspectManager;
import org.teiid.designer.core.metamodel.aspect.sql.SqlAnnotationAspect;
import org.teiid.designer.core.metamodel.aspect.sql.SqlAspect;
import org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeAspect;
import org.teiid.designer.core.metamodel.aspect.sql.SqlDatatypeCheckerAspect;
import org.teiid.designer.core.resource.MMXmiResource;
import org.teiid.designer.core.resource.xmi.MtkXmiResourceImpl;
import org.teiid.designer.core.search.DeleteRelatedWorkspaceSearch;
import org.teiid.designer.core.search.ModelWorkspaceSearch;
import org.teiid.designer.core.transaction.UnitOfWork;
import org.teiid.designer.core.transaction.UnitOfWorkImpl;
import org.teiid.designer.core.types.DatatypeConstants;
import org.teiid.designer.core.types.EnterpriseDatatypeInfo;
import org.teiid.designer.core.util.DisabledCommand;
import org.teiid.designer.core.util.ModelContents;
import org.teiid.designer.core.util.ModelResourceContainerFactory;
import org.teiid.designer.core.util.ModelVisitorProcessor;
import org.teiid.designer.core.workspace.ModelResource;
import org.teiid.designer.core.workspace.ModelUtil;
import org.teiid.designer.core.workspace.ModelWorkspaceException;
import org.teiid.designer.core.workspace.ModelWorkspaceManager;
import org.teiid.designer.core.workspace.WorkspaceResourceFinderUtil;
import org.teiid.designer.metamodels.core.Annotation;
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;
import org.teiid.designer.metamodels.core.custom.impl.XsdModelAnnotationImpl;
import org.teiid.designer.metamodels.core.extension.ExtensionFactory;
import org.teiid.designer.metamodels.core.extension.XClass;
import org.teiid.designer.metamodels.core.extension.XPackage;
import org.teiid.designer.metamodels.core.extension.impl.ExtensionFactoryImpl;
import org.teiid.designer.metamodels.diagram.Diagram;
/**
* @since 8.0
*/
public class ModelEditorImpl implements ModelEditor {
/**
* Defines the XML Schema-of-schemas namespace URI - must be consistent with the values found in org.teiid.designer.metamodels.xsd
* plugin.xml
*/
public static final String XML_SCHEMA_METAMODEL_URI = XSDPackage.eNS_URI;
private static final String ESTRING_MAP_NAME = "EStringToStringMapEntry"; //$NON-NLS-1$
protected static final String NEW = ModelerCore.Util.getString("ModelEditorImpl.New_1"); //$NON-NLS-1$
private static final ObjectIDFactory OBJECT_ID_FACTORY = IDGenerator.getInstance().getFactory(UUID.PROTOCOL);
static final int BUFFER_LENGTH = 8192;
private static final int UUID_PROTOCOL_LENGTH = UUID.PROTOCOL.length();
private static final int UUID_PREFIX_LENGTH = UUID_PROTOCOL_LENGTH + 1;
private static ContainerImpl ctnr;
public static ContainerImpl getContainer() {
if (ModelEditorImpl.ctnr != null) {
return ModelEditorImpl.ctnr;
}
try {
return (ContainerImpl)ModelerCore.getModelContainer();
} catch (CoreException err) {
ModelerCore.Util.log(IStatus.ERROR, err, err.getMessage());
}
return null;
}
/**
* @see org.teiid.designer.core.ModelEditor#setContainer(org.teiid.designer.core.container.ContainerImpl)
* @since 5.0
*/
public static void setContainer( final ContainerImpl container ) {
ModelEditorImpl.ctnr = container;
}
@Override
public boolean isDatatypeFeature( final EObject object,
final EStructuralFeature feature ) {
if (object == null || feature == null) {
return false;
}
final SqlAspect aspect = AspectManager.getSqlAspect(object);
if (aspect instanceof SqlDatatypeCheckerAspect) {
return ((SqlDatatypeCheckerAspect)aspect).isDatatypeFeature(object, feature);
}
return false;
}
@Override
public Collection getTags( final EObject obj ) {
Annotation annotation = this.getAnnotation(obj, false);
if (annotation == null) {
return Collections.EMPTY_LIST;
}
final ArrayList tags = new ArrayList();
final Iterator refs = annotation.eClass().getEReferences().iterator();
while (refs.hasNext()) {
final EReference ref = (EReference)refs.next();
if (ref.getEType() != null && ref.getEType().getName() != null && ref.getEType().getName().equals(ESTRING_MAP_NAME)) {
Object val = annotation.eGet(ref);
if (val != null) {
tags.add(val);
}
}
}
return tags;
}
/**
* @see org.teiid.designer.core.ModelEditor#equals(org.eclipse.emf.ecore.EObject, org.eclipse.emf.ecore.EObject)
*/
@Override
public boolean equals( final EObject eObject1,
final EObject eObject2 ) {
if (eObject1 == null || eObject2 == null) {
return false;
}
if (eObject1 == eObject2) {
return true;
}
EObject eObj1 = eObject1;
EObject eObj2 = eObject2;
boolean eObjIsProxy1 = eObj1.eIsProxy();
boolean eObjIsProxy2 = eObj2.eIsProxy();
if (eObjIsProxy1 && eObjIsProxy2) {
URI eProxyUri1 = EcoreUtil.getURI(eObj1);
URI eProxyUri2 = EcoreUtil.getURI(eObj2);
return eProxyUri1.equals(eProxyUri2);
}
if (eObjIsProxy1) {
try {
eObj1 = EcoreUtil.resolve(eObj1, getContainer());
} catch (Exception e) {
final String msg = ModelerCore.Util.getString("ModelEditorImpl.Error_getting_model_container._1"); //$NON-NLS-1$
ModelerCore.Util.log(IStatus.ERROR, e, msg);
}
}
if (eObjIsProxy2) {
try {
eObj2 = EcoreUtil.resolve(eObj2, getContainer());
} catch (Exception e) {
final String msg = ModelerCore.Util.getString("ModelEditorImpl.Error_getting_model_container._2"); //$NON-NLS-1$
ModelerCore.Util.log(IStatus.ERROR, e, msg);
}
}
return eObj1.equals(eObj2);
}
/**
* @see org.teiid.designer.core.ModelEditor#createInitialModel(org.eclipse.emf.ecore.resource.Resource,
* org.eclipse.emf.ecore.EClass)
*/
@Override
public EObject createInitialModel( final Resource resource,
final EClass eClass ) throws ModelerCoreException {
if (!isRootObject(eClass)) {
throw new ModelerCoreException(
ModelerCore.Util.getString("ModelEditorImpl.{0}_is_not_a_valid_root_object_1", eClass.getName())); //$NON-NLS-1$
}
final EObject rootObject = this.create(eClass);
if (rootObject != null) {
resource.getContents().add(rootObject);
}
return rootObject;
}
/**
* Return the MetamodelDescriptor for the given EObject
*
* @param object
* @return the MetamodelDescriptor for the given EObject
*/
@Override
public MetamodelDescriptor getMetamodelDescriptor( final EObject object ) {
CoreArgCheck.isNotNull(object);
Container cntr = getContainer();
String uri = object.eClass().getEPackage().getNsURI();
// If the object is a proxy look up the descriptor
// in the container's metamodel registry
if (uri != null && cntr != null) {
return cntr.getMetamodelRegistry().getMetamodelDescriptor(URI.createURI(uri));
}
// If the object is not a proxy look up the descriptor
// in the metamodel registry in ModelerCore
else if (uri != null && cntr == null) {
return ModelerCore.getMetamodelRegistry().getMetamodelDescriptor(URI.createURI(uri));
}
return null;
}
/**
* @see org.teiid.designer.core.ModelEditor#getPrimaryMetamodelDescriptor(org.teiid.designer.core.workspace.ModelResource)
*/
@Override
public MetamodelDescriptor getPrimaryMetamodelDescriptor( final ModelResource resource ) throws ModelWorkspaceException {
CoreArgCheck.isNotNull(resource);
return resource.getPrimaryMetamodelDescriptor();
}
/**
* @see org.teiid.designer.core.ModelEditor#getPrimaryMetamodelDescriptor(org.eclipse.emf.ecore.resource.Resource)
*/
@Override
public MetamodelDescriptor getPrimaryMetamodelDescriptor( final Resource resource ) throws ModelWorkspaceException {
CoreArgCheck.isNotNull(resource);
// See if this resource is an EmfResource; if so, there is a shortcut to not look up the Model Resource ...
if (resource instanceof MMXmiResource) {
final MMXmiResource emfResource = (MMXmiResource)resource;
final String primaryMetamodelUri = getPrimaryMetamodelURI(emfResource);
if (primaryMetamodelUri != null && primaryMetamodelUri.length() != 0) {
// Look up the descriptor in the metamodels ...
final URI nsUri = ModelerCore.getMetamodelRegistry().getURI(primaryMetamodelUri);
final MetamodelDescriptor descriptor = ModelerCore.getMetamodelRegistry().getMetamodelDescriptor(nsUri);
// 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);
}
}
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;
}
}
// Not found the easy way, so do the lookup ...
final ModelResource modelResource = this.findModelResource(resource);
return getPrimaryMetamodelDescriptor(modelResource);
}
/**
* @see org.teiid.designer.core.ModelEditor#getNewChildDescriptors(org.eclipse.emf.ecore.EObject)
*/
@Override
public Collection getNewChildCommands( final EObject eObject ) throws ModelerCoreException {
final ContainerImpl container = getContainer();
if (container != null) {
// Wrapping this in a transaction to avoid the sub-set operations from being placed in the
// undo/redo stack. IsSignificant and Undoable have both been set to false so the entire
// operation will not be present in the edit->undo menu. This functionality is called
// when you open the New Child sub-menu.
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) {
final EditingDomain domain = container.getEditingDomain();
Collection result = domain.getNewChildDescriptors(eObject, null);
setDescriptorOwner(result, eObject);
result = createCommands(result, domain);
return (result != null ? result : Collections.EMPTY_LIST);
}
};
Object result = executeAsTransaction(runnable, container, "Getting Child Commands", false, false, eObject); //$NON-NLS-1$
return result instanceof Collection ? (Collection)result : Collections.EMPTY_LIST;
}
return Collections.EMPTY_LIST;
}
/**
* This method determines whether the {@link CommandParameter} instance would result in a violation of the maximum
* multiplicity.
*
* @param owner the parent of a new object created by the command parameter
* @param commandParams the list of command parameters; may not be null
* @return true if the command should be disabled, or false otherwise
*/
protected boolean shouldBeDisabled( final Object owner,
final CommandParameter commandParam ) {
if (owner instanceof EObject) {
final EObject parent = (EObject)owner;
final EStructuralFeature feature = commandParam.getEStructuralFeature();
final int maxMultiplicity = feature.getUpperBound();
if (maxMultiplicity == -1) {
// feature is unbounded ...
return false;
}
if (maxMultiplicity > 1) {
// Get the current number of values ...
final Object currentValue = parent.eGet(feature);
// The current value should be a list
final int currentSize = ((List)currentValue).size();
if (currentSize >= maxMultiplicity) {
// The current size is that of the maximum allowed, so wrap the command parameter
return true;
}
// Otherwise it is okay to keep
} else {
// The current value is not a list but a single value ...
final boolean isSet;
try {
isSet = parent.eIsSet(feature);
} catch (IllegalArgumentException e) {
// IAE results if the feature is not settable
return true;
}
if (isSet) {
// The value is current set, so unable to add another
return true;
}
}
}
return false;
}
/**
* @see org.teiid.designer.core.ModelEditor#getNewChildDescriptors(org.eclipse.emf.ecore.EObject)
*/
@Override
public Collection getNewRootObjectCommands( final Resource resource ) {
final ContainerImpl container = getContainer();
final EditingDomain domain = container.getEditingDomain();
Collection descriptors = getRootDescriptors(resource);
return createCommands(descriptors, domain);
}
/**
* @see org.teiid.designer.core.ModelEditor#getNewSiblingDescriptors(org.eclipse.emf.ecore.EObject)
*/
@Override
public Collection getNewSiblingCommands( final EObject eObject ) throws ModelerCoreException {
final ContainerImpl container = getContainer();
// Wrapping this in a transaction to avoid the sub-set operations from being placed in the
// undo/redo stack. IsSignificant and Undoable have both been set to false so the entire
// operation will not be present in the edit->undo menu. This functionality is called
// when you open the New Sibling sub-menu.
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) {
Collection descriptors = null;
final EditingDomain domain = container.getEditingDomain();
if (eObject.eContainer() == null) {
URI nsUri = eObject.eClass().eResource().getURI();
List rootClasses = Arrays.asList(ModelerCore.getMetamodelRegistry().getMetamodelRootClasses(nsUri));
Collection filteredClasses = new ArrayList(rootClasses.size());
for( Object obj : rootClasses ) {
String className = ((MetamodelRootClass)obj).getEClass().getName();
boolean ignore = className.equalsIgnoreCase("BaseTable") || //$NON-NLS-1$
className.equalsIgnoreCase("Procedure") || //$NON-NLS-1$
className.equalsIgnoreCase("Index") || //$NON-NLS-1$
className.equalsIgnoreCase("View"); //$NON-NLS-1$
if( !ignore ) {
filteredClasses.add(obj);
}
}
final EPackage ePackage = ModelerCore.getMetamodelRegistry().getEPackage(nsUri);
final EFactory eFactory = ePackage.getEFactoryInstance();
descriptors = createSiblingDescriptors(filteredClasses, eFactory, eObject);
descriptors = createCommands(descriptors, domain);
} else {
descriptors = domain.getNewChildDescriptors(null, eObject);
setDescriptorOwner(descriptors, eObject.eContainer());
descriptors = createCommands(descriptors, domain);
}
if (descriptors == null) {
return Collections.EMPTY_LIST;
}
return descriptors;
}
};
Object result = executeAsTransaction(runnable, container, "Getting Sibling Commands", false, false, eObject); //$NON-NLS-1$
return result instanceof Collection ? (Collection)result : Collections.EMPTY_LIST;
}
/**
* <p>
* </p>
*
* @see org.teiid.designer.core.ModelEditor#executeAsTransaction(org.teiid.designer.core.TransactionRunnable,
* java.lang.String, boolean)
* @since 4.0
*/
@Override
public Object executeAsTransaction( final TransactionRunnable runnable,
final String description,
final boolean significant,
final Object source ) throws ModelerCoreException {
try {
return executeAsTransaction(runnable, null, description, significant, source);
} catch (final CoreException err) {
throw new ModelerCoreException(err);
}
}
/**
* <p>
* </p>
*
* @see org.teiid.designer.core.ModelEditor#executeAsTransaction(org.teiid.designer.core.TransactionRunnable,
* java.lang.String, boolean)
* @since 4.0
*/
@Override
public Object executeAsTransaction( final TransactionRunnable runnable,
final String description,
final boolean significant,
final boolean undoable,
final Object source ) throws ModelerCoreException {
try {
return executeAsTransaction(runnable, null, description, significant, undoable, source);
} catch (final CoreException err) {
throw new ModelerCoreException(err);
}
}
/**
*/
protected Object executeAsTransaction( final TransactionRunnable runnable,
Container container,
final String operationDescription,
final boolean isSignificant,
final boolean undoable,
final Object source ) throws ModelerCoreException {
// Use default container if not specified
if (container == null) {
container = getContainer();
}
// Get the current transaction (this may create one) ...
final UnitOfWork uow = container.getEmfTransactionProvider().getCurrent();
boolean startedTxn = false;
// If the current transaction is new, it must be started ...
if (uow.requiresStart()) {
uow.begin();
startedTxn = true;
uow.setSignificant(isSignificant);
uow.setSource(source);
uow.setUndoable(undoable);
// Set the description ...
if (operationDescription != null) {
uow.setDescription(operationDescription);
}
}
boolean failed = false;
Object result = null;
try {
// Perform the requested work
result = runnable.run(uow);
} catch (ModelerCoreException t) {
// There was a runtime exception while performing the work
failed = true;
throw t;
} catch (RuntimeException t) {
// There was a runtime exception while performing the work
failed = true;
throw new ModelerCoreRuntimeException(t);
} finally {
if (startedTxn) {
// We started the current transaction ...
if (!failed) {
// Commit the transaction ...
try {
uow.commit();
} catch (Throwable e) {
ModelerCore.Util.log(e);
failed = true;
}
}
if (failed) {
// Rollback the transaction ...
// (which may have failed while performing the work or when committing)
try {
uow.rollback();
} catch (ModelerCoreException e1) {
ModelerCore.Util.log(e1);
}
}
}
}
return result;
}
/**
*/
@Override
public Object executeAsTransaction( final TransactionRunnable runnable,
final Container container,
final String operationDescription,
final boolean isSignificant,
final Object source ) throws ModelerCoreException {
return executeAsTransaction(runnable, container, operationDescription, isSignificant, true, source);
}
/**
* @see org.teiid.designer.core.ModelEditor#createNewChildFromDescriptor(java.lang.Object)
*/
@Override
public EObject createNewChildFromCommand( final EObject parent,
final Command cmd ) throws ModelerCoreException {
final boolean isSignificant = true;
final String operationDescription = ModelerCore.Util.getString("ModelEditorImpl.Create_New_Child_for_{0}_1", getPresentationValue(parent)); //$NON-NLS-1$
final ContainerImpl cntr = getContainer();
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) throws ModelerCoreException {
executeCommandInTransaction(uow, parent, cmd);
EObject child = null;
if (cmd.getResult() != null) {
child = (EObject)cmd.getResult().iterator().next();
ModelEditorImpl.this.renameInternal(child, NEW + child.eClass().getName());
ModelEditorImpl.this.setUuidFeatureValue(child);
}
return child;
}
};
final EObject child = (EObject)executeAsTransaction(runnable, cntr, operationDescription, isSignificant, this);
return child;
}
protected void setUuidFeatureValue( final EObject eObj ) {
}
/**
* @see org.teiid.designer.core.ModelEditor#createNewChildFromDescriptor(java.lang.Object)
*/
@Override
public EObject createNewRootObjectFromCommand( final Resource parent,
final Command cmd ) throws ModelerCoreException {
CoreArgCheck.isNotNull(parent);
CoreArgCheck.isNotNull(cmd);
final boolean isSignificant = true;
final String operationDescription = ModelerCore.Util.getString("ModelEditorImpl.Create_New_Child_for_{0}_1", //$NON-NLS-1$
getPresentationValue(parent));
final ContainerImpl cntr = getContainer();
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) throws ModelerCoreException {
executeCommandInTransaction(uow, parent, cmd);
EObject child = null;
if (cmd.getResult() != null) {
child = (EObject)cmd.getResult().iterator().next();
ModelEditorImpl.this.renameInternal(child, NEW + child.eClass().getName());
ModelEditorImpl.this.setUuidFeatureValue(child);
}
return child;
}
};
final EObject child = (EObject)executeAsTransaction(runnable, cntr, operationDescription, isSignificant, this);
return child;
}
/**
* @see org.teiid.designer.core.ModelEditor#createNewSiblingFromDescriptor(java.lang.Object)
*/
@Override
public EObject createNewSiblingFromCommand( final EObject sibling,
final Command cmd ) throws ModelerCoreException {
final boolean isSignificant = true;
final String operationDescription = ModelerCore.Util.getString("ModelEditorImpl.Create_New_Sibling_for_{0}_2", getPresentationValue(sibling)); //$NON-NLS-1$
final ContainerImpl cntr = getContainer();
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) throws ModelerCoreException {
executeCommandInTransaction(uow, sibling, cmd);
EObject newSibling = null;
if (cmd.getResult() != null) {
newSibling = (EObject)cmd.getResult().iterator().next();
ModelEditorImpl.this.renameInternal(newSibling, NEW + newSibling.eClass().getName());
setUuidFeatureValue(newSibling);
}
return newSibling;
}
};
final EObject newSibling = (EObject)executeAsTransaction(runnable, cntr, operationDescription, isSignificant, this);
return newSibling;
}
/**
* @see org.teiid.designer.core.ModelEditor#createNewAssociationFromDescriptor(java.lang.Object)
*/
@Override
public EObject createNewAssociationFromDescriptor( Object descriptor ) throws ModelerCoreException {
if (descriptor != null && descriptor instanceof AbstractAssociationDescriptor) {
final AbstractAssociationDescriptor assocDescr = (AbstractAssociationDescriptor)descriptor;
// If the descriptor is considered complete (i.e. containing sufficient information
// for construction of the association) then create the association
if (assocDescr.isComplete()) {
// Start the association construction in a transaction if one does not exist
final boolean isSignificant = true;
final String operationDescription = ModelerCore.Util.getString("ModelEditorImpl.Create_new_Association_3"); //$NON-NLS-1$
final ContainerImpl cntr = getContainer();
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) throws ModelerCoreException {
// If the descriptor is considered ambiguous then construct the association using
// the first AssociationDescriptor instance in the list of creation possibilities
EObject result = null;
if (assocDescr.isAmbiguous()) {
result = ((AbstractAssociationDescriptor)assocDescr.getChildren()[0]).create();
}
// Else create the association using the single descriptor
else {
result = assocDescr.create();
}
ModelEditorImpl.this.renameInternal(result, NEW + result.eClass().getName());
return result;
}
};
final EObject result = (EObject)executeAsTransaction(runnable, cntr, operationDescription, isSignificant, this);
return result;
}
}
return null;
}
/**
* @see org.teiid.designer.core.ModelEditor#getNewAssociationDescriptors(java.util.List)
*/
@Override
public Collection getNewAssociationDescriptors( final List eObjects ) throws ModelerCoreException {
// Retrieve the list of AssociationProvider instances from the ExtensionDescriptor
// instances available through the ModelerCore Configuration
final Configuration config = ModelerCore.getConfiguration();
final Collection descriptors = config.getAssociationProviderDescriptors();
// Iterate over the list of AssociationProviders accumulating association descriptors
final Collection result = new HashSet(descriptors.size());
for (Iterator iter = descriptors.iterator(); iter.hasNext();) {
ExtensionDescriptor descriptor = (ExtensionDescriptor)iter.next();
AssociationProvider provider = (AssociationProvider)descriptor.getExtensionClassInstance();
if (provider != null) {
result.addAll(provider.getNewAssociationDescriptors(eObjects));
}
}
return result;
}
/**
* @see org.teiid.designer.core.ModelEditor#copy(org.eclipse.emf.ecore.EObject)
*/
@Override
public EObject copy( final EObject eObject ) throws ModelerCoreException {
CoreArgCheck.isNotNull(eObject);
return copy(eObject, null);
}
/**
* @see org.teiid.designer.core.ModelEditor#copy(org.eclipse.emf.ecore.EObject)
*/
@Override
public EObject copy( final EObject eObject,
final Map originalsToCopies ) throws ModelerCoreException {
CoreArgCheck.isNotNull(eObject);
final boolean isSignificant = true;
final String operationDescription = ModelerCore.Util.getString("ModelEditorImpl.Copy_{0}_4", getPresentationValue(eObject)); //$NON-NLS-1$
final ContainerImpl cntr = getContainer();
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) throws ModelerCoreException {
final EditingDomain ed = cntr.getEditingDomain();
final CopyCommand.Helper helper = new CopyCommand.Helper();
if (originalsToCopies != null && !originalsToCopies.isEmpty()) {
// copy all of the existing entries in the 'originalsToCopies' map into the helper ...
// This will change the copies to reference other copies that may have been created
// already and are in the map, but are not directly in the graph of contained objects
// below the original 'eObject'
helper.putAll(originalsToCopies);
}
final Command command = createCopyCommand(ed, eObject, helper);
executeCommandInTransaction(uow, eObject, command);
EObject result = null;
if (command.getResult() != null) {
result = (EObject)command.getResult().iterator().next();
setUuidFeatureValue(result);
}
// Populate the map from orig to copies
if (originalsToCopies != null) originalsToCopies.putAll(helper);
return result;
}
};
final EObject result = (EObject)executeAsTransaction(runnable, cntr, operationDescription, isSignificant, this);
return result;
}
/**
* @see org.teiid.designer.core.ModelEditor#copy(org.eclipse.emf.ecore.EObject)
*/
@Override
public Collection copyMultiple( final EObject eObject,
final int numCopies ) throws ModelerCoreException {
CoreArgCheck.isNotNull(eObject);
CoreArgCheck.isPositive(numCopies);
final ArrayList copies = new ArrayList(numCopies);
final boolean isSignificant = true;
final String operationDescription = ModelerCore.Util.getString("ModelEditorImpl.Copy_{0}_4", getPresentationValue(eObject)); //$NON-NLS-1$
final ContainerImpl cntr = getContainer();
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) throws ModelerCoreException {
final EditingDomain ed = cntr.getEditingDomain();
while (copies.size() < numCopies) {
final Command command = CopyCommand.create(ed, eObject);
executeCommandInTransaction(uow, eObject, command);
if (command.getResult() != null) {
final EObject copy = (EObject)command.getResult().iterator().next();
setUuidFeatureValue(copy);
copies.add(copy);
} else {
throw new ModelerCoreException(ModelerCore.Util.getString("ModelEditorImpl.Error_creating_copies_1")); //$NON-NLS-1$
}
}
return null;
}
};
executeAsTransaction(runnable, cntr, operationDescription, isSignificant, this);
return copies;
}
/**
* @see org.teiid.designer.core.ModelEditor#delete(java.util.Collection)
*/
@Override
public boolean delete( final Collection eObjects ) throws ModelerCoreException {
CoreArgCheck.isNotNull(eObjects);
if (eObjects.isEmpty()) {
return false;
}
boolean result = delete(eObjects, new NullProgressMonitor());
return result;
}
/**
* @see org.teiid.designer.core.ModelEditor#delete(java.util.Collection)
*/
@Override
public boolean delete( final Collection eObjects,
final IProgressMonitor monitor ) throws ModelerCoreException {
CoreArgCheck.isNotNull(eObjects);
if (eObjects.isEmpty()) {
return false;
}
// Execute the command ...
final boolean isSignificant = true;
final ContainerImpl cntr = getContainer();
final String operationDescription = ModelerCore.Util.getString("ModelEditorImpl.Delete_multiple_objects_1"); //$NON-NLS-1$
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) throws ModelerCoreException {
final EditingDomain ed = cntr.getEditingDomain();
Command command = createDeleteManyCommand(ed, eObjects, monitor);
monitor.subTask(ModelerCore.Util.getString("ModelEditorImpl.executingDeleteMsg")); //$NON-NLS-1$
monitor.worked(5);
if (!monitor.isCanceled()) {
executeCommandInTransaction(uow, null, command);
}
return null;
}
};
executeAsTransaction(runnable, cntr, operationDescription, isSignificant, this);
return true;
}
public Command createDeleteManyCommand( final EditingDomain ed,
final Collection eObjects,
final IProgressMonitor monitor ) throws ModelerCoreException {
// You need a delete command for each parent
final HashMap objectsByContainment = new HashMap();
final boolean ignoreXsdResources = !includesXsdObject(eObjects);
DebuggingStopwatch watch = new DebuggingStopwatch(
"ModelEditorImpl.createDeleteManyCommand(EObject) Ignore XSD's = " + ignoreXsdResources, 10, false); //$NON-NLS-1$
watch.start();
watch.startStats();
// Build up the list of objects that should be deleted in addition to 'eObject' ...
final LinkedList commands = new LinkedList();
final Iterator removedObjects = eObjects.iterator();
while (removedObjects.hasNext()) {
// object to be deleted
final EObject eObject = (EObject)removedObjects.next();
// owner of the object
final Object owner = eObject.eContainer() == null ? (Object)eObject.eResource() : eObject.eContainer();
// containment feature of the object in the owner
final Object feature = eObject.eContainmentFeature();
// collection of objects by owner or collection of objects by feature by owner
Object existing = objectsByContainment.get(owner);
if (existing == null) {
// no feature just object by owner
if (feature == null) {
existing = new HashSet();
// by feature by owner
} else {
existing = new HashMap();
}
objectsByContainment.put(owner, existing);
}
// update existing with new info
if (existing instanceof Collection) {
((Collection)existing).add(eObject);
} else if (existing instanceof Map) {
Collection objectsByFeature = (Collection)((Map)existing).get(feature);
if (objectsByFeature == null) {
objectsByFeature = new HashSet();
}
objectsByFeature.add(eObject);
((Map)existing).put(feature, objectsByFeature);
}
}
// defect 19592 - moved the following three statements out of the above loop,
// so that the search for deleted objects can know about all things being deleted.
// Dennis and Pat suppose the real clincher is that findReferencesToObjectsBeingDeleted
// is the main beneficiary of this -- findOtherObjectsToBeDeleted is now gathering up
// everything into one collection for everything instead of one collection per deleted object.
monitor.worked(5);
// -----------------------------------------
// find other objects and references to delete or clear:
// -----------------------------------------
// Create Delete-related search (Defect 22774)
ModelWorkspaceSearch workspaceSearch = new DeleteRelatedWorkspaceSearch(ignoreXsdResources);
// -----------------------------------------
// Find other objects to be deleted ... these are returned in a collection containing the original objects
// and the related objects
// -----------------------------------------
final Collection allDeleted = findOtherObjectsToBeDeleted(eObjects, ed, commands, workspaceSearch, monitor);
monitor.worked(10);
// -----------------------------------------
// Find references to objects being deleted ...
// -----------------------------------------
findReferencesToObjectsBeingDeleted(allDeleted, ed, commands, workspaceSearch, monitor);
monitor.subTask(ModelerCore.Util.getString("ModelEditorImpl.preparingCommandMsg")); //$NON-NLS-1$
monitor.worked(10);
// -----------------------------------------
// create commands to delete each eObject to be deleted
// -----------------------------------------
for (final Iterator iter1 = objectsByContainment.entrySet().iterator(); iter1.hasNext();) {
if (monitor.isCanceled()) {
break;
}
// owner to eObjects map
final Map.Entry entry1 = (Map.Entry)iter1.next();
Object key = entry1.getKey();
// owner is a Eobject so there is feature associated with child
if (key instanceof EObject) {
final EObject parent = (EObject)key;
// feature to child map
final Map objectsByFeature = (Map)entry1.getValue();
// for each feature delete children
for (final Iterator iter2 = objectsByFeature.entrySet().iterator(); iter2.hasNext();) {
final Map.Entry entry2 = (Map.Entry)iter2.next();
final EReference ref = (EReference)entry2.getKey();
Collection objects = (Collection)entry2.getValue();
if (ref.isMany()) {
final CommandParameter param = new CommandParameter(parent, ref, objects);
final Command command = ed.createCommand(RemoveCommand.class, param);
commands.addFirst(command);
} else {
final CommandParameter param = new CommandParameter(parent, ref, null);
final Command command = ed.createCommand(SetCommand.class, param);
commands.addFirst(command);
}
}
} else {
// owner to delted objects map
final Collection values = (Collection)entry1.getValue();
final Resource parent = (Resource)key;
final EList contents = parent.getContents();
final CommandParameter param = new CommandParameter(parent, contents, values);
final Command command = ed.createCommand(RemoveCommand.class, param);
commands.addFirst(command);
}
}
Collection finalEObjects = Collections.EMPTY_LIST;
List finalCommands = Collections.EMPTY_LIST;
if (!monitor.isCanceled()) {
finalEObjects = eObjects;
finalCommands = commands;
}
CompoundCommand cCommand = CompoundCommandFactory.create(finalEObjects, finalCommands);
watch.stop();
watch.stopStats();
return cCommand;
}
/*
* Method determines if an object or a Collection of objects is or contains at least ONE EObject contained within an XSD
* resource. This knowledge can help streamline delete-related searches. See Defect 22774
*/
private boolean includesXsdObject( Object obj ) {
try {
if (obj instanceof EObject) {
ModelResource mr = findModelResource((EObject)obj);
if (mr != null && mr.getEmfResource() != null && ModelUtil.isXsdFile(mr.getEmfResource())) {
return true;
}
} else if (obj instanceof Collection) {
Collection theObjs = (Collection)obj;
for (Iterator iter = theObjs.iterator(); iter.hasNext();) {
Object nextObj = iter.next();
if (nextObj instanceof EObject) {
ModelResource mr = findModelResource((EObject)nextObj);
if (mr != null && mr.getEmfResource() != null && ModelUtil.isXsdFile(mr.getEmfResource())) {
return true;
}
}
}
}
} catch (ModelWorkspaceException theException) {
ModelerCore.Util.log(theException);
}
return false;
}
/**
* @see org.teiid.designer.core.ModelEditor#delete(org.eclipse.emf.ecore.EObject, boolean)
*/
@Override
public boolean delete( final EObject eObject,
final boolean performResourceCheck,
final boolean performRelatedObjectCheck ) throws ModelerCoreException {
CoreArgCheck.isNotNull(eObject);
// Check the parent (and resource) to see if the object is already deleted ...
// Per defect 13042.
if (performResourceCheck) {
final Resource resource = eObject.eResource();
if (resource == null) {
// The object doesn't exist in a resource, so nothing to delete
return false;
}
}
final boolean ignoreXsdResources = !includesXsdObject(eObject);
// Execute the command ...
final boolean isSignificant = true;
final ContainerImpl cntr = getContainer();
final String operationDescription = ModelerCore.Util.getString("ModelEditorImpl.Delete_{0}_5", getPresentationValue(eObject)); //$NON-NLS-1$
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) throws ModelerCoreException {
DebuggingStopwatch watch = new DebuggingStopwatch(
"ModelEditorImpl.delete(EObject) Ignore XSD's = " + ignoreXsdResources, 10, false); //$NON-NLS-1$
watch.start();
watch.startStats();
final EditingDomain ed = cntr.getEditingDomain();
Command command = createDeleteCommand(ed, eObject);
// some reason command cannot be created
if (command == null) {
return null;
}
if (performRelatedObjectCheck) {
// Build up the list of objects that should be deleted in addition to 'eObject' ...
final LinkedList additionalCommands = new LinkedList();
final Resource emfResource = eObject.eResource();
// Don't try to delete other object for unattached objects
if (emfResource != null) {
// ------------------------------
// Create a deleted-related workspace search
// ------------------------------
ModelWorkspaceSearch workspaceSearch = new DeleteRelatedWorkspaceSearch(ignoreXsdResources);
// ------------------------------
// Find other objects to be deleted ...
// ------------------------------
final Collection allDeleted = findOtherObjectsToBeDeleted(Collections.singleton(eObject),
ed,
additionalCommands,
workspaceSearch);
// ------------------------------
// Find references to objects being deleted ...
// ------------------------------
findReferencesToObjectsBeingDeleted(allDeleted, ed, additionalCommands, workspaceSearch);
// ------------------------------
// Add any new commands to the compound command ...
// ------------------------------
if (!additionalCommands.isEmpty()) {
additionalCommands.addFirst(command);
command = CompoundCommandFactory.create(eObject, additionalCommands);
}
}
}
executeCommandInTransaction(uow, eObject, command);
watch.stop();
watch.stopStats();
return null;
}
};
executeAsTransaction(runnable, cntr, operationDescription, isSignificant, this);
return true;
}
/**
* @see org.teiid.designer.core.ModelEditor#delete(org.eclipse.emf.ecore.EObject)
*/
@Override
public boolean delete( final EObject eObject,
final boolean performResourceCheck ) throws ModelerCoreException {
return this.delete(eObject, performResourceCheck, true);
}
/**
* @see org.teiid.designer.core.ModelEditor#delete(org.eclipse.emf.ecore.EObject)
*/
@Override
public boolean delete( final EObject eObject ) throws ModelerCoreException {
return this.delete(eObject, true);
}
/**
* Create a command to delete the supplied object. This is a utility method.
*
* @param editingDomain
* @param eObject
* @return
*/
protected static Command createDeleteCommand( final EditingDomain editingDomain,
final EObject eObject ) {
CoreArgCheck.isNotNull(eObject);
Command command = null;
if (eObject.eContainer() == null) {
final Resource rsrc = eObject.eResource();
if (rsrc != null) {
EList contents = rsrc.getContents();
if (contents.contains(eObject)) {
command = new RemoveCommand(editingDomain, contents, eObject);
}
}
} else {
// Create the command through the EditingDomain that way the ItemProvider associated
// with the "owner" EObject can specialize the createRemoveCommand(...) method.
// Fix for defect 12328.
final EStructuralFeature sf = eObject.eContainmentFeature();
if (sf.isMany()) {
Collection collection = new HashSet(1);
collection.add(eObject);
final CommandParameter param = new CommandParameter(eObject.eContainer(), sf, collection);
command = editingDomain.createCommand(RemoveCommand.class, param);
} else {
final CommandParameter param = new CommandParameter(eObject.eContainer(), sf, null);
command = editingDomain.createCommand(SetCommand.class, param);
}
// final EStructuralFeature sf = eObject.eContainmentFeature();
// if(sf.isMany() ){
// command = new RemoveCommand(editingDomain, eObject.eContainer(), sf, eObject);
// }else{
// command = new SetCommand(editingDomain, eObject.eContainer(), sf, null);
// }
}
return command;
}
/**
* Find references to the deleted objects and remove/unset them. <i>Note: This method only finds all references from undeleted
* objects.
*
* @param allDeleted the EObjects being deleted; never null
* @param editingDomain the editing domain; never null
* @param additionalCommands the list into which any additional delete commands should be placed; never null
*/
@Override
public void findReferencesToObjectsBeingDeleted( final Collection allDeleted,
final EditingDomain editingDomain,
final List additionalCommands,
final ModelWorkspaceSearch workspaceSearch ) throws ModelerCoreException {
findReferencesToObjectsBeingDeleted(allDeleted,
editingDomain,
additionalCommands,
workspaceSearch,
new NullProgressMonitor());
}
/**
* Find references to the deleted objects and remove/unset them. <i>Note: This method only finds all references from undeleted
* objects.
*
* @param allDeleted the EObjects being deleted; never null
* @param editingDomain the editing domain; never null
* @param additionalCommands the list into which any additional delete commands should be placed; never null
*/
public void findReferencesToObjectsBeingDeleted( final Collection allDeleted,
final EditingDomain editingDomain,
final List additionalCommands,
final ModelWorkspaceSearch workspaceSearch,
final IProgressMonitor monitor ) throws ModelerCoreException {
int iObj = 1;
int nObj = allDeleted.size();
int iInc = 1;
int halfWay = nObj / 2;
boolean pastHalfWay = false;
if (nObj < 20) {
iInc = 1;
} else if (nObj < 100) {
iInc = 10;
} else if (nObj < 500) {
iInc = 25;
} else {
iInc = 100;
}
String startMessage = ModelerCore.Util.getString("ModelEditorImpl.searchingReferencesMsg") + CoreStringUtil.Constants.SPACE; //$NON-NLS-1$
String ofText = CoreStringUtil.Constants.DBL_SPACE
+ ModelerCore.Util.getString("ModelEditorImpl.ofText") + CoreStringUtil.Constants.SPACE; //$NON-NLS-1$
// Construct and use the visitor ...
final ClearReferencesUponDelete visitor = new ClearReferencesUponDelete(allDeleted, editingDomain, workspaceSearch);
final ModelVisitorProcessor processor = new ModelVisitorProcessor(visitor);
for (final Iterator iter = allDeleted.iterator(); iter.hasNext();) {
if (iObj % iInc == 0) {
String message = startMessage + iObj + ofText + nObj;
monitor.subTask(message);
}
final EObject eObject = (EObject)iter.next();
if (eObject.eResource() == null) {
continue;
}
processor.walk(eObject, ModelVisitorProcessor.DEPTH_INFINITE);
iObj++;
if (monitor.isCanceled()) {
break;
}
if (!pastHalfWay && iObj > halfWay) {
monitor.worked(10);
pastHalfWay = true;
}
}
monitor.worked(10);
if (!monitor.isCanceled()) {
// 12/17/03 (LLP) : changed to add new commands to additionalCommands list.
final List removeAndSetCommands = visitor.getAdditionalCommands();
if (removeAndSetCommands != null && !removeAndSetCommands.isEmpty()) {
// 08/31/05 (TBJ) : Added method to check for dups before adding command
addCommands(removeAndSetCommands, additionalCommands);
}
}
}
/**
* This method will add a Command to the master list of addtional commands, if appropriate. Handles instances where an
* additional command may have already been added as might be the case when there are multiple objects being deleted and they
* contain bi-directional references such as PrimaryKey and ForeignKeys.
*
* @param removeAndSetCommands List of Remove and Set Commands
* @param additionalCommands Master list of Remove and Set Commands
* @since 4.3
*/
private void addCommands( final List removeAndSetCommands,
List additionalCommands ) {
Object command = null;
boolean addCommand = true;
Iterator iter = removeAndSetCommands.iterator();
/*
* Iterate through the list of commands to add
*/
while (iter.hasNext()) {
command = iter.next();
/*
* If this is a RemoveCommand, iterate through through the master list of additional commands to make sure the command
* has not already been added.
*/
if (command instanceof RemoveCommand) {
addCommand = true;
Iterator addCommandsIter = additionalCommands.iterator();
while (addCommandsIter.hasNext()) {
Object additionalCommand = addCommandsIter.next();
if (additionalCommand instanceof RemoveCommand) {
if (((RemoveCommand)additionalCommand).getOwner().equals(((RemoveCommand)command).getOwner())
&& ((RemoveCommand)additionalCommand).getCollection().size() == ((RemoveCommand)command).getCollection().size()
&& ((RemoveCommand)additionalCommand).getCollection().containsAll(((RemoveCommand)command).getCollection())) {
/*
* Already added this Command
*/
addCommand = false;
break;
}
}
}
if (addCommand) additionalCommands.add(command);
} else {
additionalCommands.add(command); // This is not a RemoveCommand, go ahead and add it.
}
}
}
/**
* Find related objects to the objects in the objects list and return them.
*
* @param objects the EObjects to the find related objects to
* @param editingDomain the editing domain
* @return the list of all objects that are related to the original object or a member of the list of objects.
*/
@Override
public List findRelatedObjects( final Collection objects,
final EditingDomain domain ) {
if (domain instanceof ContainerEditingDomain) {
// ------------------------------------------------------
// Now, see if there are additional things to be done ...
// ------------------------------------------------------
// Iterate through the original objects, and find any additional objects that should be copied ...
final FindRelatedObjectsToBeCopied visitor = new FindRelatedObjectsToBeCopied();
final ModelVisitorProcessor processor = new ModelVisitorProcessor(visitor);
try {
processor.walk(objects, ModelVisitorProcessor.DEPTH_INFINITE);
} catch (ModelerCoreException e) {
ModelerCore.Util.log(e);
}
// See if there are any additional objects to be copied ...
return new ArrayList(visitor.getAdditionalObjects());
}
return Collections.EMPTY_LIST;
}
/**
* Find external references to the deleted objects. The method will process the original model and all imported models
* checking for references to either the original object being deleted or one of the members contained in the list of objects
* being deleted.
*
* @param eObject the original object that is being deleted; never null
* @param allDeleted the Collection of all related objects that are being deleted
* @return the Collection of all objects that reference the original object or a member of the list of deleted objects.
*/
@Override
public Collection findExternalReferencesToObjectsBeingDeleted( final EObject eObject,
final Collection allDeleted ) {
CoreArgCheck.isNotNull(eObject);
final Resource resource = eObject.eResource();
if (resource == null) {
return Collections.EMPTY_LIST;
}
// Create a list of all deleted objects, including the original object
final Collection allDeletedObjects = (allDeleted == null ? new HashSet() : new HashSet(allDeleted));
if (!allDeletedObjects.contains(eObject)) {
allDeletedObjects.add(eObject);
}
// Find all the external references ...
final FindReferencesToDeletedObjects visitor = new FindReferencesToDeletedObjects(allDeleted);
final ModelVisitorProcessor processor = new ModelVisitorProcessor(visitor);
try {
processor.walk(resource, ModelVisitorProcessor.DEPTH_INFINITE);
} catch (Throwable t) {
ModelerCore.Util.log(IStatus.ERROR, t, t.getMessage());
}
return visitor.getReferencesToDeletedObjects();
}
/**
* Find related objects to be deleted. This method only processes the same model in which the deleted object exists.
*
* @param eObject the original object that is being deleted; never null
* @return the Collection of all objects that are being deleted
*/
protected Collection findOtherObjectsToBeDeleted( final EObject eObject,
ModelWorkspaceSearch workspaceSearch ) throws ModelerCoreException {
CoreArgCheck.isNotNull(eObject);
final ContainerImpl cntr = getContainer();
final EditingDomain ed = cntr.getEditingDomain();
final LinkedList additionalCommands = new LinkedList();
return findOtherObjectsToBeDeleted(Collections.singleton(eObject), ed, additionalCommands, workspaceSearch);
}
/**
* Find related objects to be deleted. This method only processes the same model in which the deleted object exists.
*
* @param eObject the original object that is being deleted; never null
* @return the Collection of all objects that are being deleted
*/
@Override
public Collection findOtherObjectsToBeDeleted( final EObject eObject ) throws ModelerCoreException {
CoreArgCheck.isNotNull(eObject);
final ContainerImpl cntr = getContainer();
final EditingDomain ed = cntr.getEditingDomain();
final LinkedList additionalCommands = new LinkedList();
final boolean ignoreXsdResources = !includesXsdObject(eObject);
// Defect 22774 - Changed following call to new up a DeleteRelatedWorkspaceSearch to prevent searching xsd resources
// if no deleted objects are xsd objects. Improves performance.
ModelWorkspaceSearch search = new DeleteRelatedWorkspaceSearch(ignoreXsdResources);
return findOtherObjectsToBeDeleted(Collections.singleton(eObject), ed, additionalCommands, search);
}
/**
* Find related objects to be deleted. This method processes all models in which the object being deleted is referenced.
*
* @param eObject the original object that is being deleted; never null
* @param modelContents the {@link ModelContents} for the {@link Resource} that contains the EObject; never null
* @param editingDomain the editing domain; never null
* @param additionalCommands the list into which any additional delete commands should be placed; never null
* @return the collection of commands for all objects that are being deleted
*/
@Override
public Collection findOtherObjectsToBeDeleted( final Collection eObjects,
final EditingDomain editingDomain,
final List additionalCommands,
final ModelWorkspaceSearch workspaceSearch ) throws ModelerCoreException {
return findOtherObjectsToBeDeleted(eObjects,
editingDomain,
additionalCommands,
workspaceSearch,
new NullProgressMonitor());
}
/**
* Find related objects to be deleted. This method processes all models in which the object being deleted is referenced.
*
* @param eObject the original object that is being deleted; never null
* @param modelContents the {@link ModelContents} for the {@link Resource} that contains the EObject; never null
* @param editingDomain the editing domain; never null
* @param additionalCommands the list into which any additional delete commands should be placed; never null
* @return the collection of commands for all objects that are being deleted
*/
public Collection findOtherObjectsToBeDeleted( final Collection eObjects,
final EditingDomain editingDomain,
final List additionalCommands,
final ModelWorkspaceSearch workspaceSearch,
final IProgressMonitor monitor ) throws ModelerCoreException {
// collection to return:
Collection rv = new HashSet();
int iObj = 1;
int nObj = eObjects.size();
int halfWay = nObj / 2;
boolean pastHalfWay = false;
String startMessage = ModelerCore.Util.getString("ModelEditorImpl.searchingRelatedMsg") + CoreStringUtil.Constants.SPACE; //$NON-NLS-1$
String ofText = CoreStringUtil.Constants.DBL_SPACE
+ ModelerCore.Util.getString("ModelEditorImpl.ofText") + CoreStringUtil.Constants.SPACE; //$NON-NLS-1$
Iterator itor = eObjects.iterator();
while (itor.hasNext()) {
String message = startMessage + CoreStringUtil.Constants.DBL_SPACE + iObj + ofText + nObj;
iObj++;
monitor.subTask(message);
EObject eObject = (EObject)itor.next();
final Resource resource = eObject.eResource();
if (resource == null) {
continue;
}
// linked list of that would be updated by the visitor
// with the eObject to be deleted
final LinkedList objectsToDelete = new LinkedList();
// work on delegate not all eObjects have proxies, collections
// should have consistent versions for lookup
objectsToDelete.addFirst(eObject);
// Construct and use the visitor ...
final FindRelatedObjectsToDeleted visitor = new FindRelatedObjectsToDeleted(eObject, editingDomain, objectsToDelete,
getRemovedObjectsForCurrentTxn(),
workspaceSearch);
final ModelVisitorProcessor processor = new ModelVisitorProcessor(visitor);
// continue processing the list till there are
// no objects to be deleted
while (!objectsToDelete.isEmpty() && !monitor.isCanceled()) {
processor.walk((EObject)objectsToDelete.getFirst(), ModelVisitorProcessor.DEPTH_INFINITE);
}
if (!monitor.isCanceled()) {
// 12/17/03 (LLP) : changed to add new commands to additionalCommands list.
if (visitor.getAdditionalDeleteCommands() != null && !visitor.getAdditionalDeleteCommands().isEmpty()) {
additionalCommands.addAll(visitor.getAdditionalDeleteCommands());
}
rv.addAll(visitor.getAllDeletedObjects());
}
if (!pastHalfWay && iObj > halfWay) {
monitor.worked(10);
pastHalfWay = true;
}
} // endwhile
monitor.worked(10);
// System.out.println(" ModelEditorImpl.findOtherObjectsToBeDeleted() Found [" + deadEndObjs.size() + "] Dead End
// Objects");
if (monitor.isCanceled()) {
rv.clear();
}
return rv;
}
private Collection getRemovedObjectsForCurrentTxn() {
try {
final ContainerImpl container = getContainer();
final UnitOfWorkImpl uow = (UnitOfWorkImpl)container.getEmfTransactionProvider().getCurrent();
return uow.getRemovedEObjects();
} catch (Exception err) {
return new HashSet();
}
}
/**
* @see org.teiid.designer.core.ModelEditor#rename(org.eclipse.emf.ecore.EObject, java.lang.String)
*/
@Override
public boolean rename( final EObject eObject,
final String newName ) throws ModelerCoreException {
CoreArgCheck.isNotNull(eObject);
final EStructuralFeature nameFeature = getNameFeature(eObject);
if (nameFeature == null) {
return false;
}
final boolean isSignificant = true;
final String operationDescription = ModelerCore.Util.getString("ModelEditorImpl.Rename_{0}_6", getPresentationValue(eObject)); //$NON-NLS-1$
final ContainerImpl cntr = getContainer();
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) throws ModelerCoreException {
final EditingDomain ed = cntr.getEditingDomain();
Command command = SetCommand.create(ed, eObject, nameFeature, newName);
executeCommandInTransaction(uow, eObject, command);
return null;
}
};
executeAsTransaction(runnable, cntr, operationDescription, isSignificant, this);
return true;
}
/**
* This method currently looks for a feature with a name that case-insensitively matches "name".
*
* @see org.teiid.designer.core.ModelEditor#getNameFeature(org.eclipse.emf.ecore.EObject)
*/
@Override
public EStructuralFeature getNameFeature( final EObject eObject ) {
return ModelUtil.getNameFeature(eObject);
}
/**
* @see org.teiid.designer.core.ModelEditor#getName(org.eclipse.emf.ecore.EObject)
*/
@Override
public String getName( final EObject eObject ) {
return ModelUtil.getName(eObject);
}
/**
* @see org.teiid.designer.core.ModelEditor#hasName(org.eclipse.emf.ecore.EObject)
*/
@Override
public boolean hasName( final EObject eObject ) {
CoreArgCheck.isNotNull(eObject);
final EStructuralFeature nameFeature = getNameFeature(eObject);
return nameFeature != null;
}
/**
* @see org.teiid.designer.core.ModelEditor#rename(org.eclipse.emf.ecore.resource.Resource, org.eclipse.emf.ecore.EObject,
* java.lang.String)
*/
protected boolean renameInternal( final EObject eObject,
final String newName ) {
CoreArgCheck.isNotNull(eObject);
final EStructuralFeature nameFeature = getNameFeature(eObject);
if (nameFeature != null) {
generateUniqueInternalName(eObject.eContainer() == null ? eObject.eResource().getContents() : eObject.eContainer().eContents(),
eObject,
nameFeature,
newName);
return true;
}
return false;
}
private void generateUniqueInternalName( final EList siblings,
final EObject eObject,
final EStructuralFeature nameFeature,
final String name ) {
String newName = name;
if (siblings != null && eObject.eGet(nameFeature) == null) {
final Set siblingNames = new HashSet();
for (Iterator it = siblings.iterator(); it.hasNext();) {
final EObject child = (EObject)it.next();
if (eObject.getClass().equals(child.getClass())) {
siblingNames.add(child.eGet(nameFeature));
}
}
boolean foundUniqueName = false;
int index = 1;
while (!foundUniqueName) {
if (siblingNames.contains(newName)) {
newName = name + String.valueOf(index++);
} else {
foundUniqueName = true;
}
}
}
eObject.eSet(nameFeature, newName);
}
/**
* @see org.teiid.designer.core.ModelEditor#executeCommand(org.eclipse.emf.common.command.Command)
*/
@Override
public void executeCommand( final EObject owner,
final Command cmd ) throws ModelerCoreException {
final boolean isSignificant = true;
final String operationDescription = null;
final ContainerImpl cntr = getContainer();
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) throws ModelerCoreException {
executeCommandInTransaction(uow, owner, cmd);
return null;
}
};
executeAsTransaction(runnable, cntr, operationDescription, isSignificant, this);
}
/**
* Should only be called by the model container's EMF content adapter.
* @param owner command owner
* @param cmd command to be post executed
* @throws ModelerCoreException
*
* @see org.teiid.designer.core.ModelEditor#executeCommand(org.eclipse.emf.ecore.EObject,
* org.eclipse.emf.common.command.Command)
* @since 5.0.3
*/
public void postExecuteCommand( final EObject owner,
final Command cmd ) throws ModelerCoreException {
executeAsTransaction(new TransactionRunnable() {
@Override
public Object run( UnitOfWork uow ) throws ModelerCoreException {
executeCommandInTransaction(uow, owner, cmd);
return null;
}
}, getContainer(), null, true, this);
}
/**
* Executes a command in the context of an existing transaction ...
*
* @param owner
* @param cmd
* @param operationDescription
* @throws ModelerCoreException
*/
protected void executeCommandInTransaction( final UnitOfWork uow,
final Object owner,
final Command cmd ) throws ModelerCoreException {
CoreArgCheck.isNotNull(uow);
if (cmd == null || !cmd.canExecute()) {
final String nullMsg = ModelerCore.Util.getString("ModelEditorImpl.Can_not_execute_a_null_command_1"); //$NON-NLS-1$
final String reason = cmd == null ? nullMsg : getCmdFailureReason(cmd);
throw new ModelerCoreException(ModelerCore.Util.getString("ModelEditorImpl.Unable_to_execute_Command_1", reason)); //$NON-NLS-1$
}
// Execute the command ...
uow.executeCommand(cmd);
}
protected String getCmdFailureReason( final Command cmd ) {
final StringBuffer failures = new StringBuffer();
failures.append(cmd.toString());
try {
if (cmd instanceof CompoundCommand && !cmd.canExecute()) {
failures.append(ModelerCore.Util.getString("ModelEditorImpl.Compound_Command_with_unexecutable_children_1")); //$NON-NLS-1$
} else if (cmd instanceof AddCommand && !cmd.canExecute()) {
final AddCommand add = (AddCommand)cmd;
if (add.getOwnerList() == null || add.getCollection() == null || add.getCollection().size() == 0
|| add.getIndex() != CommandParameter.NO_INDEX
&& (add.getIndex() < 0 || add.getIndex() > add.getOwnerList().size())) {
// Verify index is valid
failures.append(ModelerCore.Util.getString("ModelEditorImpl.Invalid_index_for_Add_operation_2")); //$NON-NLS-1$
return failures.toString();
}
// Check that each object conforms to the requirements of the owner list.
//
for (Iterator objects = add.getCollection().iterator(); objects.hasNext();) {
Object object = objects.next();
if (add.getFeature() != null && !add.getFeature().getEType().isInstance(object)) {
failures.append(ModelerCore.Util.getString("ModelEditorImpl._nCan_not_add_item_of_type_{0}_to_feature_{1}_3", object.getClass().getName(), add.getFeature().getName())); //$NON-NLS-1$
}
}
// Check to see if a container is being put into a contained object.
//
if (add.getFeature() instanceof EReference && ((EReference)add.getFeature()).isContainment()) {
for (EObject container = add.getOwner(); container != null; container = container.eContainer()) {
if (add.getCollection().contains(container)) {
failures.append(ModelerCore.Util.getString("ModelEditorImpl._nCan_not_add_object_to_a_contained_object_4")); //$NON-NLS-1$
return failures.toString();
}
}
}
} else if (cmd instanceof CopyToClipboardCommand && !cmd.canExecute()) {
if (((CopyToClipboardCommand)cmd).getSourceObjects() == null) {
failures.append(ModelerCore.Util.getString("ModelEditorImpl._nSource_Objects_collection_may_not_be_null_for_Copy_operation_5")); //$NON-NLS-1$
} else if (((CopyToClipboardCommand)cmd).getSourceObjects().isEmpty()) {
failures.append(ModelerCore.Util.getString("ModelEditorImpl._nSource_Objects_collection_may_not_be_empty_for_Copy_operation_6")); //$NON-NLS-1$
} else {
failures.append(ModelerCore.Util.getString("ModelEditorImpl._nUnable_to_execute_copy_to_clipboard_command_7")); //$NON-NLS-1$
}
} else if (cmd instanceof CommandWrapper && !cmd.canExecute()) {
final Command tmp = ((CommandWrapper)cmd).getCommand();
if (tmp != null && tmp != UnexecutableCommand.INSTANCE) {
return getCmdFailureReason(tmp);
}
failures.append(ModelerCore.Util.getString("ModelEditorImpl._nWrapped_command_may_not_be_null_or_Unexecutable_8")); //$NON-NLS-1$
} else if (cmd instanceof CreateCopyCommand && !cmd.canExecute()) {
if (((CreateCopyCommand)cmd).getOwner() == null) {
failures.append(ModelerCore.Util.getString("ModelEditorImpl._nCan_not_create_copy_of_NULL_object_9")); //$NON-NLS-1$
} else {
failures.append(ModelerCore.Util.getString("ModelEditorImpl._nUnexecutable_Create_Copy_command_10")); //$NON-NLS-1$
}
} else if (cmd instanceof MoveCommand && !cmd.canExecute()) {
final MoveCommand tmp = (MoveCommand)cmd;
if (tmp.getOwnerList() == null) {
failures.append(ModelerCore.Util.getString("ModelEditorImpl._nOwner_list_may_not_be_null_for_a_Move_Command_11")); //$NON-NLS-1$
} else if (!tmp.getOwnerList().contains(tmp.getValue())) {
failures.append(ModelerCore.Util.getString("ModelEditorImpl._nOwner_list_must_contain_value_for_a_Move_Command_12")); //$NON-NLS-1$
} else if (tmp.getIndex() < tmp.getOwnerList().size()) {
failures.append(ModelerCore.Util.getString("ModelEditorImpl._nInvalid_index_for_Move_Command_13")); //$NON-NLS-1$
} else {
failures.append(ModelerCore.Util.getString("ModelEditorImpl._nUnexpected_failure_for_Move_Command_14")); //$NON-NLS-1$
}
} else if (cmd instanceof PasteFromClipboardCommand && !cmd.canExecute()) {
final PasteFromClipboardCommand tmp = (PasteFromClipboardCommand)cmd;
final Collection copies = tmp.getChildrenToCopy();
if (copies == null || copies.isEmpty()) {
failures.append(ModelerCore.Util.getString("ModelEditorImpl._nNo_objects_found_to_paste_15")); //$NON-NLS-1$
return failures.toString();
} else if (tmp.getFeature() != null && tmp.getFeature() instanceof EStructuralFeature) {
final EStructuralFeature feature = (EStructuralFeature)tmp.getFeature();
// Check that each object conforms to the requirements of the owner list.
//
for (Iterator objects = copies.iterator(); objects.hasNext();) {
Object object = objects.next();
if (!feature.getEType().isInstance(object)) {
failures.append(ModelerCore.Util.getString("ModelEditorImpl._nCan_not_paste_item_of_type_{0}_to_feature_{1}_16", object.getClass().getName(), feature.getName())); //$NON-NLS-1$
}
}
}
// Check to see if a container is being put into a contained object.
//
if (tmp.getOwner() instanceof EObject && tmp.getFeature() instanceof EReference
&& ((EReference)tmp.getFeature()).isContainment()) {
for (EObject container = (EObject)tmp.getOwner(); container != null; container = container.eContainer()) {
if (copies.contains(container)) {
failures.append(ModelerCore.Util.getString("ModelEditorImpl._nCan_not_add_object_to_a_contained_object_17")); //$NON-NLS-1$
return failures.toString();
}
}
}
if (failures.length() == 0) {
failures.append(ModelerCore.Util.getString("ModelEditorImpl._nUnexecutable_Paste_From_Clipboard_command_18")); //$NON-NLS-1$
}
} else if (cmd instanceof RemoveCommand && !cmd.canExecute()) {
RemoveCommand removeCmd = (RemoveCommand)cmd;
// Owner list must not be null and must contain all values in collection
if (removeCmd.getOwnerList() == null) {
failures.append(ModelerCore.Util.getString("ModelEditorImpl._nOwner_list_may_not_be_null_19")); //$NON-NLS-1$
} else if (!removeCmd.getOwnerList().containsAll(removeCmd.getCollection())) {
failures.append(ModelerCore.Util.getString("ModelEditorImpl._nOwner_list_must_contain_all_values_to_be_removed_20")); //$NON-NLS-1$
}
if (failures.length() == 0) {
failures.append(ModelerCore.Util.getString("ModelEditorImpl._nUnexecutable_Remove_command_21")); //$NON-NLS-1$
}
} else if (cmd instanceof SetCommand && !cmd.canExecute()) {
final SetCommand tmp = (SetCommand)cmd;
final EObject owner = tmp.getOwner();
final EStructuralFeature feature = tmp.getFeature();
final Object value = tmp.getValue();
if (feature == null) {
failures.append(ModelerCore.Util.getString("ModelEditorImpl._nCan_not_set_value_on_null_feature_22")); //$NON-NLS-1$
return failures.toString();
}
if (owner == null) {
failures.append(ModelerCore.Util.getString("ModelEditorImpl._nCan_not_set_value_on_null_owner_23")); //$NON-NLS-1$
return failures.toString();
}
// Get the owner's meta object.
//
EClass eMetaObject = owner.eClass();
// Is the feature an attribute of the owner...
//
if (eMetaObject.getEAllAttributes().contains(feature)) {
// If must be of this type then.
//
EAttribute eAttribute = (EAttribute)feature;
EClassifier eType = eAttribute.getEType();
if (eAttribute.isMany()) {
if (value instanceof EList) {
EList list = (EList)value;
for (Iterator objects = list.iterator(); objects.hasNext();) {
Object next = objects.next();
if (!eType.isInstance(next)) {
failures.append(ModelerCore.Util.getString("ModelEditorImpl._nCan_not_add_object_of_type_{0}_to_feature_{1}_24", next.getClass().getName(), tmp.getFeature().getName())); //$NON-NLS-1$
}
}
}
}// end isMany
}
// Is the feature a reference of the owner...
//
else if (eMetaObject.getEAllReferences().contains(feature)) {
// It must be of this type.
//
EReference eReference = (EReference)feature;
// Make sure it's a single-valued relation (multi-valued is not supported).
//
if (!eReference.isMany()) {
// We want to make sure the object is of a type compatible with the type of the reference.
//
if (value == null || eReference.getEType().isInstance(value)) {
// Check to see if the container is being put into a contained object
//
if (eReference.isContainment()) {
for (EObject container = owner; container != null; container = container.eContainer()) {
if (value == container) {
failures.append(ModelerCore.Util.getString("ModelEditorImpl._nMay_not_add_value_to_contained_object_25")); //$NON-NLS-1$
break;
}
}
}// end isContainment
}
}// end if isMany
}
if (failures.length() == 0) {
failures.append(ModelerCore.Util.getString("ModelEditorImpl._nUnexpected_failure_executing_Set_command_26")); //$NON-NLS-1$
}
}
} catch (Exception e) {
// Do nothing... return default message
}
if (failures.length() == 0) {
failures.append(ModelerCore.Util.getString("ModelEditorImpl._nUnexpected_failure_executing_command___Command_not_executable_27")); //$NON-NLS-1$
}
return failures.toString();
}
/**
* @see org.teiid.designer.core.ModelEditor#move(org.eclipse.emf.ecore.EObject, org.eclipse.emf.ecore.EObject)
*/
@Override
public boolean move( final Object newParent,
final EObject eObject ) throws ModelerCoreException {
CoreArgCheck.isNotNull(newParent);
CoreArgCheck.isNotNull(eObject);
if (!isValidParent(newParent, eObject)) {
throw new ModelerCoreException(ModelerCore.Util.getString("ModelEditorImpl.Invalid_parent_for_child_encountered_1")); //$NON-NLS-1$
}
int index = 0;
if (newParent instanceof EObject) {
final EObject eParent = (EObject)newParent;
EReference ref = getChildReference(eParent, eObject);
if (ref != null && ref.isMany()) {
if (eParent.eGet(ref) instanceof EList) {
index = ((EList)eParent.eGet(ref)).size();
}
}
} else if (newParent instanceof Resource) {
index = ((Resource)newParent).getContents().size();
}
return move(newParent, eObject, index);
}
@Override
public boolean move( final Object newParent,
final EObject eObject,
final int index ) throws ModelerCoreException {
CoreArgCheck.isNotNull(newParent);
CoreArgCheck.isNotNull(eObject);
if (!isValidParent(newParent, eObject)) {
throw new ModelerCoreException(ModelerCore.Util.getString("ModelEditorImpl.Invalid_parent_for_child_encountered_1")); //$NON-NLS-1$
}
final boolean isSignificant = true;
final String operationDescription = ModelerCore.Util.getString("ModelEditorImpl.Move_{0}_7", getPresentationValue(eObject)); //$NON-NLS-1$
final ContainerImpl cntr = getContainer();
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) throws ModelerCoreException {
final EditingDomain ed = cntr.getEditingDomain();
Command command = null;
if (eObject.eContainer() != null && eObject.eContainer() == newParent) {
command = MoveCommand.create(ed, newParent, null, eObject, index);
} else {
if (eObject.eContainer() != null) {
command = RemoveCommand.create(ed, eObject.eContainer(), eObject.eContainmentFeature(), eObject);
executeCommandInTransaction(uow, eObject, command);
}
command = AddCommand.create(ed, newParent, null, eObject, index);
}
executeCommandInTransaction(uow, newParent, command);
return null;
}
};
executeAsTransaction(runnable, cntr, operationDescription, isSignificant, this);
return true;
}
/**
* @see org.teiid.designer.core.ModelEditor#copyToClipboard
*/
@Override
public void copyToClipboard( final EObject eObject ) throws ModelerCoreException {
CoreArgCheck.isNotNull(eObject);
Collection objects = new ArrayList(1);
objects.add(eObject);
copyAllToClipboard(objects);
}
/**
* @see org.teiid.designer.core.ModelEditor#copyAllToClipboard
*/
@Override
public void copyAllToClipboard( final Collection eObjects ) throws ModelerCoreException {
CoreArgCheck.isNotEmpty(eObjects);
final EObject eObject = (EObject)eObjects.iterator().next();
final boolean isSignificant = false;
final String operationDescription = ModelerCore.Util.getString("ModelEditorImpl.Copy_{0}_8", getPresentationValue(eObjects)); //$NON-NLS-1$
final ContainerImpl cntr = getContainer();
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) throws ModelerCoreException {
final EditingDomain ed = cntr.getEditingDomain();
final Command command = CopyToClipboardCommand.create(ed, eObjects);
executeCommandInTransaction(uow, eObject, command);
return null;
}
};
executeAsTransaction(runnable, cntr, operationDescription, isSignificant, this);
}
/**
* @see org.teiid.designer.core.ModelEditor#cutToClipboard
*/
@Override
public void cutToClipboard( final EObject eObject ) throws ModelerCoreException {
CoreArgCheck.isNotNull(eObject);
Collection objects = new ArrayList(1);
objects.add(eObject);
cutAllToClipboard(objects);
}
/**
* @see org.teiid.designer.core.ModelEditor#cutAllToClipboard
*/
@Override
public void cutAllToClipboard( final Collection eObjects ) throws ModelerCoreException {
CoreArgCheck.isNotEmpty(eObjects);
final EObject eObject = (EObject)eObjects.iterator().next();
final boolean isSignificant = true;
final String operationDescription = ModelerCore.Util.getString("ModelEditorImpl.Cut_{0}_9", getPresentationValue(eObjects)); //$NON-NLS-1$
final ContainerImpl cntr = getContainer();
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) throws ModelerCoreException {
final EditingDomain ed = cntr.getEditingDomain();
final CompoundCommand command = CompoundCommandFactory.create(eObjects, new ArrayList(1));
command.append(CutToClipboardCommand.create(ed, eObjects));
executeCommandInTransaction(uow, eObject, command);
return null;
}
};
executeAsTransaction(runnable, cntr, operationDescription, isSignificant, this);
}
/**
* @see org.teiid.designer.core.ModelEditor#pasteFromClipboard
*/
@Override
public boolean pasteFromClipboard( final Object owner ) throws ModelerCoreException {
CoreArgCheck.isNotNull(owner);
final boolean isSignificant = true;
final String operationDescription = ModelerCore.Util.getString("ModelEditorImpl.Paste_{0}_10", getPresentationValue(owner)); //$NON-NLS-1$
final ContainerImpl cntr = getContainer();
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) throws ModelerCoreException {
final EditingDomain ed = cntr.getEditingDomain();
final Object realOwner = owner instanceof ModelResource ? ((ModelResource)owner).getEmfResource() : owner;
final Command command = PasteFromClipboardCommand.create(ed, realOwner, null);
executeCommandInTransaction(uow, realOwner, command);
return null;
}
};
executeAsTransaction(runnable, cntr, operationDescription, isSignificant, this);
return true;
}
/**
* @see org.teiid.designer.core.ModelEditor#getClipboardContents
*/
@Override
public Collection getClipboardContents( final Object target ) {
try {
final ContainerImpl cntr = getContainer();
final EditingDomain ed = cntr.getEditingDomain();
final Collection content = ed.getClipboard();
// have to check - getClipboard can return null
if (content != null) {
return Collections.unmodifiableCollection(ed.getClipboard());
}
return Collections.EMPTY_LIST;
} catch (Exception e) {
return Collections.EMPTY_LIST;
}
}
/**
* @see org.teiid.designer.core.ModelEditor#getClipboardContentsOriginalToCopyMapping(java.lang.Object)
*/
@Override
public Map getClipboardContentsOriginalToCopyMapping( Object target ) {
try {
final ContainerImpl cntr = getContainer();
final EditingDomain ed = cntr.getEditingDomain();
if (ed instanceof ContainerEditingDomain) {
final ContainerEditingDomain ced = (ContainerEditingDomain)ed;
return ced.getClipboardContentsOriginalToCopyMapping();
}
} catch (Exception e) {
return null;
}
return null;
}
/**
* @see org.teiid.designer.core.ModelEditor#getClipboardContentsCopyToOriginalMapping(java.lang.Object)
*/
@Override
public Map getClipboardContentsCopyToOriginalMapping( Object target ) {
final Map originalToCopy = getClipboardContentsOriginalToCopyMapping(target);
if (originalToCopy != null) {
final Map copyToOriginal = new HashMap();
final Iterator iter = originalToCopy.entrySet().iterator();
while (iter.hasNext()) {
final Map.Entry entry = (Map.Entry)iter.next();
final Object copy = entry.getValue();
final Object orig = entry.getKey();
copyToOriginal.put(copy, orig);
}
return copyToOriginal;
}
return null;
}
/**
* @see org.teiid.designer.core.ModelEditor#copyAll(java.util.Collection)
*/
@Override
public Collection copyAll( final Collection eObjects ) throws ModelerCoreException {
if (eObjects == null || eObjects.isEmpty()) {
return Collections.EMPTY_LIST;
}
return copyAll(eObjects, null);
}
/**
* @see org.teiid.designer.core.ModelEditor#copyAll(java.util.Collection)
*/
@Override
public Collection copyAll( final Collection eObjects,
final Map originalsToCopies ) throws ModelerCoreException {
if (eObjects == null || eObjects.isEmpty()) {
return Collections.EMPTY_LIST;
}
final EObject eObject = (EObject)eObjects.iterator().next();
final boolean isSignificant = true;
final String operationDescription = ModelerCore.Util.getString("ModelEditorImpl.Copy_{0}_11", getPresentationValue(eObjects)); //$NON-NLS-1$
final ContainerImpl cntr = getContainer();
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) throws ModelerCoreException {
final EditingDomain ed = cntr.getEditingDomain();
final CopyCommand.Helper helper = new CopyCommand.Helper();
if (originalsToCopies != null && !originalsToCopies.isEmpty()) {
// copy all of the existing entries in the 'originalsToCopies' map into the helper ...
// This will change the copies to reference other copies that may have been created
// already and are in the map, but are not directly in the graph of contained objects
// below the 'eObjects' originals
for (final Iterator iter = originalsToCopies.entrySet().iterator(); iter.hasNext();) {
Map.Entry entry = (Map.Entry)iter.next();
// putAll does not initialize the collection on the helper
helper.put((EObject)entry.getKey(), (EObject)entry.getValue());
}
helper.putAll(originalsToCopies);
}
final Command command = createCopyCommand(ed, eObjects, helper);
executeCommandInTransaction(uow, eObject, command);
// Set the uuid on all applicable copies
for (final Iterator copies = command.getResult().iterator(); copies.hasNext();) {
Object next = copies.next();
if (next instanceof EObject) {
setUuidFeatureValue((EObject)next);
}
}
// Populate the map from orig to copies
if (originalsToCopies != null) originalsToCopies.putAll(helper);
return command.getResult();
}
};
final Collection result = (Collection)executeAsTransaction(runnable, cntr, operationDescription, isSignificant, this);
return result;
}
/**
* Tries to add the given value to the given EObject's feature
*
* @param eObject to add new value : may not be null
* @param value to add - May be a list or single item, but may not be null
* @param feature EList from eObject to add value, may not be null
* @return
* @throws ModelerCoreException if there is an error executing the command
*/
@Override
public void addValue( final Object owner,
final Object value,
final EList feature ) throws ModelerCoreException {
addValue(owner, value, feature, CommandParameter.NO_INDEX);
}
/**
* Tries to add the given value to the given EObject's feature
*
* @param eObject to add new value : may not be null
* @param value to add - May be a list or single item, but may not be null
* @param feature EList from eObject to add value, may not be null
* @param index position to insert the element into the collection standard Eclipse AddCommand
* @return
* @throws ModelerCoreException if there is an error executing the command
*/
@Override
public void addValue( final Object owner,
final Object value,
final EList feature,
final int index ) throws ModelerCoreException {
CoreArgCheck.isNotNull(owner);
CoreArgCheck.isNotNull(value);
CoreArgCheck.isNotNull(feature);
// convert the value into a collection
final Collection values = new ArrayList();
if (value instanceof Collection) {
values.addAll((Collection)value);
} else {
values.add(value);
}
final ContainerImpl cntr = getContainer();
if (cntr == null) {
feature.add(index, values);
} else {
final boolean isSignificant = true;
final String operationDescription = ModelerCore.Util.getString("ModelEditorImpl.Add_values_to_{0}_1", getPresentationValue(owner)); //$NON-NLS-1$
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) throws ModelerCoreException {
final EditingDomain ed = cntr.getEditingDomain();
Command command = AddCommandFactory.create(owner, ed, feature, values, index);
executeCommandInTransaction(uow, owner, command);
return null;
}
};
executeAsTransaction(runnable, cntr, operationDescription, isSignificant, this);
}
}
/**
* Tries to add the given value to the given map with the given key
*
* @param eObject : may not be null
* @param map to add key/value pair - may not be null
* @param key to add - May be null (depends on map implementation)
* @param value to add - May be null (depends on map implementation)
* @return
* @throws ModelerCoreException if there is an error executing the command
*/
@Override
public void addMapValue( final Object owner,
final Map map,
final Object key,
final Object value ) throws ModelerCoreException {
CoreArgCheck.isNotNull(owner);
CoreArgCheck.isNotNull(map);
final ContainerImpl cntr = getContainer();
if (cntr == null) {
map.put(key, value);
} else {
// setting isSignificant to FALSE since we do not want to see this low-level operation in the undo stack
final boolean isSignificant = false;
final String operationDescription = ModelerCore.Util.getString("ModelEditorImpl.Add_value_to_map_for_{0}", getPresentationValue(owner)); //$NON-NLS-1$
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) throws ModelerCoreException {
final EditingDomain ed = cntr.getEditingDomain();
final AddValueToMapCommand command = new AddValueToMapCommand(ed, owner, map, key, value);
executeCommandInTransaction(uow, owner, command);
return null;
}
};
executeAsTransaction(runnable, cntr, operationDescription, isSignificant, this);
}
}
/**
* Tries to remove the given value from the given EObject's feature
*
* @param eObject to remove new value from : may not be null
* @param value to remove - May be a list or single item, but may not be null
* @param feature EList from eObject to remove value, may not be null
* @return
* @throws ModelerCoreException if there is an error executing the command
*/
@Override
public void removeValue( final Object owner,
final Object value,
final EList feature ) throws ModelerCoreException {
CoreArgCheck.isNotNull(owner);
CoreArgCheck.isNotNull(value);
CoreArgCheck.isNotNull(feature);
// convert the value into a collection
final Collection values = new ArrayList();
if (value instanceof Collection) {
values.addAll((Collection)value);
} else {
values.add(value);
}
final ContainerImpl cntr = getContainer();
if (cntr == null) {
feature.remove(values);
} else {
final boolean isSignificant = true;
final String operationDescription = ModelerCore.Util.getString("ModelEditorImpl.Remove_values_from_{0}_1", getPresentationValue(owner)); //$NON-NLS-1$
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) throws ModelerCoreException {
final EditingDomain ed = cntr.getEditingDomain();
final RemoveCommand command = new RemoveCommand(ed, feature, values);
executeCommandInTransaction(uow, owner, command);
return null;
}
};
executeAsTransaction(runnable, cntr, operationDescription, isSignificant, this);
}
}
/**
* Tries to remove the value associated with the given key from the given map
*
* @param eObject : may not be null
* @param map to remove key/value pair - may not be null
* @param key to add - May be null (depends on map implementation)
* @param isSignificant - whether this action will be seen in the edit menu as undoable
* @return
* @throws ModelerCoreException if there is an error executing the command
*/
@Override
public void removeMapValue( final Object owner,
final Map map,
final Object key ) throws ModelerCoreException {
CoreArgCheck.isNotNull(owner);
CoreArgCheck.isNotNull(map);
final ContainerImpl cntr = getContainer();
if (cntr == null) {
map.remove(key);
} else {
// setting isSignificant to FALSE since we do not want to see this low-level operation in the undo stack
final boolean isSignificant = false;
final String operationDescription = ModelerCore.Util.getString("ModelEditorImpl.Remove_value_from_map_for_{0}", getPresentationValue(owner)); //$NON-NLS-1$
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) throws ModelerCoreException {
final EditingDomain ed = cntr.getEditingDomain();
final RemoveValueFromMapCommand command = new RemoveValueFromMapCommand(ed, owner, map, key);
executeCommandInTransaction(uow, owner, command);
return null;
}
};
executeAsTransaction(runnable, cntr, operationDescription, isSignificant, this);
}
}
/**
* @see org.teiid.designer.core.ModelEditor#setPropertyValue(org.eclipse.emf.ecore.EObject, java.lang.Object,
* org.eclipse.emf.edit.provider.ItemPropertyDescriptor)
*/
@Override
public boolean setPropertyValue( final EObject eObject,
final Object value,
final ItemPropertyDescriptor descriptor ) {
if (eObject == null || descriptor == null) {
return false;
}
// Set the property value via the EMF Command framework which allows
// the operation to be undone.
return this.setPropertyValue(eObject, value, descriptor.getFeature(eObject));
}
/**
* Tries to set the given values on a simple datatype's enterprise extensions
*
* @param owner - the owning EObject for the dom node.
* @param value - Should be an instanceof EnterpriseDatatypeInfo
* @return true if successful
*/
@Override
public boolean setEnterpriseDatatypePropertyValue( final EObject owner,
final Object object ) {
if (owner == null || object == null || !(owner instanceof XSDSimpleTypeDefinition)
|| !(object instanceof EnterpriseDatatypeInfo)) {
return false;
}
final XSDSimpleTypeDefinition simpleType = (XSDSimpleTypeDefinition)owner;
final EnterpriseDatatypeInfo newEdtInfo = (EnterpriseDatatypeInfo)object;
final EnterpriseDatatypeInfo oldEdtInfo = ModelerCore.getDatatypeManager(simpleType).getEnterpriseDatatypeInfo(simpleType);
if (newEdtInfo.equals(oldEdtInfo)) {
return false;
}
fillWithDefaultValues(newEdtInfo, simpleType);
final ContainerImpl cntr = getContainer();
final boolean isSignificant = true;
final String operationDescription = ModelerCore.Util.getString("ModelEditorImpl.Set_{0}_1", object.toString()); //$NON-NLS-1$
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) throws ModelerCoreException {
final EditingDomain ed = cntr.getEditingDomain();
Command cmd = new EnterpriseDatatypeInfoSetCommand(ed, simpleType, newEdtInfo, oldEdtInfo);
executeCommandInTransaction(uow, object, cmd);
return null;
}
};
try {
executeAsTransaction(runnable, cntr, operationDescription, isSignificant, this);
} catch (ModelerCoreException e) {
ModelerCore.Util.log(IStatus.ERROR, e, e.getMessage());
return false;
}
return true;
}
/**
* Fix me: I'm in the wrong spot
*/
public static void fillWithDefaultValues( final EnterpriseDatatypeInfo newEdtInfo,
final XSDSimpleTypeDefinition simpleType ) {
if (newEdtInfo.getUuid() == null || newEdtInfo.getUuid().length() == 0) {
String objectID = ModelerCore.getObjectIdString(simpleType);
if (objectID != null) {
newEdtInfo.setUuid(objectID);
}
}
if (newEdtInfo.getRuntimeType() == null || newEdtInfo.getRuntimeType().length() == 0) {
newEdtInfo.setRuntimeType(EnterpriseDatatypeInfo.DEFAULT_RUNTIME_TYPE_VALUE);
}
if (newEdtInfo.getRuntimeTypeFixed() == null) {
newEdtInfo.setRuntimeTypeFixed(EnterpriseDatatypeInfo.DEFAULT_RUNTIME_TYPE_FIXED_VALUE);
}
}
/**
* Tries to clear out the given simple datatype's enterprise extensions
*
* @param owner - the owning EObject for the dom node.
* @return true if successful
*/
@Override
public boolean unsetEnterpriseDatatypePropertyValue( final EObject owner ) {
if (owner == null || !(owner instanceof XSDSimpleTypeDefinition)) {
return false;
}
final XSDSimpleTypeDefinition simpleType = (XSDSimpleTypeDefinition)owner;
final EnterpriseDatatypeInfo oldEdtInfo = ModelerCore.getDatatypeManager(simpleType).getEnterpriseDatatypeInfo(simpleType);
final ContainerImpl cntr = getContainer();
final boolean isSignificant = true;
final String operationDescription = ModelerCore.Util.getString("ModelEditorImpl.Set_{0}_1", owner.toString()); //$NON-NLS-1$
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) throws ModelerCoreException {
final EditingDomain ed = cntr.getEditingDomain();
Command cmd = new EnterpriseDatatypeInfoUnsetCommand(ed, simpleType, oldEdtInfo);
executeCommandInTransaction(uow, owner, cmd);
return null;
}
};
try {
executeAsTransaction(runnable, cntr, operationDescription, isSignificant, this);
} catch (ModelerCoreException e) {
ModelerCore.Util.log(IStatus.ERROR, e, e.getMessage());
return false;
}
return true;
}
/**
* Tries to set the given value on the given eObjects sf that corresponds to the propertyID
*
* @param eObject
* @param value
* @param propertyID String name of the sf
* @return true if successful
*/
@Override
public boolean setPropertyValue( final EObject eObject,
final Object value,
final Object feature ) {
if (eObject == null || feature == null || !(feature instanceof EStructuralFeature)) {
return false;
}
final EStructuralFeature sf = (EStructuralFeature)feature;
final boolean isSignificant = true;
final String operationDescription = ModelerCore.Util.getString("ModelEditorImpl.Set_{0}_1", sf.getName()); //$NON-NLS-1$
final ContainerImpl cntr = getContainer();
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) throws ModelerCoreException {
final EditingDomain ed = cntr.getEditingDomain();
if (sf.isMany()) {
// Compute which values in the newValue are added and which values in the
// existing value need to be removed.
final EList currentValues = (EList)eObject.eGet(sf);
final Collection addedValues = new ArrayList(currentValues.size());
final Collection removedValues = new ArrayList(currentValues.size());
Collection newValues = new ArrayList();
if (value instanceof Collection) {
newValues = (Collection)value;
} else {
newValues.add(value);
}
removedValues.addAll(currentValues);
addedValues.addAll(newValues);
// Clear all old values
if (!currentValues.isEmpty()) {
removeValue(eObject, removedValues, currentValues);
}
// Adds all new values
if (!addedValues.isEmpty()) {
addValue(eObject, addedValues, currentValues);
}
} else {
Object newValue = value;
// the value could be of the wrong type. if value is of type String
// try and convert it to the proper type before setting the feature.
if ((value != null) && (value instanceof String)) {
final EDataType dt = (EDataType)sf.getEType();
final EPackage ePackage = dt.getEPackage();
final EFactory fac = ePackage.getEFactoryInstance();
newValue = fac.createFromString(dt, (String)value);
}
// If owner EObject is an XSDParticle but the EStructuralFeature being modified
// belongs to the content of that XSDParticle and not the XSDParticle itself
// then reset the owner reference to the content EObject (see defect 21088)
EObject owner = eObject;
if (owner instanceof XSDParticle && !owner.eClass().getEAllStructuralFeatures().contains(sf)) {
XSDParticleContent particleContent = ((XSDParticle)owner).getContent();
if (particleContent != null && particleContent.eClass().getEAllStructuralFeatures().contains(sf)) {
owner = particleContent;
}
}
final SetCommand command = new SetCommand(ed, owner, sf, newValue);
executeCommandInTransaction(uow, owner, command);
}
return null;
}
};
try {
executeAsTransaction(runnable, cntr, operationDescription, isSignificant, this);
} catch (ModelerCoreException e) {
ModelerCore.Util.log(IStatus.ERROR, e, e.getMessage());
return false;
}
return true;
}
/**
* @see org.teiid.designer.core.ModelEditor#clone(org.eclipse.emf.ecore.EObject)
*/
@Override
public EObject clone( final EObject eObject ) throws ModelerCoreException {
CoreArgCheck.isNotNull(eObject);
final boolean isSignificant = true;
final String operationDescription = ModelerCore.Util.getString("ModelEditorImpl.Clone_{0}_12", getPresentationValue(eObject)); //$NON-NLS-1$
final ContainerImpl cntr = getContainer();
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) throws ModelerCoreException {
final EditingDomain ed = cntr.getEditingDomain();
final CloneCommand command = new CloneCommand(ed, eObject);
executeCommandInTransaction(uow, eObject, command);
command.getAffectedObjects();
// Look up the result ...
return command.getHelper().getCopy(eObject);
}
};
final EObject result = (EObject)executeAsTransaction(runnable, cntr, operationDescription, isSignificant, this);
return result;
}
/*
*
*/
@Override
public void cloneProject( final String originalProjectPath,
final String clonedProjectPath ) throws IOException {
cloneProject(originalProjectPath, clonedProjectPath, null);
}
void cloneProject( String originalProjectPath,
String clonedProjectPath,
Tester tester ) throws IOException {
Map model2RefMap = new HashMap();
Map genRefMap = new HashMap();
File originalProject = new File(originalProjectPath);
cloneFolder(originalProject, originalProject, model2RefMap, genRefMap, tester);
cloneFolder2(originalProject, originalProject, model2RefMap, genRefMap, new File(clonedProjectPath), tester);
}
private void cloneFolder( File originalProject,
File originalFolder,
Map modelToReferenceMap,
Map genRefMap,
Tester tester ) throws IOException {
File[] origFiles = originalFolder.listFiles();
if (origFiles != null) {
for (int ndx = origFiles.length; --ndx >= 0;) {
File origFile = origFiles[ndx];
String name = origFile.getName();
if (origFile.isDirectory()) {
if (name.charAt(0) != '.') {
cloneFolder(originalProject, origFile, modelToReferenceMap, genRefMap, tester);
}
} else {
if (name.endsWith(StringConstants.DOT_XMI)) {
cloneFile(originalProject, origFile, modelToReferenceMap, genRefMap, tester);
}
}
}
}
}
private void cloneFolder2( File originalProject,
File originalFolder,
Map modelToReferenceMap,
Map genRefMap,
File clonedFolder,
Tester tester ) throws IOException {
File[] origFiles = originalFolder.listFiles();
if (origFiles != null) {
for (int ndx = origFiles.length; --ndx >= 0;) {
File origFile = origFiles[ndx];
File clonedFile = new File(clonedFolder, origFile.getName());
String name = origFile.getName();
if (origFile.isDirectory()) {
if (name.charAt(0) != '.') {
cloneFolder2(originalProject, origFile, modelToReferenceMap, genRefMap, clonedFile, tester);
}
} else {
if (name.endsWith(StringConstants.DOT_XMI) || name.endsWith(StringConstants.DOT_XSD)) {
clonedFolder.mkdirs();
cloneFile2(originalProject, origFile, modelToReferenceMap, genRefMap, clonedFile, tester);
}
}
}
}
}
void cloneFile( File originalProject,
File originalFile,
Map modelToReferenceMap,
Map genRefMap,
Tester tester ) throws IOException {
Reader in = new FileReader(originalFile);
char[] buf = new char[8192];
char state = '\0';
StringBuffer elemNameBuilder = null;
StringBuffer attrNameBuilder = null;
StringBuffer attrValBuilder = null;
String attrName = null;
boolean href = false;
boolean choiceCriteria = false;
boolean sqlUuid = false;
char skipState = '\0';
/*
* Variables used for calls to the Tester() class.
*/
int xmiUuidCounter = 0;
int newUuidCounter = 0;
int xProjectHRefCounter = 0;
try {
for (int bufLen = in.read(buf); bufLen > 0; bufLen = in.read(buf)) {
for (int bufNdx = 0; bufNdx < bufLen; bufNdx++) {
char chr = buf[bufNdx];
if (state == '\0') { // Outside of element?
if (chr == '<') { // Start of element (either start element or end element)?
state = '<';
}
} else if (state == '<') { // Within element?
if (chr == '?') {
state = '?';
} else if (chr == '!') {
state = '!';
} else if (chr == '/') {
state = '\0';
} else if (!Character.isWhitespace(chr)) { // Start of element name?
state = 'E';
elemNameBuilder = new StringBuffer();
elemNameBuilder.append(chr);
}
} else if (state == 'E') { // Within element name?
if (chr == '/' || chr == '>') {
state = '\0';
if (chr == '/' || skipState == 'H') {
skipState = updateSkipMode(skipState, chr, elemNameBuilder);
}
} else if (Character.isWhitespace(chr)) { // After element name?
state = '@';
attrNameBuilder = new StringBuffer();
if (skipState == '\0') {
if ((elemNameBuilder.charAt(0) == 't' || elemNameBuilder.charAt(0) == 'T')
&& "transformation:TransformationContainer".equalsIgnoreCase(elemNameBuilder.toString())) { //$NON-NLS-1$
skipState = 'C';
}
} else if (skipState == 'C') {
if ("transformationMappings".equals(elemNameBuilder.toString())) { //$NON-NLS-1$
skipState = 'M';
}
} else if (skipState == 'M') {
if ("helper".equals(elemNameBuilder.toString())) { //$NON-NLS-1$
skipState = 'H';
}
}
} else {
elemNameBuilder.append(chr);
}
} else if (state == 'e') { // Within element name of end tag?
if (chr == '>' || Character.isWhitespace(chr)) {
state = '\0';
skipState = updateSkipMode(skipState, chr, elemNameBuilder);
} else {
elemNameBuilder.append(chr);
}
} else if (state == '@') { // After element name?
if (chr == '/' || chr == '>') { // End of start element?
state = '\0';
if (chr == '/' || skipState == 'H') {
skipState = updateSkipMode(skipState, chr, elemNameBuilder);
}
} else if (chr == '\'' || chr == '"') { // Start of attribute value?
state = chr;
attrName = attrNameBuilder.toString();
// Check if this is an attribute that should be skipped
if ("xmi:uuid".equals(attrName) || "mmedt:UUID".equals(attrName)) { //$NON-NLS-1$ //$NON-NLS-2$
// If so, change mode to not collect attribute value
attrValBuilder = null;
xmiUuidCounter++;
} else if (skipState == 'H' && attrName.endsWith("Sql") //$NON-NLS-1$
&& (attrName.startsWith("select") || attrName.startsWith("insert") //$NON-NLS-1$ //$NON-NLS-2$
|| attrName.startsWith("update") || attrName.startsWith("delete"))) { //$NON-NLS-1$ //$NON-NLS-2$
attrValBuilder = new StringBuffer();
sqlUuid = true;
} else {
// else, create a buffer to store attribute value
attrValBuilder = new StringBuffer();
if ("href".equals(attrName)) { //$NON-NLS-1$
href = true;
} else if ("choiceCriteria".equals(attrName)) { //$NON-NLS-1$
choiceCriteria = true;
}
}
} else if (chr != '=' && !Character.isWhitespace(chr)) { // Start of attribute name
attrNameBuilder.append(chr);
}
} else if (state == '\'' || state == '"') { // Within attribute value?
if (chr == state) { // End of attribute value?
state = 'E';
if (attrValBuilder != null) {
String attrVal = attrValBuilder.toString();
if (href) {
href = false;
// Skip references to built-in models/metamodels
if (attrVal.startsWith("http:") || attrVal.indexOf(UUID.PROTOCOL) < 0) { //$NON-NLS-1$
continue;
}
// Skip references to artifacts in external projects
int ndx = attrVal.indexOf('#');
String ref = attrVal.substring(0, ndx);
File referencedFile = new File(originalFile.getParentFile().getPath(), ref);
String referencedPath = referencedFile.getCanonicalPath();
if (!referencedPath.startsWith(originalProject.getCanonicalPath())) {
xProjectHRefCounter++;
continue;
}
// Map model to reference
boolean didCreate = mapOriginalUuidToNewUuidForReferencedPath(attrVal.substring(ndx
+ 1
+ UUID_PREFIX_LENGTH),
getOriginalReferenceToNewReferenceMap(referencedPath,
modelToReferenceMap),
genRefMap);
if (didCreate) {
newUuidCounter++;
}
} else if (choiceCriteria) {
choiceCriteria = false;
Map origRef2NewRefMap = getOriginalReferenceToNewReferenceMap(originalFile.getCanonicalPath(),
modelToReferenceMap);
for (int ndx = attrVal.indexOf(UUID.PROTOCOL); ndx >= 0; ndx = attrVal.indexOf(UUID.PROTOCOL,
ndx)) {
ndx += UUID_PREFIX_LENGTH;
boolean didCreate = mapOriginalUuidToNewUuidForReferencedPath(attrVal.substring(ndx,
ndx
+ UUID.FQ_LENGTH
- UUID_PREFIX_LENGTH),
origRef2NewRefMap,
genRefMap);
if (didCreate) {
newUuidCounter++;
}
}
} else if (sqlUuid) {
sqlUuid = false;
for (int ndx = attrVal.indexOf(UUID.PROTOCOL); ndx >= 0; ndx = attrVal.indexOf(UUID.PROTOCOL,
ndx)) {
ndx += UUID_PREFIX_LENGTH;
String originalUuid = attrVal.substring(ndx, ndx + UUID.FQ_LENGTH - UUID_PREFIX_LENGTH);
boolean didCreate = mapOriginalUuidToNewUuidForReferencedPath(originalUuid,
genRefMap,
genRefMap);
if (didCreate) {
// System.out.println(" File: " + originalFile.getName() + " ATTR: " + attrName +
// " Created New UUID: "
// + (String)genRefMap.get(originalUuid) + " OLD UUID: " + originalUuid);
newUuidCounter++;
}
}
} else {
// Skip all other references that don't start with the UUID protocol
if (attrValBuilder.length() < UUID_PROTOCOL_LENGTH) {
continue;
}
// Map model to reference
Map origRef2NewRefMap = getOriginalReferenceToNewReferenceMap(originalFile.getCanonicalPath(),
modelToReferenceMap);
String[] origUuids = attrVal.split(" +"); //$NON-NLS-1$
for (int ndx = origUuids.length; --ndx >= 0;) {
boolean didCreate = mapOriginalUuidToNewUuidForReferencedPath(origUuids[ndx].substring(UUID_PREFIX_LENGTH),
origRef2NewRefMap,
genRefMap);
if (didCreate) {
newUuidCounter++;
}
}
}
}
} else if (attrValBuilder != null) {
attrValBuilder.append(chr);
if (!href && !choiceCriteria && !sqlUuid && attrValBuilder.length() == UUID_PROTOCOL_LENGTH
&& !UUID.PROTOCOL.equals(attrValBuilder.toString())) {
attrValBuilder = null;
}
}
} else if (state == '?') {
if (chr == '?') {
state = '>';
}
} else if (state == '>') {
if (chr == '>') {
state = '\0';
} else {
state = '?';
}
} else if (state == '!') {
if (chr == '-') {
state = '~';
}
} else if (state == '~') {
if (chr == '-') {
state = '-';
} else {
state = '!';
}
} else if (state == '-') {
if (chr == '>') {
state = '\0';
} else {
state = '!';
}
}
if (tester != null) {
tester.cloneFile1(originalProject,
originalFile,
modelToReferenceMap,
buf,
bufLen,
bufNdx,
chr,
state,
elemNameBuilder,
attrNameBuilder,
attrValBuilder,
href,
choiceCriteria);
}
}
}
if (tester != null) {
tester.cloneFilePassOneSummary(originalProject,
originalFile,
getOriginalReferenceToNewReferenceMap(originalFile.getCanonicalPath(),
modelToReferenceMap),
xmiUuidCounter,
newUuidCounter,
xProjectHRefCounter);
}
} finally {
try {
in.close();
} catch (IOException ignored) {
}
}
}
void cloneFile2( File originalProject,
File originalFile,
Map modelToReferenceMap,
Map genRefMap,
File clonedFile,
Tester tester ) throws IOException {
Reader in = new FileReader(originalFile);
int replacedUuidCounter = 0;
try {
BufferedWriter out;
CharArrayWriter testWriter = null;
if (tester == null) {
out = new BufferedWriter(new FileWriter(clonedFile));
} else {
tester.cloningFile(originalFile);
testWriter = new CharArrayWriter();
out = new BufferedWriter(testWriter);
}
char[] buf = new char[BUFFER_LENGTH];
char state = '\0';
StringBuffer elemNameBuilder = null;
StringBuffer attrNameBuilder = null;
StringBuffer attrValBuilder = null;
String attrName = null;
boolean href = false;
boolean choiceCriteria = false;
boolean sqlUuid = false;
boolean uuid = false;
int prevBufLen = 0;
int outBufNdx = 0;
boolean xsd = originalFile.getName().endsWith(StringConstants.DOT_XSD);
try {
for (int bufLen = in.read(buf, 0, BUFFER_LENGTH); bufLen > prevBufLen; bufLen = prevBufLen
+ in.read(buf,
prevBufLen,
BUFFER_LENGTH)) {
for (int inBufNdx = prevBufLen; inBufNdx < bufLen; inBufNdx++) {
char chr = buf[inBufNdx];
if (state == '\0') { // Outside of element?
if (chr == '<') { // Start of element (either start element or end element)?
state = '<';
}
} else if (state == '<') { // Within element?
if (chr == '?') {
state = '?';
} else if (chr == '!') {
state = '!';
} else if (chr == '/') {
state = 'e';
elemNameBuilder = new StringBuffer();
} else if (!Character.isWhitespace(chr)) { // Start of element name?
state = 'E';
elemNameBuilder = new StringBuffer();
elemNameBuilder.append(chr);
}
} else if (state == 'E') { // Within element name?
if (chr == '/' || chr == '>') {
state = '\0';
} else if (Character.isWhitespace(chr)) { // After element name?
state = '@';
attrNameBuilder = new StringBuffer();
} else {
elemNameBuilder.append(chr);
}
} else if (state == 'e') { // Within element name of end tag?
if (chr == '>' || Character.isWhitespace(chr)) {
state = '\0';
} else {
elemNameBuilder.append(chr);
}
} else if (state == '@') { // After element name?
if (chr == '/' || chr == '>') { // End of start element?
state = '\0';
} else if (chr == '\'' || chr == '"') { // Start of attribute value?
state = chr;
// Check if this is an UUID-based SQL attribute that should be skipped
attrName = attrNameBuilder.toString();
// Write everything up until here
if (tester != null) {
tester.writeToOut(buf, outBufNdx, inBufNdx + 1 - outBufNdx);
}
out.write(buf, outBufNdx, inBufNdx + 1 - outBufNdx);
outBufNdx = inBufNdx + 1;
if (xsd) {
if ("mmedt:UUID".equals(attrName)) { //$NON-NLS-1$
uuid = true;
attrValBuilder = new StringBuffer();
} else {
// Ignore all other attributes in XSDs
attrValBuilder = null;
}
} else {
attrValBuilder = new StringBuffer();
if ("xmi:uuid".equals(attrName)) { //$NON-NLS-1$
uuid = true;
} else if ("href".equals(attrName)) { //$NON-NLS-1$
href = true;
} else if ("choiceCriteria".equals(attrName)) { //$NON-NLS-1$
choiceCriteria = true;
} else if (attrName.endsWith("Sql")) { //$NON-NLS-1$
if (attrName.startsWith("select") || attrName.startsWith("insert") //$NON-NLS-1$ //$NON-NLS-2$
|| attrName.startsWith("update") || attrName.startsWith("delete")) { //$NON-NLS-1$ //$NON-NLS-2$
sqlUuid = true;
}
}
}
} else if (chr != '=' && !Character.isWhitespace(chr)) { // Start of attribute name
// Write everything up until here
if (attrNameBuilder.length() == 0) {
if (tester != null) {
tester.writeToOut(buf, outBufNdx, inBufNdx - outBufNdx);
}
out.write(buf, outBufNdx, inBufNdx - outBufNdx);
outBufNdx = inBufNdx;
}
attrNameBuilder.append(chr);
}
} else if (state == '\'' || state == '"') { // Within attribute value?
if (chr == state) { // End of attribute value?
state = 'E';
if (attrValBuilder == null) {
// if (skipState == 'S') {
// skipState = 'H';
// outBufNdx = inBufNdx + 1;
// }
} else {
String attrVal = attrValBuilder.toString();
if (uuid) {
uuid = false;
boolean emptyUuid = false;
String referencedPath = originalFile.getCanonicalPath();
String originalUuid = ""; //$NON-NLS-1$
if (attrVal.length() >= UUID_PREFIX_LENGTH) {
originalUuid = attrVal.substring(UUID_PREFIX_LENGTH);
} else if (attrVal.trim().length() == 0) {
emptyUuid = true;
}
// else {
// System.out.println(" File: " + originalFile.getName() + " ATTR: " + attrName +
// " ATTR VALUE TOO SHORT : Value = " + attrVal);
// }
String newUuid = (String)genRefMap.get(originalUuid);
if (newUuid == null) {
Map origRef2NewRefMap = (Map)modelToReferenceMap.get(referencedPath);
if (origRef2NewRefMap != null) {
newUuid = (String)origRef2NewRefMap.get(originalUuid);
}
if (newUuid == null) {
newUuid = ((UUID)OBJECT_ID_FACTORY.create()).exportableForm();
}
}
replacedUuidCounter++;
// Check if emptyUuid and prefix the generated UUID with "mmedt:UUID
if (xsd && emptyUuid) {
if (tester != null) {
tester.writeToOut(UUID.PROTOCOL + ':');
}
out.write(UUID.PROTOCOL + ':');
} else {
// Write
if (tester != null) {
tester.writeToOut(buf, outBufNdx, UUID_PREFIX_LENGTH);
}
out.write(buf, outBufNdx, UUID_PREFIX_LENGTH);
}
if (tester != null) {
tester.writeToOut(newUuid);
}
out.write(newUuid);
outBufNdx = inBufNdx;
} else if (href) {
href = false;
// Skip references to built-in models/metamodels
if (!attrVal.startsWith("http:")) { //$NON-NLS-1$
int ndx = attrVal.indexOf('#');
// Skip non-UUID references
if (attrVal.regionMatches(ndx + 1, UUID.PROTOCOL, 0, UUID_PROTOCOL_LENGTH)) {
// Skip references to artifacts in external projects
String referencedPath = new File(originalFile.getParentFile().getPath(),
attrVal.substring(0, ndx)).getCanonicalPath();
if (referencedPath.startsWith(originalProject.getCanonicalPath())) {
Map origRef2NewRefMap = (Map)modelToReferenceMap.get(referencedPath);
String originalUuid = attrVal.substring(ndx + 1 + UUID_PREFIX_LENGTH);
String newUuid = (String)genRefMap.get(originalUuid);
if (newUuid == null) {
newUuid = (String)origRef2NewRefMap.get(originalUuid);
}
replacedUuidCounter++;
// Write
if (tester != null) {
tester.writeToOut(buf, outBufNdx, UUID_PREFIX_LENGTH);
}
out.write(buf, outBufNdx, ndx + 1 + UUID_PREFIX_LENGTH);
if (tester != null) {
tester.writeToOut(newUuid);
}
out.write(newUuid);
outBufNdx = inBufNdx;
}
}
}
} else if (sqlUuid) {
sqlUuid = false;
for (int startNdx = 0, ndx = attrVal.indexOf(UUID.PROTOCOL); ndx >= 0; ndx = attrVal.indexOf(UUID.PROTOCOL,
startNdx)) {
ndx += UUID_PREFIX_LENGTH;
int endNdx = ndx + UUID.FQ_LENGTH - UUID_PREFIX_LENGTH;
String origUuid = attrVal.substring(ndx, endNdx);
String newUuid = (String)genRefMap.get(origUuid);
if (newUuid == null) {
// We don't know what model this is in
newUuid = getNewUuidForOriginalUuid(origUuid, modelToReferenceMap);
}
replacedUuidCounter++;
// Write
if (tester != null) {
tester.writeToOut(buf, outBufNdx, ndx - startNdx);
}
out.write(buf, outBufNdx, ndx - startNdx);
if (tester != null) {
tester.writeToOut(newUuid);
}
out.write(newUuid);
outBufNdx += endNdx - startNdx;
startNdx = endNdx;
}
} else {
if (choiceCriteria) {
choiceCriteria = false;
}
Map origRef2NewRefMap = (Map)modelToReferenceMap.get(originalFile.getCanonicalPath());
for (int startNdx = 0, ndx = attrVal.indexOf(UUID.PROTOCOL); ndx >= 0; ndx = attrVal.indexOf(UUID.PROTOCOL,
startNdx)) {
ndx += UUID_PREFIX_LENGTH;
int endNdx = ndx + UUID.FQ_LENGTH - UUID_PREFIX_LENGTH;
String origUuid = attrVal.substring(ndx, endNdx);
String newUuid = (String)genRefMap.get(origUuid);
if (newUuid == null) {
newUuid = (String)origRef2NewRefMap.get(origUuid);
}
replacedUuidCounter++;
// Write
if (tester != null) {
tester.writeToOut(buf, outBufNdx, ndx - startNdx);
}
out.write(buf, outBufNdx, ndx - startNdx);
if (tester != null) {
tester.writeToOut(newUuid);
}
out.write(newUuid);
outBufNdx += endNdx - startNdx;
startNdx = endNdx;
}
}
}
} else if (attrValBuilder != null) {
attrValBuilder.append(chr);
if (!uuid && !href && !sqlUuid && !choiceCriteria
&& attrValBuilder.length() == UUID.PROTOCOL.length()
&& !UUID.PROTOCOL.equals(attrValBuilder.toString())) {
attrValBuilder = null;
}
}
} else if (state == '?') {
if (chr == '?') {
state = '>';
}
} else if (state == '>') {
if (chr == '>') {
state = '\0';
} else {
state = '?';
}
} else if (state == '!') {
if (chr == '-') {
state = '~';
}
} else if (state == '~') {
if (chr == '-') {
state = '-';
} else {
state = '!';
}
} else if (state == '-') {
if (chr == '>') {
state = '\0';
} else {
state = '!';
}
}
if (tester != null) {
out.flush();
tester.cloneFile2(originalProject,
originalFile,
modelToReferenceMap,
buf,
bufLen,
inBufNdx,
chr,
state,
elemNameBuilder,
attrNameBuilder,
attrValBuilder,
href,
choiceCriteria,
clonedFile,
testWriter,
uuid,
outBufNdx);
}
}
// Save any remaining characters that haven't been written
if (outBufNdx < bufLen) {
prevBufLen = bufLen - outBufNdx;
char[] newBuf = new char[prevBufLen + BUFFER_LENGTH];
System.arraycopy(buf, outBufNdx, newBuf, 0, prevBufLen);
buf = newBuf;
} else if (prevBufLen > 0) {
prevBufLen = 0;
buf = new char[BUFFER_LENGTH];
}
outBufNdx = 0;
}
// Write any remaining characters that haven't been written
if (prevBufLen > 0) {
if (tester != null) {
tester.writeToOut(buf, outBufNdx, prevBufLen);
}
out.write(buf, outBufNdx, prevBufLen);
if (tester != null) {
out.flush();
tester.cloneFile2(originalProject,
originalFile,
modelToReferenceMap,
buf,
prevBufLen,
0,
'\0',
'\0',
null,
null,
null,
false,
false,
clonedFile,
testWriter,
false,
0);
}
}
} finally {
try {
out.close();
} catch (IOException ignored) {
}
}
if (tester != null) {
tester.cloneFilePassTwoSummary(originalProject, originalFile, replacedUuidCounter);
}
} finally {
try {
in.close();
} catch (IOException ignored) {
}
}
}
private Map getOriginalReferenceToNewReferenceMap( String referencedPath,
Map modelToReferenceMap ) {
Map origRef2NewRefMap = (Map)modelToReferenceMap.get(referencedPath);
if (origRef2NewRefMap == null) {
origRef2NewRefMap = new HashMap();
modelToReferenceMap.put(referencedPath, origRef2NewRefMap);
}
return origRef2NewRefMap;
}
private boolean mapOriginalUuidToNewUuidForReferencedPath( String originalUuid,
Map origRef2NewRefMap,
Map genRefMap ) {
boolean createdNew = false;
String newUuid = (String)origRef2NewRefMap.get(originalUuid);
if (newUuid == null) {
newUuid = (String)genRefMap.get(originalUuid);
if (newUuid == null) {
createdNew = true;
newUuid = ((UUID)OBJECT_ID_FACTORY.create()).exportableForm();
origRef2NewRefMap.put(originalUuid, newUuid);
// System.out.println("\t Map: => [" + originalUuid + " => " + newUuid + "]");
}
}
return createdNew;
}
private String getNewUuidForOriginalUuid( String originalUuid,
Map modelToReferenceMap ) {
for (Iterator iter = modelToReferenceMap.keySet().iterator(); iter.hasNext();) {
String nextKey = (String)iter.next();
if (nextKey != null) {
Map origRef2NewRefMap = (Map)modelToReferenceMap.get(nextKey);
String newUuid = (String)origRef2NewRefMap.get(originalUuid);
if (newUuid != null) {
return newUuid;
}
}
}
return null;
}
private char updateSkipMode( char skipMode,
char chr,
StringBuffer elementName ) {
if (skipMode == 'H' && "helper".equals(elementName.toString())) { //$NON-NLS-1$
return 'M';
}
if (skipMode == 'M' && "transformationMappings".equals(elementName.toString())) { //$NON-NLS-1$
return 'C';
}
if (skipMode == 'C' && "Transformation:TransformationContainer".equals(elementName.toString())) { //$NON-NLS-1$
return '$';
}
return skipMode;
}
/**
* @see org.teiid.designer.core.ModelEditor#cloneMultiple(org.eclipse.emf.ecore.EObject, int)
*/
@Override
public Collection cloneMultiple( final EObject eObject,
final int numClones ) throws ModelerCoreException {
CoreArgCheck.isNotNull(eObject);
CoreArgCheck.isPositive(numClones);
final boolean isSignificant = true;
final String operationDescription = ModelerCore.Util.getString("ModelEditorImpl.Clone_{0}_12", getPresentationValue(eObject)); //$NON-NLS-1$
final ContainerImpl cntr = getContainer();
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) throws ModelerCoreException {
final EditingDomain ed = cntr.getEditingDomain();
final Collection resultsList = new ArrayList();
for (int i = 0; i != numClones; ++i) {
final Command command = new CloneCommand(ed, eObject);
executeCommandInTransaction(uow, eObject, command);
command.getAffectedObjects();
// Add the result to the command ...
Collection commandResults = command.getResult();
for (Iterator iter = commandResults.iterator(); iter.hasNext();) {
Object nextObj = iter.next();
if (!resultsList.contains(nextObj)) {
resultsList.add(nextObj);
}
}
}
// Look up the result ...
return resultsList;
}
};
final Collection result = (Collection)executeAsTransaction(runnable, cntr, operationDescription, isSignificant, this);
return result;
}
/**
* Return true if the child may be added to this parent
*
* @param parent
* @param child
* @return true if the child may be added to this parent
*/
@Override
public boolean isValidParent( final Object parent,
final EObject child ) {
if (parent instanceof EObject) {
EObject eParent = (EObject)parent;
final EReference ref = getChildReference(eParent, child);
// If no EReference for the parent has the child's EClass
// as an EType then this child cannot be owned by this parent
if (ref == null) {
return false;
}
// If the EReference is not containment then this
// parent cannot own this child
if (!ref.isContainment()) {
return false;
}
// If the potential child and the parent are from different metamodels
// then we cannot paste even if one EClass extends the other
final EClass eParentClass = eParent.eClass();
final EClass eChildClass = child.eClass();
if (eParentClass != null && eChildClass != null) {
final URI eParentMetamodelURI = eParentClass.eResource().getURI();
final URI eChildMetamodelURI = eChildClass.eResource().getURI();
if (eParentMetamodelURI != null && !eParentMetamodelURI.equals(eChildMetamodelURI)) {
return false;
}
}
if (ref.isMany()) {
return true;
}
Object value = eParent.eGet(ref);
if (value == null) {
return true;
}
} else if (parent instanceof Resource) {
return isValidRootObject((Resource)parent, child.eClass());
} else if (parent instanceof IFile) {
try {
final ModelResource mr = findModelResource((IFile)parent);
if (mr != null) {
final Resource rsrc = mr.getEmfResource();
if (rsrc != null) {
return isValidRootObject(rsrc, child.eClass());
}
}
} catch (ModelWorkspaceException e) {
return false;
}
} else if (parent instanceof ModelResource) {
try {
final Resource rsrc = ((ModelResource)parent).getEmfResource();
if (rsrc != null) {
return isValidRootObject(rsrc, child.eClass());
}
} catch (ModelWorkspaceException e) {
// Do nothing... all false to be returned;
}
}
return false;
}
@Override
public boolean isValidPasteParent( final Object potentialParent ) {
final ContainerImpl cntr = getContainer();
if (cntr == null) {
return false;
}
final EditingDomain ed = cntr.getEditingDomain();
if (ed.getClipboard() == null || ed.getClipboard().isEmpty()) {
return false;
}
final Iterator children = ed.getClipboard().iterator();
while (children.hasNext()) {
final EObject next = (EObject)children.next();
if (!isValidParent(potentialParent, next)) {
return false;
}
}
return true;
}
/**
* @see org.teiid.designer.core.ModelEditor#create(org.eclipse.emf.ecore.EClass)
*/
public EObject create( final EClass eClass ) {
return eClass.getEPackage().getEFactoryInstance().create(eClass);
}
/**
* @param result
* @param eObject
*/
Collection createCommands( final Collection commandParams,
final EditingDomain ed ) {
if (commandParams == null) {
return commandParams;
}
final Collection commands = new ArrayList(commandParams.size());
for (final Iterator iter = commandParams.iterator(); iter.hasNext();) {
final CommandParameter param = (CommandParameter)iter.next();
final EObject eOwner = param.getEOwner();
final Object owner = param.getOwner();
Command command = null;
if (eOwner == null && owner instanceof Resource) {
final EObject value = param.getEValue();
command = new AddCommand(ed, ((Resource)owner).getContents(), value);
} else {
final CommandParameter newChildParam = new CommandParameter(param.getOwner(), param.getFeature(), param);
command = ed.createCommand(CreateChildCommand.class, newChildParam);
}
// Determine if this command should be disabled by first checking
// for a null feature reference. EMF will create child parameters
// with a null feature to indicate that the feature is disabled
if (param.getFeature() == null) {
command = new DisabledCommand(command);
}
// Determine if this command should be disabled by checking
// for violations in the feature multiplicity
else {
final boolean disable = shouldBeDisabled(owner, param);
if (disable && command != null) {
command = new DisabledCommand(command);
}
}
if( command != null && !(command instanceof DisabledCommand) ) {
commands.add(command);
}
}
return commands;
}
private Collection getRootDescriptors( final Resource rsrc ) {
CoreArgCheck.isNotNull(rsrc);
final String primaryMetamodelURI = getPrimaryMetamodelURI(rsrc);
if (primaryMetamodelURI == null) {
// any older models may not have a primaryMetamodelURI... just return empty list
// instead of throwing an exception
return Collections.EMPTY_LIST;
}
// 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.
final URI nsUri = ModelerCore.getMetamodelRegistry().getURI(primaryMetamodelURI);
if (ModelerCore.getMetamodelRegistry().getMetamodelDescriptor(nsUri) == 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);
}
}
final Object[] params = new Object[] {primaryMetamodelURI, sb.toString()};
final String msg = ModelerCore.Util.getString("ModelEditorImpl.No_root_classes_found_for_metamodel_URI", params); //$NON-NLS-1$
ModelerCore.Util.log(IStatus.ERROR, msg);
}
final EPackage ePackage = ModelerCore.getMetamodelRegistry().getEPackage(nsUri);
final EFactory eFactory = ePackage.getEFactoryInstance();
final Collection rootClasses = Arrays.asList(ModelerCore.getMetamodelRegistry().getMetamodelRootClasses(nsUri));
Collection filteredClasses = new ArrayList(rootClasses.size());
for( Object obj : rootClasses ) {
String className = ((MetamodelRootClass)obj).getEClass().getName();
boolean ignore = className.equalsIgnoreCase("BaseTable") || //$NON-NLS-1$
className.equalsIgnoreCase("Procedure") || //$NON-NLS-1$
className.equalsIgnoreCase("Index") || //$NON-NLS-1$
className.equalsIgnoreCase("View"); //$NON-NLS-1$
if( !ignore ) {
filteredClasses.add(obj);
}
}
final Collection descriptors = createSiblingDescriptors(filteredClasses, eFactory, rsrc);
return descriptors;
}
private String getPresentationValue( final Object obj ) {
if (obj == null) {
return ""; //$NON-NLS-1$
}
if (obj instanceof EObject) {
for (Iterator iter = ((EObject)obj).eClass().getEAllStructuralFeatures().iterator(); iter.hasNext();) {
final EStructuralFeature feature = (EStructuralFeature)iter.next();
if (NAME_FEATURE_NAME.equalsIgnoreCase(feature.getName())) {
Object val = ((EObject)obj).eGet(feature);
if (val == null) {
return ((EObject)obj).eClass().getName();
}
return val.toString();
}
}
return ((EObject)obj).eClass().getName();
} else if (obj instanceof Resource) {
return URI.decode(((Resource)obj).getURI().toString());
} else if (obj instanceof Collection) {
if (((Collection)obj).size() > 1) {
return ModelerCore.Util.getString("ModelEditorImpl.many_1"); //$NON-NLS-1$
} else if (((Collection)obj).size() == 0) {
return ModelerCore.Util.getString("ModelEditorImpl.empty_list_2"); //$NON-NLS-1$
}
Object first = ((Collection)obj).iterator().next();
return getPresentationValue(first);
}
return obj.toString();
}
static void setDescriptorOwner( final Collection descriptors,
final Object owner ) {
CoreArgCheck.isNotNull(descriptors);
for (Iterator iter = descriptors.iterator(); iter.hasNext();) {
final Object descriptor = iter.next();
if (descriptor instanceof CommandParameter) {
if (owner instanceof XSDParticle) {
((CommandParameter)descriptor).setOwner(((XSDParticle)owner).getContent());
} else if (owner instanceof XSDAttributeUse) {
((CommandParameter)descriptor).setOwner(((XSDAttributeUse)owner).getContent());
} else {
((CommandParameter)descriptor).setOwner(owner);
}
}
}
}
/**
* Return the first EReference of all the parent EClass's EReferences that matches the EType of the child object and is a
* containment EReference. If no match is found then null is returned.
*
* @param object
* @param child
* @return
*/
private EReference getChildReference( final EObject object,
final Object child ) {
if (child instanceof EObject) {
final EObject eChild = (EObject)child;
final EObject eParent = object;
// Iterate over all the child references to factor each child to the right reference.
//
final Collection refs = eParent.eClass().getEAllReferences();
for (Iterator childrenReferences = refs.iterator(); childrenReferences.hasNext();) {
final EReference eReference = (EReference)childrenReferences.next();
final EClassifier eType = eReference.getEType();
// If this object is compatible with this reference and
// represents a containment feature. Only containment
// features can own this EType as a child ...
//
if (eType.isInstance(eChild) && eReference.isContainment()) {
return eReference;
}
}
}
return null;
}
private ModelAnnotation getModelAnnotation( final Resource rsrc ) {
if (rsrc instanceof MMXmiResource) {
final ModelAnnotation model = ((MMXmiResource)rsrc).getModelAnnotation();
return model;
}
final ModelResource mr = findModelResource(rsrc);
if (mr != null) {
try {
final ModelAnnotation ma = mr.getModelAnnotation();
if (ma != null) {
return ma;
}
} catch (ModelWorkspaceException e) {
ModelerCore.Util.log(e);
}
}
// Couldn't find a model resource... just find the root annotation
for (final Iterator contents = rsrc.getContents().iterator(); contents.hasNext();) {
final EObject next = (EObject)contents.next();
if (next instanceof ModelAnnotation) {
return (ModelAnnotation)next;
}
}
return null;
}
/**
* @param rsrc
* @return
*/
private static String getPrimaryMetamodelURI( Resource rsrc ) {
String primaryMetamodelUri = null;
if (ModelUtil.isXsdFile(rsrc)) {
primaryMetamodelUri = XSDPackage.eNS_URI;
} else if (ModelUtil.isModelFile(rsrc) && rsrc instanceof MMXmiResource) {
final MMXmiResource eRsrc = (MMXmiResource)rsrc;
if (eRsrc.isLoaded()) {
final ModelAnnotation annotation = eRsrc.getModelAnnotation();
if (annotation != null) {
primaryMetamodelUri = annotation.getPrimaryMetamodelUri();
}
} else {
XMIHeader header = getXmiHeader(eRsrc);
if (header != null) {
primaryMetamodelUri = header.getPrimaryMetamodelURI();
}
}
} else if (ModelUtil.isVdbArchiveFile(rsrc)) {
primaryMetamodelUri = "http://www.metamatrix.com/metamodels/VirtualDatabase"; //$NON-NLS-1$
}
return primaryMetamodelUri;
}
/**
* @param eclasses
* @param factory
* @return
*/
static Collection createSiblingDescriptors( final Collection rootClasses,
final EFactory factory,
final Object owner ) {
if (factory == null) {
return Collections.EMPTY_LIST;
}
final boolean ownerIsRoot = (owner instanceof Resource || (owner instanceof EObject && ((EObject)owner).eContainer() == null));
final Collection result = new HashSet(rootClasses.size());
for (Iterator iter = rootClasses.iterator(); iter.hasNext();) {
Resource rsrc = null;
if (owner instanceof Resource) {
rsrc = (Resource)owner;
} else if (owner instanceof EObject) {
rsrc = ((EObject)owner).eResource();
}
if (rsrc != null) {
final Object next = iter.next();
EClass eClass = null;
int maxOccurs = -1;
if (next instanceof MetamodelRootClass) {
MetamodelRootClass mmrc = (MetamodelRootClass)next;
eClass = mmrc.getEClass();
maxOccurs = mmrc.getMaxOccurs();
} else {
eClass = (EClass)next;
}
final EObject child = factory.create(eClass);
boolean disable = false;
// If no root entities of this type are allowed then disable the command
if (ownerIsRoot && maxOccurs == 0) {
disable = true;
}
// If a finite number of root entities of this type are allowed ...
else if (ownerIsRoot && maxOccurs > 0) {
// Count the number of instances for this EClass
int count = 0;
for (Iterator iterator = rsrc.getContents().iterator(); iterator.hasNext();) {
EObject root = (EObject)iterator.next();
if (root.eClass().equals(eClass)) {
count++;
}
}
// If the current number of instances exceeds the max allowable then disable the command
if (count >= maxOccurs) {
disable = true;
}
}
// If the command is to be disable, then null the feature reference. This
// is one way EMF indicates to its wizards to disable a command.
if (disable) {
result.add(new CommandParameter(rsrc, null, child));
} else {
result.add(new CommandParameter(rsrc, rsrc.getContents(), child));
}
} else {
// return an empty list
return Collections.EMPTY_LIST;
}
}
return result;
}
private static boolean isRootObject( final EClass eclass ) {
URI uri = eclass.eResource().getURI();
Collection eclasses = Arrays.asList(ModelerCore.getMetamodelRegistry().getRootMetaClasses(uri));
if (eclasses == null || eclasses.isEmpty()) {
return false;
}
return eclasses.contains(eclass);
}
private static boolean isValidRootObject( final Resource rsrc,
final EClass eclass ) {
if (rsrc == null || eclass == null || !isRootObject(eclass)) {
return false;
}
try {
String primaryMetamodelUri = getPrimaryMetamodelURI(rsrc);
if (primaryMetamodelUri == null) {
return false;
}
final URI nsUri = ModelerCore.getMetamodelRegistry().getURI(primaryMetamodelUri);
final Collection validRoots = Arrays.asList(ModelerCore.getMetamodelRegistry().getRootMetaClasses(nsUri));
return validRoots.contains(eclass);
} catch (Exception e) {
return false;
}
}
/**
* Return a {@link XMIHeader} instance for the specified resource or null if the resource is not an instance of a EmfResource.
*
* @param resource
* @return
* @since 4.2
*/
public static XMIHeader getXmiHeader( final Resource resource ) {
XMIHeader header = null;
if (resource != null && resource.getURI().isFile()) {
final File resourceFile = new File(resource.getURI().toFileString());
if (resourceFile.exists()) {
try {
header = XMIHeaderReader.readHeader(resourceFile);
} catch (TeiidDesignerException e) {
ModelerCore.Util.log(IStatus.ERROR, e, e.getLocalizedMessage());
}
}
}
return header;
}
/**
* @see org.teiid.designer.core.ModelEditor#getDescription(org.eclipse.emf.ecore.EObject)
*/
@Override
public String getDescription( final EObject eObject ) {
CoreArgCheck.isNotNull(eObject);
// Find the existing annotation object ...
final Annotation annotation = getAnnotation(eObject, false);
if (annotation != null) {
return annotation.getDescription();
}
// else there was no annotation, so return null
return null;
}
/**
* @see org.teiid.designer.core.ModelEditor#setDescription(org.eclipse.emf.ecore.EObject, java.lang.String)
*/
@Override
public void setDescription( final EObject eObject,
final String desc ) throws ModelerCoreException {
CoreArgCheck.isNotNull(eObject);
if (eObject.eIsProxy()) {
return; // cannot resolve an eProxy without a container/resource set
}
final boolean isSignificant = true;
final String operationDescription = ModelerCore.Util.getString("ModelEditorImpl.Set_Description_on_{0}_14", eObject.toString()); //$NON-NLS-1$
final ContainerImpl cntr = getContainer();
final TransactionRunnable runnable = new TransactionRunnable() {
@Override
public Object run( final UnitOfWork uow ) {
// If the description is null ...
if (desc == null || desc.trim().length() == 0) {
// Find the existing annotation object ...
final Annotation annotation = getAnnotation(eObject, false);
if (annotation != null) {
annotation.setDescription(null);
// And see if there is anything else on the annotation ...
if (annotation.getKeywords().isEmpty() && annotation.getTags().isEmpty()) {
// There isn't, so we can remove!
annotation.setAnnotationContainer(null);
}
} // else there was no annotation, so nothing to do ...
} else {
// The description is non-null and non-trivial,
// so we have to make sure to get an Annotation ...
final Annotation annotation = getAnnotation(eObject, true);
annotation.setDescription(desc);
}
return null;
}
};
executeAsTransaction(runnable, cntr, operationDescription, isSignificant, this);
}
/**
* @see org.teiid.designer.core.ModelEditor#findModelResource(org.eclipse.emf.ecore.resource.Resource)
*/
@Override
public ModelResource findModelResource( final Resource resource ) {
return ModelerCore.getModelWorkspace().findModelResource(resource);
}
/**
* @see org.teiid.designer.core.ModelEditor#findModelResource(EObject)
*/
@Override
public ModelResource findModelResource( final EObject eObject ) {
ModelResource modelResource = ModelerCore.getModelWorkspace().findModelResource(eObject);
if (modelResource == null) {
// See if the object is a transient diagram ...
if (eObject instanceof Diagram) {
// See what the target of the diagram is ...
final EObject target = ((Diagram)eObject).getTarget();
if (target != null) {
modelResource = findModelResource(target);
}
}
}
return modelResource;
}
/*
* @See org.teiid.designer.core.ModelEditor#findResource(org.teiid.designer.core.container.Container,
* org.eclipse.emf.ecore.EObject)
*/
@Override
public Resource findResource( final Container container,
final EObject eObject ) {
CoreArgCheck.isNotNull(container);
CoreArgCheck.isNotNull(eObject);
return this.findResource(container, eObject, true);
}
/*
* @See org.teiid.designer.core.ModelEditor#findResource(org.teiid.designer.core.container.Container,org.eclipse.emf.ecore.EObject,boolean)
*/
@Override
public Resource findResource( final Container container,
final EObject eObject,
final boolean resolve ) {
CoreArgCheck.isNotNull(eObject);
CoreArgCheck.isNotNull(container);
Resource resource = eObject.eResource();
// Obtain the resource by resolving the eProxy
if (resolve && resource == null && eObject.eIsProxy()) {
try {
URI uri = ((InternalEObject)eObject).eProxyURI();
resource = container.getResource(uri.trimFragment(), resolve);
} catch (Exception e) {
// ignore resource cannot be found
}
} else if (eObject instanceof XsdModelAnnotationImpl) {
resource = ((XsdModelAnnotationImpl)eObject).getResource();
}
return resource;
}
/**
* @see org.teiid.designer.core.ModelEditor#findModelResource(org.eclipse.core.resources.IResource)
*/
@Override
public ModelResource findModelResource( final IResource resource ) throws ModelWorkspaceException {
CoreArgCheck.isNotNull(resource);
return (ModelResource)ModelWorkspaceManager.getModelWorkspaceManager().findModelWorkspaceItem(resource);
}
/**
* @see org.teiid.designer.core.ModelEditor#addModelImport(org.teiid.designer.core.resource.EmfResource,
* org.eclipse.emf.ecore.resource.Resource)
*/
@Override
public boolean addModelImport( final MMXmiResource resource,
final Resource importedResource ) throws ModelerCoreException {
if (resource != null && importedResource != null && resource != importedResource) {
// If the resource is the same as this model's (same URI),
// then return (don't need an import to self)
final URI importedUri = importedResource.getURI();
final URI resourceUri = resource.getURI();
if (resourceUri.isRelative() || resourceUri.equals(importedUri)) {
return false;
}
// If a ModelImport already exists that matches the specified
// "imported resource" then there is nothing to add.
ModelImport existingImport = findModelImport(resource, importedResource);
if (existingImport != null) {
return false;
}
final ModelAnnotation modelAnnotation = resource.getModelAnnotation();
if (modelAnnotation != null) {
final ModelImport newModelImport = createModelImport(resource, importedResource);
if (newModelImport != null) {
// If we got here, then the import is not in current list, so go ahead and add it
addValue(modelAnnotation, newModelImport, modelAnnotation.getModelImports());
return true;
}
}
}
return false;
}
/**
* @see org.teiid.designer.core.ModelEditor#getExistingModelImportForLocation(org.teiid.designer.core.resource.EmfResource,
* java.lang.String)
* @since 5.0.2
*/
@Override
public ModelImport getExistingModelImportForLocation( final MMXmiResource resource,
String someModelLocation ) {
CoreArgCheck.isNotNull(resource);
CoreArgCheck.isNotNull(someModelLocation);
// Cache the URI for the importedResource so we can look for it in the import list
final Container cntr = ModelerCore.getContainer(resource);
if (cntr != null) {
final ModelAnnotation modelAnnot = resource.getModelAnnotation();
if (modelAnnot != null && modelAnnot.getModelImports() != null) {
for (final Iterator iter = modelAnnot.getModelImports().iterator(); iter.hasNext();) {
ModelImport modelImport = (ModelImport)iter.next();
// Get the import's location
String existingModelImportLocation = modelImport.getModelLocation();
if (existingModelImportLocation != null && existingModelImportLocation.equalsIgnoreCase(someModelLocation)) {
return modelImport;
}
}
}
}
return null;
}
/**
* @see org.teiid.designer.core.ModelEditor#createModelLocation(org.teiid.designer.core.resource.EmfResource,
* org.eclipse.emf.ecore.resource.Resource)
* @since 5.0.2
*/
@Override
public String createModelLocation( final MMXmiResource resource,
final Resource importedResource ) {
CoreArgCheck.isNotNull(importedResource);
// Check if the resource being imported is a valid import
if (!isValidImportResource(importedResource)) {
return null;
}
String newModelLocation = null;
// Set the relative location of the imported resource
URI resourceURI = resource.getURI();
URI importURI = importedResource.getURI();
String uriString = URI.decode(importURI.toString());
boolean isVdbResource = false;
if (resourceURI.toString().indexOf(ResourceFinder.VDB_WORKING_FOLDER_URI_PATH_SEGEMENT) > -1) {
isVdbResource = true;
}
// If the URI of the proxy resource is a logical URI of a built-in resource then use this value as the location
if (uriString.startsWith("http") || //$NON-NLS-1$
uriString.startsWith(ResourceFinder.METAMODEL_PREFIX) || uriString.startsWith(ResourceFinder.UML2_METAMODELS_PREFIX)) {
newModelLocation = uriString;
if (isVdbResource && newModelLocation.equalsIgnoreCase(DatatypeConstants.BUILTIN_DATATYPES_URI)) {
// Get the vdb's temp project path
IPath vdbProjectPath = ModelUtil.getVdbProjectPathURI(resource);
if (vdbProjectPath != null && !vdbProjectPath.isEmpty()) {
// We need to convert this location to the ../builtInDatatypes.xsd string
String builtInDatatypesName = DatatypeConstants.DATATYPES_MODEL_FILE_NAME;
IPath builtInDatatypesPath = vdbProjectPath.append(builtInDatatypesName);
URI builtInDTypeURI = URI.createFileURI(builtInDatatypesPath.toString());
URI relURI = ModelUtil.getRelativeLocation(resourceURI, builtInDTypeURI);
newModelLocation = relURI.toString();
}
}
// If the import is to a file, compute the location relative to the resource containing the import
} else if (importURI.isFile()) {
boolean deresolve = (!resourceURI.isRelative() && resourceURI.isHierarchical());
if (deresolve && !importURI.isRelative()) {
URI deresolvedURI = importURI.deresolve(resourceURI, true, true, false);
if (deresolvedURI.hasRelativePath()) {
importURI = deresolvedURI;
}
}
newModelLocation = URI.decode(importURI.toString());
// If the URI of the imported resource is to one of the built-in resources ...
} else {
// Check if the imported resource is one of the XSD global resources
ResourceSet globalResourceSet = XSDSchemaImpl.getGlobalResourceSet();
if (globalResourceSet.getResources().contains(importedResource)) {
if (importedResource == XSDSchemaImpl.getSchemaForSchema(XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001).eResource()) {
newModelLocation = XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001;
} else if (importedResource == XSDSchemaImpl.getSchemaInstance(XSDConstants.SCHEMA_INSTANCE_URI_2001).eResource()) {
newModelLocation = XSDConstants.SCHEMA_INSTANCE_URI_2001;
} else if (importedResource == XSDSchemaImpl.getMagicSchemaForSchema(XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001).eResource()) {
newModelLocation = ResourceFinder.MAGIC_SCHEMA_URI.toString();
}
// Assume the reference is to some system reosurce
} else {
newModelLocation = URI.decode(importURI.toString());
}
}
return newModelLocation;
}
/**
* @see org.teiid.designer.core.ModelEditor#createModelImport(org.teiid.designer.metamodels.core.ModelImport,
* org.eclipse.emf.ecore.resource.Resource)
* @since 4.3
*/
@Override
public ModelImport createModelImport( final MMXmiResource resource,
final Resource importedResource ) {
CoreArgCheck.isNotNull(importedResource);
// Check if the resource being imported is a valid import
if (!isValidImportResource(importedResource)) {
return null;
}
ModelImport modelImport = null;
// Check for valid model location
String newModelLocation = createModelLocation(resource, importedResource);
if (newModelLocation != null) {
modelImport = CoreFactory.eINSTANCE.createModelImport();
modelImport.setName(this.getResourceName(importedResource));
modelImport.setModelLocation(newModelLocation);
if (importedResource instanceof MMXmiResource) {
final MMXmiResource emfResource = (MMXmiResource)importedResource;
modelImport.setModelType(emfResource.getModelType());
modelImport.setPrimaryMetamodelUri(emfResource.getPrimaryMetamodelUri().toString());
modelImport.setUuid(emfResource.getUuid().toString());
} else if (importedResource instanceof XSDResourceImpl) {
modelImport.setModelType(ModelType.TYPE_LITERAL);
modelImport.setPrimaryMetamodelUri(XML_SCHEMA_METAMODEL_URI);
}
} else {
String msg = ModelerCore.Util.getString("ModelEditorImpl.could_not_create_model_import_for_resource_0", importedResource.getURI()); //$NON-NLS-1$
ModelerCore.Util.log(IStatus.ERROR, msg);
}
return modelImport;
}
protected boolean isValidImportResource( final Resource importedResource ) {
if (importedResource instanceof MMXmiResource) {
final MMXmiResource emfResource = (MMXmiResource)importedResource;
if (emfResource.getModelType() == null) {
return false;
} else if (emfResource.getPrimaryMetamodelUri() == null) {
return false;
} else if (emfResource.getUuid() == null) {
return false;
}
return true;
} else if (importedResource instanceof XSDResourceImpl) {
return true;
}
return false;
}
/**
* @see org.teiid.designer.core.ModelEditor#updateModelImport(org.teiid.designer.metamodels.core.ModelImport,
* org.eclipse.emf.ecore.resource.Resource)
* @since 4.3
*/
@Override
public void updateModelImport( final ModelImport modelImport,
final Resource importedResource ) {
CoreArgCheck.isNotNull(modelImport);
CoreArgCheck.isNotNull(importedResource);
Resource resource = modelImport.eResource();
if (resource != null) {
URI resourceURI = resource.getURI();
URI importURI = importedResource.getURI();
// If the URI of the imported resource is to one of the built-in resources then there is no location to update
Container cntr = ModelerCore.getContainer(resource);
if (cntr != null && cntr.getResourceFinder().isBuiltInResource(importedResource)) {
return;
}
if (importURI.isFile()) {
boolean deresolve = (resourceURI != null && !resourceURI.isRelative() && resourceURI.isHierarchical());
if (deresolve && !importURI.isRelative()) {
URI deresolvedURI = importURI.deresolve(resourceURI, true, true, false);
if (deresolvedURI.hasRelativePath()) {
importURI = deresolvedURI;
}
}
modelImport.setName(importURI.trimFileExtension().lastSegment());
modelImport.setModelLocation(URI.decode(importURI.toString()));
}
}
}
/**
* @see org.teiid.designer.core.ModelEditor#removeModelImports(org.teiid.designer.core.resource.EmfResource,
* org.eclipse.emf.ecore.resource.Resource)
*/
@Override
public void removeModelImport( final MMXmiResource resource,
final Resource importedResource ) throws ModelerCoreException {
if (resource != null && importedResource != null && resource != importedResource) {
// If no ModelImport exists that matches the specified
// "imported resource" then there is nothing to remove.
ModelImport importToRemove = findModelImport(resource, importedResource);
if (importToRemove == null) {
return;
}
// If an external reference still exists to the "imported resource" then we cannot remove the ModelImport
final Container cntr = ModelerCore.getContainer(resource);
if (cntr != null) {
final ResourceFinder finder = cntr.getResourceFinder();
Resource[] refs = finder.findReferencesFrom(resource, true, true);
for (int i = 0; i != refs.length; ++i) {
if (importedResource == refs[i]) {
return;
}
}
}
ModelAnnotation modelWithImports = resource.getModelAnnotation();
if (modelWithImports != null) {
removeValue(modelWithImports, importToRemove, modelWithImports.getModelImports());
}
}
}
/**
* @see org.teiid.designer.core.ModelEditor#findModelImport(org.teiid.designer.core.resource.EmfResource,
* org.eclipse.emf.ecore.resource.Resource)
* @since 4.3
*/
@Override
public ModelImport findModelImport( final MMXmiResource resource,
final Resource importedResource ) {
CoreArgCheck.isNotNull(resource);
if (importedResource == null || resource.getURI().isRelative() || importedResource.getURI().isRelative()) {
return null;
}
ModelImport theModelImport = null;
final Container cntr = ModelerCore.getContainer(resource);
if (cntr != null) {
// Defect 23340 - create a model location for the importedResource to resource dependency
String importedModelLocation = createModelLocation(resource, importedResource);
// if location created, check for existing model import using the location.
if (importedModelLocation != null) {
theModelImport = getExistingModelImportForLocation(resource, importedModelLocation);
}
} else {
String importedResourceUuid = null;
String importedResourceLocation = null;
if (importedResource instanceof MMXmiResource) {
importedResourceUuid = ((MMXmiResource)importedResource).getUuid().toString();
}
URI resourceURI = resource.getURI();
URI importURI = importedResource.getURI();
// Check if the imported resource is one of the XSD global resources
if (XSDSchemaImpl.getGlobalResourceSet().getResources().contains(importedResource)) {
if (importedResource == XSDSchemaImpl.getSchemaForSchema(XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001).eResource()) {
importURI = ResourceFinder.SCHEMA_FOR_SCHEMA_URI;
} else if (importedResource == XSDSchemaImpl.getSchemaInstance(XSDConstants.SCHEMA_INSTANCE_URI_2001).eResource()) {
importURI = ResourceFinder.SCHEMA_INSTANCE_URI;
} else if (importedResource == XSDSchemaImpl.getMagicSchemaForSchema(XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001).eResource()) {
importURI = ResourceFinder.MAGIC_SCHEMA_URI;
}
// If the importURI is an absolute URI to a file then deresolve it to obtain
// a relative URI like what is stored in the modelLocation feature of ModelImport
} else if (resourceURI.isFile() && importURI.isFile()) {
boolean deresolve = (!resourceURI.isRelative() && resourceURI.isHierarchical());
if (deresolve && !importURI.isRelative()) {
URI deresolvedURI = importURI.deresolve(resourceURI, true, true, false);
if (deresolvedURI.hasRelativePath()) {
importURI = deresolvedURI;
}
}
}
importedResourceLocation = URI.decode(importURI.toString());
final ModelAnnotation modelAnnot = resource.getModelAnnotation();
if (modelAnnot != null) {
final List modelImports = modelAnnot.getModelImports();
if (!modelImports.isEmpty()) {
for (Iterator iter = modelImports.iterator(); iter.hasNext();) {
ModelImport modelImport = (ModelImport)iter.next();
String modelImportUuid = modelImport.getUuid();
if (modelImportUuid != null && modelImportUuid.equalsIgnoreCase(importedResourceUuid)) {
theModelImport = modelImport;
}
if (theModelImport == null) {
String modelLocation = modelImport.getModelLocation();
if (modelLocation != null && modelLocation.equalsIgnoreCase(importedResourceLocation)) {
theModelImport = modelImport;
}
}
if (theModelImport != null) {
break;
}
}
}
}
}
return theModelImport;
}
/**
* @see org.teiid.designer.core.ModelEditor#getAnnotation(org.eclipse.emf.ecore.EObject, boolean)
*/
@Override
public Annotation getAnnotation( EObject eObject,
boolean forceCreate ) {
final Resource eObjectResource = eObject.eResource();
if (eObjectResource instanceof MMXmiResource) {
// Just look up the annotations right off the resource ...
final MMXmiResource emfResource = (MMXmiResource)eObjectResource;
Annotation annotation = emfResource.getAnnotation(eObject);
if (annotation == null && forceCreate) {
annotation = ModelResourceContainerFactory.createNewAnnotation(eObject, emfResource.getAnnotationContainer(true));
}
return annotation;
}
return null;
}
/**
* @see org.teiid.designer.core.ModelEditor#getAnnotation(org.teiid.designer.core.workspace.ModelResource,
* org.eclipse.emf.ecore.EObject, boolean)
*/
@Override
public Annotation getAnnotation( ModelResource modelResource,
EObject eObject,
boolean forceCreate ) {
return getAnnotation(eObject, forceCreate);
}
/**
* @see org.teiid.designer.core.ModelEditor#getExtension(org.eclipse.emf.ecore.EObject)
*/
@Override
public EObject getExtension( EObject eObject ) throws ModelerCoreException {
CoreArgCheck.isNotNull(eObject);
final EClass eClass = eObject.eClass();
// mtkTODO: Check whether the metamodel for this object allows extensions.
final EPackage ePackage = eClass.getEPackage();
// There is never an extension object for ECore ...
if (EcorePackage.eINSTANCE.equals(ePackage)) {
return null;
}
final Resource emfResource = eObject.eResource();
if (emfResource == null) {
return null;
}
// If the resource is an EmfResource ...
if (emfResource instanceof MMXmiResource) {
// Get the ModelAnnotation for the model that contains the eObject ...
final ModelAnnotation model = getModelAnnotation(emfResource);
if (model != null) {
final XPackage extPackage = model.getExtensionPackage();
if (extPackage != null) {
final XClass xclass = extPackage.findXClass(eClass);
if (xclass != null) {
EObject result = null;
try {
EPackage pkg = extPackage;
ExtensionFactory factory = null;
final EFactory existingFactory = pkg.getEFactoryInstance();
if (existingFactory == null || !(existingFactory instanceof ExtensionFactory)) {
factory = new ExtensionFactoryImpl();
factory.setEPackage(extPackage);
}
result = new ObjectExtension(eObject, xclass, this);
} catch (Throwable e) {
e.printStackTrace();
}
return result;
}
}
}
// mmDefect_12555 - Return the ObjectExtension associated with the XSDResource if one exists.
} else if (emfResource instanceof XSDResourceImpl) {
XSDResourceImpl xsdResource = (XSDResourceImpl)emfResource;
XSDSchema xsdSchema = xsdResource.getSchema();
if (xsdSchema != null) {
// Get the extension XPackage for the schema - null is returned if extension is defined.
final XPackage extPackage = XsdObjectExtension.getExtensionPackage(xsdSchema);
if (extPackage != null) {
final XClass xclass = extPackage.findXClass(eClass);
if (xclass != null) {
EObject result = null;
try {
EPackage pkg = extPackage;
ExtensionFactory factory = null;
final EFactory existingFactory = pkg.getEFactoryInstance();
if (existingFactory == null || !(existingFactory instanceof ExtensionFactory)) {
factory = new ExtensionFactoryImpl();
factory.setEPackage(extPackage);
}
result = new XsdObjectExtension(eObject, xclass, this);
} catch (Throwable e) {
final String msg = ModelerCore.Util.getString("ModelEditorImpl.getExtension_0", xsdSchema); //$NON-NLS-1$
throw new ModelerCoreException(msg);
}
return result;
}
// } else {
// final String msg = ModelerCore.Util.getString("ModelEditorImpl.getExtension_0",xsdSchema); //$NON-NLS-1$
// throw new ModelerCoreException(msg);
}
}
}
return null;
//
// // mtkTODO: Replace with a call to get the real extension object
// return getAnnotation(eObject,true);
}
/**
* @see org.teiid.designer.core.ModelEditor#findModelResource(org.teiid.designer.metamodels.core.ModelImport)
*/
@Override
public ModelResource findModelResource( final ModelImport modelImport ) {
CoreArgCheck.isNotNull(modelImport);
String thePath = modelImport.getPath();
if (thePath != null) {
final IPath pathInWorkspace = new Path(modelImport.getPath());
return ModelerCore.getModelWorkspace().findModelResource(pathInWorkspace);
}
return null;
}
/**
* @see org.teiid.designer.core.ModelEditor#getURI(org.eclipse.emf.ecore.EObject)
*/
@Override
public URI getUri( final EObject object ) {
CoreArgCheck.isNotNull(object);
// If the object is a metamodel EClass then we need to return a URI based on the metamodel's
// logical URI (e.g. http://www.metamatrix.com/metamodels/Relational) and not the actual
// metamodel resource URI (e.g. mtkplugin:///org.teiid.designer.metamodels.Relational).
if (object instanceof EClass) {
Resource eResource = object.eResource();
// Do this only if we are in the Eclipse plugin environment since the metamodel
// registry will not be loaded otherwise.
if (eResource != null && ModelerCore.getPlugin() != null) {
URI eResourceUri = eResource.getURI();
MetamodelDescriptor descriptor = ModelerCore.getMetamodelRegistry().getMetamodelDescriptor(eResourceUri);
if (descriptor != null) {
String logicalUri = URI.decode(descriptor.getNamespaceURI());
return URI.createURI(logicalUri).appendFragment(eResource.getURIFragment(object));
}
}
}
// Otherwise return the URI based on the EObject's resource URI and
// it's location within that resource
return EcoreUtil.getURI(object);
}
/**
* {@inheritDoc}
*
* @see org.teiid.designer.core.ModelEditor#getObjectID(org.eclipse.emf.ecore.EObject)
*/
@Override
public ObjectID getObjectID( final EObject object ) {
CoreArgCheck.isNotNull(object);
try {
String uuid = getContainer().getObjectManager().getObjectId(object);
if (uuid != null) {
// JPAV: DOES THIS CREATE A NEW OBJECT EACH TIME?
return stringToUuid(uuid);
}
} catch (Exception err) {
ModelerCore.Util.log(IStatus.ERROR, err, err.getMessage());
}
return null;
}
private ObjectID stringToUuid( String uuidString ) throws InvalidIDException {
return UUID.stringToObject(uuidString.startsWith(UUID.PROTOCOL) ? uuidString.substring(UUID.PROTOCOL.length() + 1) : uuidString);
}
/**
* {@inheritDoc}
*
* @see org.teiid.designer.core.ModelEditor#getObjectIdString(org.eclipse.emf.ecore.EObject)
*/
@Override
public String getObjectIdString( EObject object ) {
CoreArgCheck.isNotNull(object);
return getContainer().getObjectManager().getObjectId(object);
}
/**
* {@inheritDoc}
*
* @see org.teiid.designer.core.ModelEditor#setObjectID(EObject, ObjectID)
*/
@Override
public void setObjectID( EObject object,
ObjectID objectId ) {
setObjectID(object, objectId.toString());
}
/**
* {@inheritDoc}
*
* @see org.teiid.designer.core.ModelEditor#setObjectID(org.eclipse.emf.ecore.EObject, java.lang.String)
*/
@Override
public void setObjectID( EObject object,
String objectId ) {
CoreArgCheck.isNotNull(object);
try {
getContainer().getObjectManager().setObjectId(object, objectId);
} catch (Exception err) {
ModelerCore.Util.log(IStatus.ERROR, err, err.getMessage());
}
}
/**
* Try to retrieve the ObjectID from the SqlAspect. Certain implementations of SqlAspect override the getObjectID method with
* specialized logic to determine the identifier. If the ObjectID cannot be obtained from the aspect then resort to the
* default behavior found in ModelEditor.getObjectID.
*
* @param eObject
* @return
* @since 4.2
*/
public String getSearchIndexObjectID( final EObject eObject ) {
CoreArgCheck.isNotNull(eObject);
Object objId = null;
SqlAspect sqlAspect = AspectManager.getSqlAspect(eObject);
if (sqlAspect != null) {
if (sqlAspect instanceof SqlAnnotationAspect) {
objId = getObjectIdString(eObject);
} else {
objId = sqlAspect.getObjectID(eObject);
}
} else if (eObject instanceof XSDConcreteComponent) {
if (eObject.eIsProxy()) {
URI proxyURI = EcoreUtil.getURI(eObject);
if (proxyURI != null) {
objId = proxyURI.fragment();
}
} else if (eObject.eResource() != null) {
objId = eObject.eResource().getURIFragment(eObject);
}
} else {
objId = getObjectIdString(eObject);
}
if (objId != null) {
return objId.toString();
}
return null;
}
/**
* @see org.teiid.designer.core.ModelEditor#findObjectID(java.lang.Object)
*/
@Override
public EObject findObject( final Object objectId ) {
CoreArgCheck.isNotNull(objectId);
// Look in the main container ...
final Container cntr = getContainer();
return findObject(objectId, cntr);
}
protected EObject findObject( Object objectId,
final Container container ) {
if (container == null) {
return null;
}
EObject result = null;
Object resolvedObjectId = null;
if (objectId instanceof String) {
final String stringId = (String)objectId;
// See if the string really is an ObjectID ...
try {
resolvedObjectId = IDGenerator.getInstance().stringToObject(stringId);
} catch (InvalidIDException e1) {
// malformed ObjectID or not even an ObjectID; just continue
}
if (resolvedObjectId == null) {
// See if the string really is a URI ...
try {
resolvedObjectId = URI.createURI(stringId);
} catch (IllegalArgumentException e) {
// malformed URI or not even a URI; just continue
}
}
} else if (objectId instanceof URI) {
resolvedObjectId = objectId;
} else if (objectId instanceof ObjectID) {
resolvedObjectId = objectId;
}
if (resolvedObjectId != null) {
final EObjectFinder finder = container.getEObjectFinder();
result = (EObject)finder.find(resolvedObjectId); // works for URI, Proxy, or ObjectID
}
return result;
}
/**
* @see org.teiid.designer.core.ModelEditor#findObjectID(java.lang.Object,
* org.teiid.designer.core.workspace.ModelResource)
*/
@Override
public EObject findObject( final Object objectId,
final ModelResource resource,
final IProgressMonitor monitor ) throws ModelerCoreException {
CoreArgCheck.isNotNull(objectId);
CoreArgCheck.isNotNull(resource);
if (!resource.isLoaded() || !resource.isOpen()) {
resource.open(monitor);
resource.getEmfResource(); // loads the model
}
return findObject(objectId);
}
/**
* @see org.teiid.designer.core.ModelEditor#getChangedObject(org.eclipse.emf.common.notify.Notification)
*/
@Override
public Object getChangedObject( final Notification notification ) {
CoreArgCheck.isNotNull(notification);
return notification.getNotifier();
}
/**
* @see org.teiid.designer.core.ModelEditor#findObjectByPath(org.eclipse.emf.ecore.resource.Resource,
* org.eclipse.core.runtime.IPath)
*/
@Override
public EObject findObjectByPath( final Resource resource,
final IPath modelRelativePath ) {
CoreArgCheck.isNotNull(resource);
CoreArgCheck.isNotNull(modelRelativePath);
EObject object = null;
Collection children = resource.getContents();
final String[] segments = modelRelativePath.segments();
for (int i = 0; i < segments.length; ++i) {
final String segment = segments[i];
object = findChildByLabel(children, segment);
if (object == null) {
return null;
}
children = object.eContents();
}
return object;
}
protected EObject findChildByLabel( final Collection children,
final String label ) {
for (final Iterator iter = children.iterator(); iter.hasNext();) {
final EObject child = (EObject)iter.next();
final AdapterFactory adapterFactory = ModelerCore.getMetamodelRegistry().getAdapterFactory();
// Get the "name segment" for the current object ...
final IItemLabelProvider provider = (IItemLabelProvider)adapterFactory.adapt(child, IItemLabelProvider.class);
// We have to remove any ':'s from the label returned, as IPath treats anything before the ':' as a device name. Thus,
// we remove the entire ':' and type info.
final String objName = formatLabel(provider.getText(child));
if (objName.equals(label)) {
return child;
}
}
return null;
}
/**
* @see org.teiid.designer.core.ModelEditor#findObjectByPath(org.teiid.designer.core.workspace.ModelResource,
* org.eclipse.core.runtime.IPath)
*/
@Override
public EObject findObjectByPath( final ModelResource resource,
final IPath modelRelativePath ) throws ModelWorkspaceException {
CoreArgCheck.isNotNull(resource);
CoreArgCheck.isNotNull(modelRelativePath);
final Resource emfResource = resource.getEmfResource();
return findObjectByPath(emfResource, modelRelativePath);
}
/**
* @see org.teiid.designer.core.ModelEditor#getModelRelativatePath(org.eclipse.emf.ecore.EObject)
*/
@Override
public IPath getModelRelativePath( EObject object ) {
return getModelRelativePath(object, true);
}
/**
* @see org.teiid.designer.core.ModelEditor#getModelRelativePath(org.eclipse.emf.ecore.EObject, boolean)
* @since 5.0.1
*/
@Override
public IPath getModelRelativePath( EObject object,
boolean includeUnnamedObjects ) {
CoreArgCheck.isNotNull(object);
return computeModelRelativePath(object, false, includeUnnamedObjects);
}
/**
* @see org.teiid.designer.core.ModelEditor#getModelRelativatePathIncludingModel(org.eclipse.emf.ecore.EObject)
*/
@Override
public IPath getModelRelativePathIncludingModel( EObject object ) {
return getModelRelativePathIncludingModel(object, true);
}
/**
* @see org.teiid.designer.core.ModelEditor#getModelRelativePathIncludingModel(org.eclipse.emf.ecore.EObject, boolean)
* @since 5.0.1
*/
@Override
public IPath getModelRelativePathIncludingModel( EObject object,
boolean includeUnnamedObjects ) {
CoreArgCheck.isNotNull(object);
return computeModelRelativePath(object, true, includeUnnamedObjects);
}
/**
* @see org.teiid.designer.core.ModelEditor#getFullPathToParent(org.eclipse.emf.ecore.EObject)
*/
@Override
public IPath getFullPathToParent( final EObject object ) {
CoreArgCheck.isNotNull(object);
// Get the path to the resource ...
final Resource resource = object.eResource();
if (resource == null) {
return Path.ROOT;
}
final String resourcePathStr = getResourcePath(resource);
if (resourcePathStr == null) {
return Path.ROOT;
}
final IPath resourcePath = new Path(resourcePathStr);
// get the parent of object (may be the model) and generate the path in the model ...
final EObject container = object.eContainer();
if (container != null) {
// Return the path to the parent ...
final IPath relPathWithoutModel = computeModelRelativePath(container, false);
return resourcePath.append(relPathWithoutModel);
}
// Else, there is no container/parent - that is, it is a root-level object
// and the parent is the resource ...
return resourcePath;
}
protected IPath computeModelRelativePath( EObject object,
boolean includeModelInPath ) {
return computeModelRelativePath(object, includeModelInPath, true);
}
protected IPath computeModelRelativePath( EObject object,
boolean includeModelInPath,
boolean includeUnnamedObjects ) {
AdapterFactory adapterFactory = ModelerCore.getMetamodelRegistry().getAdapterFactory();
// Walk up the tree, prepending the path of the parent to the path seen so far ...
IPath path = new Path(""); //$NON-NLS-1$
EObject tmp = object;
if (tmp instanceof XSDParticle) {
path = updatePath(path, ((XSDParticle)tmp).getTerm(), adapterFactory, includeUnnamedObjects);
tmp = tmp.eContainer();
}
for (; tmp != null; tmp = tmp.eContainer()) {
if (!(tmp instanceof XSDParticle)) {
path = updatePath(path, tmp, adapterFactory, includeUnnamedObjects);
}
}
// Prepend the model name if required
if (includeModelInPath) {
String modelName = getModelName(object);
if (modelName != null) {
path = new Path(modelName).append(path);
}
}
return path;
}
private IPath updatePath( final IPath path,
final EObject eObject,
final AdapterFactory factory,
boolean includeUnnamedObjects ) {
if (!includeUnnamedObjects && !hasName(eObject)) {
return path;
}
// Get the "name segment" for the current object ...
final IItemLabelProvider provider = (IItemLabelProvider)factory.adapt(eObject, IItemLabelProvider.class);
// We have to remove any ':'s from the label returned, as IPath treats anything before the ':' as a device name. Thus, we
// remove the entire ':' and type info.
String objName = formatLabel(provider.getText(eObject));
// Add the segment for the current object
return new Path(objName).append(path);
}
// removes ':'s and trailing white space from object labels
private String formatLabel( final String name ) {
final int ndx = name.indexOf(':');
if (ndx >= 0) {
return name.substring(0, ndx).trim();
}
return name;
}
@Override
public String getModelName( final EObject object ) {
CoreArgCheck.isNotNull(object);
if (object.eIsProxy()) {
URI proxyUri = ((InternalEObject)object).eProxyURI();
URI resourceUri = proxyUri.trimFragment();
return getModelName(resourceUri);
}
if (object.eResource() != null) {
return getModelName(object.eResource().getURI());
}
return CoreStringUtil.Constants.EMPTY_STRING;
}
/**
* @see org.teiid.designer.core.ModelEditor#getModelName(org.eclipse.emf.ecore.resource.Resource)
*/
@Override
public String getModelName( Resource resource ) {
CoreArgCheck.isNotNull(resource);
// derive the model name from the EMF resource URI ...
return getModelName(resource.getURI());
}
public String getModelName( final URI resourceUri ) {
CoreArgCheck.isNotNull(resourceUri);
// derive the model name from the EMF resource URI ...
return resourceUri.trimFileExtension().lastSegment();
}
/**
* @see org.teiid.designer.core.ModelEditor#getModelName(org.teiid.designer.core.workspace.ModelResource)
*/
@Override
public String getModelName( ModelResource modelResource ) {
CoreArgCheck.isNotNull(modelResource);
final IResource modelFile = modelResource.getResource();
String modelName = null;
if (modelFile instanceof IFile) {
final IFile theFile = (IFile)modelFile;
final String extension = theFile.getFileExtension(); // may be null, doesn't include the '.'
modelName = theFile.getName();
if (extension != null) {
final int indexOfExtension = modelName.lastIndexOf(extension);
if (indexOfExtension == 0) {
modelName = ""; //$NON-NLS-1$
} else {
// Should find, but remove the extension plus the '.' before it
modelName = modelName.substring(0, indexOfExtension - 1);
}
}
} else {
modelName = modelResource.getItemName();
}
return modelName;
}
/**
* This method will return the list of containers defined within a given <code>ModelResource</code> Applicable containers are
* defined by the specific Metamodel type.
*
* @param emfResource
* @return
* @since 4.3
*/
@Override
public Collection getAllContainers( Resource resource ) {
if (resource == null || !(resource instanceof MMXmiResource)) return Collections.EMPTY_LIST;
return ModelResourceContainerFactory.getAllContainers(resource, true);
}
/**
* Get the relative path within the workspace to the specified resource
*
* @param resource
* @return
*/
public String getResourcePath( final Resource resource ) {
CoreArgCheck.isNotNull(resource);
return WorkspaceResourceFinderUtil.getWorkspaceUri(resource);
}
/**
* Return the name of the specified resource removing any file extension if one exists.
*
* @param resource
* @return
*/
private String getResourceName( final Resource resource ) {
CoreArgCheck.isNotNull(resource);
final URI resourceUri = resource.getURI();
final String modelNameWithExt = resourceUri.lastSegment();
final String extension = resourceUri.fileExtension();
if (extension != null) {
final int index = modelNameWithExt.indexOf(extension);
if (index > 1) {
return modelNameWithExt.substring(0, index - 1); // also remove the "."
}
}
return modelNameWithExt;
}
/**
* This creates a command that copies the given object.
*/
public static Command createCopyCommand( EditingDomain domain,
Object owner,
CopyCommand.Helper helper ) {
return domain.createCommand(CopyCommand.class, new CommandParameter(owner, null, helper));
}
/**
* This creates a command that copies the given collection of objects. If the collection contains more than one object, then a
* compound command will be created containing individual copy commands for each object.
*/
public static Command createCopyCommand( final EditingDomain domain,
final Collection collection,
CopyCommand.Helper helper ) {
if (collection == null || collection.isEmpty()) {
return UnexecutableCommand.INSTANCE;
}
CopyCommand.Helper copyHelper = helper;
CompoundCommand copyCommand = CompoundCommandFactory.create(CompoundCommand.MERGE_COMMAND_ALL);
for (Iterator objects = collection.iterator(); objects.hasNext();) {
copyCommand.append(domain.createCommand(CopyCommand.class, new CommandParameter(objects.next(), null, copyHelper)));
}
return copyCommand.unwrap();
}
/**
* @see org.teiid.designer.core.ModelEditor#getModelContents(org.eclipse.emf.ecore.EObject)
*/
@Override
public ModelContents getModelContents( final EObject eObject ) {
CoreArgCheck.isNotNull(eObject);
final Resource resource = eObject.eResource();
return getModelContents(resource);
}
/**
* @see org.teiid.designer.core.ModelEditor#getModelContents(org.eclipse.emf.ecore.resource.Resource)
*/
@Override
public ModelContents getModelContents( final Resource resource ) {
CoreArgCheck.isNotNull(resource);
if (resource instanceof MtkXmiResourceImpl) {
return ((MtkXmiResourceImpl)resource).getModelContents();
}
final ModelResource modelResource = this.findModelResource(resource);
return getModelContents(modelResource);
}
/**
* @see org.teiid.designer.core.ModelEditor#getModelContents(org.teiid.designer.core.workspace.ModelResource)
*/
@Override
public ModelContents getModelContents( final ModelResource modelResource ) {
CoreArgCheck.isNotNull(modelResource);
try {
return ModelContents.getModelContents(modelResource);
} catch (ModelWorkspaceException e) {
ModelerCore.Util.log(e);
}
return null;
}
/**
* @see org.teiid.designer.core.ModelEditor#getModelAnnotation(org.eclipse.emf.ecore.EObject)
*/
@Override
public ModelAnnotation getModelAnnotation( final EObject eObject ) throws ModelerCoreException {
CoreArgCheck.isNotNull(eObject);
final Resource resource = eObject.eResource();
if (resource instanceof MMXmiResource) {
return ((MMXmiResource)resource).getModelAnnotation();
}
final ModelResource modelResource = resource == null ? null : this.findModelResource(resource);
return modelResource == null ? null : modelResource.getModelAnnotation();
}
protected static SqlDatatypeAspect getSqlAspect( final EObject obj ) {
if (obj != null && obj instanceof XSDSimpleTypeDefinition) {
return (SqlDatatypeAspect)ModelerCore.getMetamodelRegistry().getMetamodelAspect(obj, SqlAspect.class);
}
return null;
}
static EObject resolveWhenProxy( EObject e ) {
EObject resolvedEObject = e;
if (e.eIsProxy()) {
resolvedEObject = EcoreUtil.resolve(e, getContainer());
if (resolvedEObject.eIsProxy()) {
throw new TeiidDesignerRuntimeException(
ModelerCore.Util.getString("ModelEditorImpl.Error_EObject_can_not_be_a_proxy", resolvedEObject.toString())); //$NON-NLS-1$
}
}
return resolvedEObject;
}
/**
* @since 8.0
*/
public class EnterpriseDatatypeInfoSetCommand extends AbstractOverrideableCommand {
private EnterpriseDatatypeInfo oldEdtInfo;
private final EnterpriseDatatypeInfo newEdtInfo;
private final XSDSimpleTypeDefinition simpleType;
public EnterpriseDatatypeInfoSetCommand( final EditingDomain ed,
final XSDSimpleTypeDefinition simpleType,
final EnterpriseDatatypeInfo newEdtInfo,
final EnterpriseDatatypeInfo oldEdtInfo ) {
super(ed);
this.simpleType = simpleType;
this.newEdtInfo = newEdtInfo;
this.oldEdtInfo = oldEdtInfo;
}
protected void invokeSetOperation( EnterpriseDatatypeInfo edtInfo ) {
ModelEditorImpl.getSqlAspect(this.simpleType).setEnterpriseDataAttributes((XSDSimpleTypeDefinition)ModelEditorImpl.resolveWhenProxy(this.simpleType),
edtInfo);
}
/**
* @see org.eclipse.emf.edit.command.OverrideableCommand#doExecute()
*/
@Override
public void doExecute() {
invokeSetOperation(this.newEdtInfo);
this.simpleType.eNotify(new ENotificationImpl(
(InternalEObject)this.simpleType,
Notification.SET,
this.simpleType.eClass().getEStructuralFeature(XSDPackage.XSD_SIMPLE_TYPE_DEFINITION__NAME),
this.oldEdtInfo, this.newEdtInfo));
}
/**
* @see org.eclipse.emf.edit.command.OverrideableCommand#doRedo()
*/
@Override
public void doRedo() {
invokeSetOperation(this.newEdtInfo);
this.simpleType.eNotify(new ENotificationImpl(
(InternalEObject)this.simpleType,
Notification.SET,
this.simpleType.eClass().getEStructuralFeature(XSDPackage.XSD_SIMPLE_TYPE_DEFINITION__NAME),
this.oldEdtInfo, this.newEdtInfo));
}
/**
* @see org.eclipse.emf.edit.command.OverrideableCommand#doUndo()
*/
@Override
public void doUndo() {
invokeSetOperation(this.oldEdtInfo);
this.simpleType.eNotify(new ENotificationImpl(
(InternalEObject)this.simpleType,
Notification.UNSET,
this.simpleType.eClass().getEStructuralFeature(XSDPackage.XSD_SIMPLE_TYPE_DEFINITION__NAME),
this.newEdtInfo, this.oldEdtInfo));
}
/**
* @see org.eclipse.emf.common.command.AbstractCommand#prepare()
*/
@Override
protected boolean prepare() {
if (this.simpleType == null || this.newEdtInfo == null || this.domain == null) {
this.isExecutable = false;
return false;
}
this.isExecutable = true;
this.isPrepared = true;
return true;
}
}
/**
* @since 8.0
*/
public class EnterpriseDatatypeInfoUnsetCommand extends AbstractOverrideableCommand {
private EnterpriseDatatypeInfo oldEdtInfo;
private final XSDSimpleTypeDefinition simpleType;
public EnterpriseDatatypeInfoUnsetCommand( final EditingDomain ed,
final XSDSimpleTypeDefinition simpleType,
final EnterpriseDatatypeInfo oldEdtInfo ) {
super(ed);
this.simpleType = simpleType;
this.oldEdtInfo = oldEdtInfo;
}
protected void invokeUnsetOperation() {
ModelEditorImpl.getSqlAspect(this.simpleType).unSetEnterpriseDataAttributes((XSDSimpleTypeDefinition)ModelEditorImpl.resolveWhenProxy(this.simpleType));
}
protected void invokeSetOperation( EnterpriseDatatypeInfo edtInfo ) {
ModelEditorImpl.getSqlAspect(this.simpleType).setEnterpriseDataAttributes((XSDSimpleTypeDefinition)ModelEditorImpl.resolveWhenProxy(this.simpleType),
edtInfo);
}
/**
* @see org.eclipse.emf.edit.command.OverrideableCommand#doExecute()
*/
@Override
public void doExecute() {
invokeUnsetOperation();
this.simpleType.eNotify(new ENotificationImpl(
(InternalEObject)this.simpleType,
Notification.UNSET,
this.simpleType.eClass().getEStructuralFeature(XSDPackage.XSD_SIMPLE_TYPE_DEFINITION__NAME),
this.oldEdtInfo, null));
}
/**
* @see org.eclipse.emf.edit.command.OverrideableCommand#doRedo()
*/
@Override
public void doRedo() {
invokeUnsetOperation();
this.simpleType.eNotify(new ENotificationImpl(
(InternalEObject)this.simpleType,
Notification.UNSET,
this.simpleType.eClass().getEStructuralFeature(XSDPackage.XSD_SIMPLE_TYPE_DEFINITION__NAME),
this.oldEdtInfo, null));
}
/**
* @see org.eclipse.emf.edit.command.OverrideableCommand#doUndo()
*/
@Override
public void doUndo() {
invokeSetOperation(this.oldEdtInfo);
this.simpleType.eNotify(new ENotificationImpl(
(InternalEObject)this.simpleType,
Notification.SET,
this.simpleType.eClass().getEStructuralFeature(XSDPackage.XSD_SIMPLE_TYPE_DEFINITION__NAME),
null, this.oldEdtInfo));
}
/**
* @see org.eclipse.emf.common.command.AbstractCommand#prepare()
*/
@Override
protected boolean prepare() {
if (this.simpleType == null || this.domain == null) {
this.isExecutable = false;
return false;
}
this.isExecutable = true;
this.isPrepared = true;
return true;
}
}
/**
* @since 8.0
*/
public class AddValueToMapCommand extends AbstractOverrideableCommand {
private Object owner;
private Map map;
private Object key;
private Object oldValue;
private Object newValue;
public AddValueToMapCommand( final EditingDomain ed,
final Object owner,
final Map map,
final Object key,
final Object newValue ) {
super(ed);
this.owner = owner;
this.map = map;
this.key = key;
this.newValue = newValue;
if (map != null) {
this.oldValue = map.get(key);
}
}
/**
* @see org.eclipse.emf.edit.command.OverrideableCommand#doExecute()
*/
@Override
public void doExecute() {
this.map.put(this.key, this.newValue);
if (this.owner instanceof EObject) {
((EObject)this.owner).eNotify(new ENotificationImpl((InternalEObject)this.owner, Notification.ADD, null,
this.oldValue, this.newValue));
}
}
/**
* @see org.eclipse.emf.edit.command.OverrideableCommand#doRedo()
*/
@Override
public void doRedo() {
this.map.put(this.key, this.newValue);
if (this.owner instanceof EObject) {
((EObject)this.owner).eNotify(new ENotificationImpl((InternalEObject)this.owner, Notification.ADD, null,
this.oldValue, this.newValue));
}
}
/**
* @see org.eclipse.emf.edit.command.OverrideableCommand#doUndo()
*/
@Override
public void doUndo() {
if (this.oldValue != null) {
this.map.put(this.key, this.oldValue);
} else {
this.map.remove(this.key);
if (this.key == null && this.owner instanceof XSDSchema) {
((XSDSchema)this.owner).getElement().removeAttribute("xmlns"); //$NON-NLS-1$
}
}
if (this.owner instanceof EObject) {
((EObject)this.owner).eNotify(new ENotificationImpl((InternalEObject)this.owner, Notification.REMOVE, null,
this.newValue, this.oldValue != null ? this.oldValue : null));
}
}
/**
* @see org.eclipse.emf.common.command.AbstractCommand#prepare()
*/
@Override
protected boolean prepare() {
if (this.map == null || this.newValue == null || this.domain == null) {
this.isExecutable = false;
return false;
}
this.isExecutable = true;
this.isPrepared = true;
return true;
}
}
/**
* @since 8.0
*/
public class RemoveValueFromMapCommand extends AbstractOverrideableCommand {
private Object owner;
private Map map;
private Object key;
private Object oldValue;
public RemoveValueFromMapCommand( final EditingDomain ed,
final Object owner,
final Map map,
final Object key ) {
super(ed);
this.owner = owner;
this.map = map;
this.key = key;
if (map != null) {
this.oldValue = map.get(key);
}
}
/**
* @see org.eclipse.emf.edit.command.OverrideableCommand#doExecute()
*/
@Override
public void doExecute() {
this.map.remove(this.key);
if (this.key == null && this.owner instanceof XSDSchema) {
((XSDSchema)this.owner).getElement().removeAttribute("xmlns"); //$NON-NLS-1$
}
if (this.owner instanceof EObject) {
((EObject)this.owner).eNotify(new ENotificationImpl((InternalEObject)this.owner, Notification.REMOVE, null,
this.oldValue, null));
}
}
/**
* @see org.eclipse.emf.edit.command.OverrideableCommand#doRedo()
*/
@Override
public void doRedo() {
this.map.remove(this.key);
if (this.key == null && this.owner instanceof XSDSchema) {
((XSDSchema)this.owner).getElement().removeAttribute("xmlns"); //$NON-NLS-1$
}
if (this.owner instanceof EObject) {
((EObject)this.owner).eNotify(new ENotificationImpl((InternalEObject)this.owner, Notification.REMOVE, null,
this.oldValue, null));
}
}
/**
* @see org.eclipse.emf.edit.command.OverrideableCommand#doUndo()
*/
@Override
public void doUndo() {
if (this.oldValue != null) {
this.map.put(this.key, this.oldValue);
if (this.owner instanceof EObject) {
((EObject)this.owner).eNotify(new ENotificationImpl((InternalEObject)this.owner, Notification.ADD, null,
null, this.oldValue));
}
}
}
/**
* @see org.eclipse.emf.common.command.AbstractCommand#prepare()
*/
@Override
protected boolean prepare() {
if (this.map == null || this.domain == null) {
this.isExecutable = false;
return false;
}
this.isExecutable = true;
this.isPrepared = true;
return true;
}
}
public static class AddCommandFactory {
public static AddCommand create( Object owner,
EditingDomain domain,
EList list,
Collection collection,
int index ) {
if (owner instanceof XSDConcreteComponent) {
return new XsdConcreteComponentAddCommand(domain, list, collection, index);
}
return new AddCommand(domain, list, collection, index);
}
}
public static class CompoundCommandFactory {
/**
* Note that code using this method does not currently need functionality from the SafeRemoveCompoundCommand, so it just
* returns a new CompoundCommand.
*/
public static CompoundCommand create( int index ) {
return new CompoundCommand(index);
}
public static CompoundCommand create( Object owner,
List commands ) {
if (owner instanceof XSDConcreteComponent) {
return new SafeRemoveCompoundCommand(commands);
} else if (owner instanceof Collection) {
// scan all items to be deleted, looking for an XSDConcreteComp:
Collection col = (Collection)owner;
Iterator itor = col.iterator();
while (itor.hasNext()) {
Object element = itor.next();
if (element instanceof XSDConcreteComponent) {
// found one, go ahead and accept it:
return new SafeRemoveCompoundCommand(commands);
} // endif -- XSDConcreteComp
} // endwhile -- items in collection
} // endif -- need special compoundCommand
return new CompoundCommand(commands);
}
}
static class Tester {
protected void cloneFilePassOneSummary( File originalProject,
File originalFile,
Map modelToReferenceMap,
int xmiUuidCount,
int newUuidCount,
int xProjectHRefCounter ) {
}
protected void cloneFile1( File originalProject,
File originalFile,
Map modelToReferenceMap,
char[] buf,
int bufLen,
int bufNdx,
char chr,
char state,
StringBuffer elemNameBuilder,
StringBuffer attrNameBuilder,
StringBuffer attrValBuilder,
boolean href,
boolean choiceCriteria ) {
}
protected void cloneFilePassTwoSummary( File originalProject,
File originalFile,
int replacedUuidCount ) {
}
protected void cloneFile2( File originalProject,
File originalFile,
Map modelToReferenceMap,
char[] buf,
int bufLen,
int inBufNdx,
char chr,
char state,
StringBuffer elemNameBuilder,
StringBuffer attrNameBuilder,
StringBuffer attrValBuilder,
boolean href,
boolean choiceCriteria,
File clonedFile,
CharArrayWriter testWriter,
boolean uuid,
int outBufNdx ) {
}
protected void cloningFile( File file ) {
}
protected void writeToOut( char[] charBuff,
int startIndex,
int length ) {
}
protected void writeToOut( String str ) {
}
}
}