blob: 774e16d601552aa9d84ab9692f6edecf371fd188 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012-2014 SAP SE.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* SAP SE - initial API and implementation and/or initial documentation
*
*******************************************************************************/
package org.eclipse.ogee.designer.features;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.graphiti.features.IFeatureProvider;
import org.eclipse.graphiti.features.context.IDeleteContext;
import org.eclipse.graphiti.features.context.IMultiDeleteInfo;
import org.eclipse.graphiti.mm.pictograms.ContainerShape;
import org.eclipse.graphiti.mm.pictograms.PictogramElement;
import org.eclipse.graphiti.ui.features.DefaultDeleteFeature;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.ogee.designer.Activator;
import org.eclipse.ogee.designer.contexts.LinkUsageContext;
import org.eclipse.ogee.designer.messages.Messages;
import org.eclipse.ogee.designer.providers.ODataFeatureProvider;
import org.eclipse.ogee.designer.utils.ArtifactUtil;
import org.eclipse.ogee.designer.utils.IODataEditorConstants;
import org.eclipse.ogee.designer.utils.ODataArtifactSelectionUtil;
import org.eclipse.ogee.designer.utils.ODataLayoutUtil;
import org.eclipse.ogee.designer.utils.ODataShapeUtil;
import org.eclipse.ogee.designer.utils.PropertyUtil;
import org.eclipse.ogee.model.odata.Annotation;
import org.eclipse.ogee.model.odata.Association;
import org.eclipse.ogee.model.odata.ComplexTypeUsage;
import org.eclipse.ogee.model.odata.EntityContainer;
import org.eclipse.ogee.model.odata.EntityType;
import org.eclipse.ogee.model.odata.EnumTypeUsage;
import org.eclipse.ogee.model.odata.IAnnotationTarget;
import org.eclipse.ogee.model.odata.Parameter;
import org.eclipse.ogee.model.odata.Property;
import org.eclipse.ogee.utils.logger.Logger;
import org.eclipse.ui.PlatformUI;
/**
* Default delete feature is extended in order provided custom delete messages
* and to support for linked artifact delete.
*
*/
public class ODataDeleteFeature extends DefaultDeleteFeature {
/**
* String constant for DOT
*/
private static final String DOT = "."; //$NON-NLS-1$
/**
* Entity Type Pictogram element.
*/
private PictogramElement mainPictogramElement;
/**
* Rectangle (Properties/EntitySets/Navigation Properties)
*/
private PictogramElement parentPE;
private int deleteItemIndex;
/**
* Parent Object
*/
private EObject deletableParentObject;
/**
* Feature provider
*/
public IFeatureProvider fp;
private EObject affectedShowUsageObj;
/**
* @param fp
*/
public ODataDeleteFeature(IFeatureProvider fp) {
super(fp);
this.fp = fp;
}
@Override
public String getDescription() {
return Messages.DEFAULTDELETEFEATURE_DEFAULT_MESSAGE;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.graphiti.ui.features.DefaultDeleteFeature#preDelete(org.eclipse
* .graphiti.features.context.IDeleteContext)
*/
/**
* Deletes EntitySet and Associations on Entity Delete.
*
* Deletes AssociationSet and Navigation Properties ON ASSOCIATION Delete.
*
*/
@Override
public void preDelete(IDeleteContext context) {
this.mainPictogramElement = null;
this.parentPE = null;
this.deletableParentObject = null;
PictogramElement pe = context.getPictogramElement();
if (PropertyUtil.isTypeIdentifier(pe)) {
EObject parentContainer = pe.eContainer();
if (parentContainer instanceof PictogramElement
&& PropertyUtil
.isInvisibleRectangle((PictogramElement) parentContainer)) {
EObject mainContainer = parentContainer.eContainer();
if (mainContainer instanceof PictogramElement
&& PropertyUtil
.isTopContainer((PictogramElement) mainContainer)) {
this.mainPictogramElement = (PictogramElement) mainContainer;
this.parentPE = ((PictogramElement) parentContainer);
this.deleteItemIndex = ((ContainerShape) this.parentPE)
.getChildren().indexOf(pe);
}
}
}
// Get the object which is selected
Object currentObject = getBusinessObjectForPictogramElement(context
.getPictogramElement());
if (currentObject != null) {
if (ArtifactUtil.isEntityType(currentObject)) {
ODataShapeUtil.deleteEntity(context.getPictogramElement(),
getFeatureProvider());
} else if (ArtifactUtil.isAssociation(currentObject)) {
ODataShapeUtil.deleteAssociation(currentObject,
getFeatureProvider());
} else if (ArtifactUtil.isComplexTypeProperty(currentObject)) {
Property delCmplxProp = (Property) currentObject;
ComplexTypeUsage propertyUsage = (ComplexTypeUsage) delCmplxProp
.getType();
affectedShowUsageObj = propertyUsage.getComplexType();
} else if (ArtifactUtil.isEnumTypeProperty(currentObject)) {
Property delEnumProp = (Property) currentObject;
EnumTypeUsage propertyUsage = (EnumTypeUsage) delEnumProp
.getType();
affectedShowUsageObj = propertyUsage.getEnumType();
} else if (ArtifactUtil.isFunctionImportReturnType(currentObject)) {
affectedShowUsageObj = ArtifactUtil
.getObjectFromTypeUsage((EObject) currentObject);
} else if (ArtifactUtil.isParameter(currentObject)) {
Parameter delProp = (Parameter) currentObject;
EObject propType = delProp.getType();
affectedShowUsageObj = ArtifactUtil
.getObjectFromTypeUsage(propType);
}
EObject parentObject = ((EObject) currentObject).eContainer();
if (parentObject instanceof EntityContainer) {
this.deletableParentObject = parentObject;
}
// this is to update referred PictogramElements.
ODataShapeUtil.updateReferedShapes((EObject) currentObject,
getFeatureProvider(), true);
// this is to update referred PictogramElements.
EObject businessObject = (EObject) currentObject;
ODataArtifactSelectionUtil.notifyRegisteredSubscribers(context
.getPictogramElement(), businessObject , ODataArtifactSelectionUtil.SelectionStatus.DELETED);
}
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.graphiti.ui.features.DefaultDeleteFeature#postDelete(org.
* eclipse.graphiti.features.context.IDeleteContext)
*/
/**
* updates the layout in case EntitySet, Property and Navigation Property
* delete.
*/
@Override
public void postDelete(IDeleteContext context) {
// default entity container shouldn't be deleted
/*
* if (this.deletableParentObject instanceof EntityContainer) {
* deleteParentObject(); }
*/
if (this.mainPictogramElement != null) {
if (this.parentPE != null) {
ODataLayoutUtil
.updateContainerHeightsOnDelete((ContainerShape) this.parentPE);
ODataShapeUtil.updateSelOnDelete(getFeatureProvider(),
this.mainPictogramElement, this.parentPE,
this.deleteItemIndex);
}
ODataShapeUtil.layoutPictogramElement(this.mainPictogramElement,
getFeatureProvider());
}
if (affectedShowUsageObj != null) {
ODataShapeUtil.updateShowUsageLinks(this.fp, null,
affectedShowUsageObj);
}
}
/**
* This method is responsible to delete the Object which do not have
* children. This is called only for EntityContainer Object.
*/
private void deleteParentObject() {
EList<EReference> eReferences = this.deletableParentObject.eClass()
.getEReferences();
boolean noChildren = true;
for (EReference eReference : eReferences) {
if (eReference.isContainment() && eReference.isMany()) {
Object childElements = this.deletableParentObject
.eGet(eReference);
if (childElements instanceof List
&& ((List<?>) childElements).size() > 0) {
noChildren = false;
break;
}
}
}
if (noChildren) {
deleteBusinessObject(this.deletableParentObject);
}
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.graphiti.ui.features.DefaultDeleteFeature#getDeleteName(org
* .eclipse.graphiti.features.context.IDeleteContext)
*/
@Override
protected String getDeleteName(IDeleteContext context) {
PictogramElement pe = context.getPictogramElement();
Object ObjectForPE = getBusinessObjectForPictogramElement(pe);
if (ObjectForPE instanceof EObject) {
EObject businessObject = (EObject) ObjectForPE;
String className = businessObject.eClass().getInstanceTypeName();
if (className != null) {
String totalName = className;
StringTokenizer st = new StringTokenizer(totalName, DOT);
while (st.hasMoreElements()) {
className = (String) st.nextElement();
}
return className;
}
}
return super.getDeleteName(context);
}
/**
* Shows a dialog which asks the user to confirm the deletion of one or more
* elements.
*
* @param context
* delete context
* @return <code>true</code> to delete element(s); <code>false</code> to
* cancel delete
*/
@Override
protected boolean getUserDecision(IDeleteContext context) {
String msg;
IMultiDeleteInfo multiDeleteInfo = context.getMultiDeleteInfo();
if (multiDeleteInfo != null) {
msg = MessageFormat.format(Messages.DEFAULTDELETEFEATURE_2_XMSG,
Integer.valueOf(multiDeleteInfo.getNumber()));
} else {
PictogramElement pe = context.getPictogramElement();
Object ObjectForPE = getBusinessObjectForPictogramElement(pe);
msg = ObjectForPE != null ? ArtifactUtil
.getDeleteMessage(ObjectForPE) : null;
if (msg == null) {
String deleteName = getDeleteName(context);
if (deleteName != null && deleteName.length() > 0) {
msg = MessageFormat.format(
Messages.DEFAULTDELETEFEATURE_3_XMSG, deleteName);
} else {
msg = Messages.DEFAULTDELETEFEATURE_4_XMSG;
}
}
}
return MessageDialog.openQuestion(PlatformUI.getWorkbench()
.getActiveWorkbenchWindow().getShell(),
Messages.DEFAULTDELETEFEATURE_5_XFLD, msg);
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.graphiti.ui.features.DefaultDeleteFeature#canDelete(org.eclipse
* .graphiti.features.context.IDeleteContext)
*/
@Override
public boolean canDelete(IDeleteContext context) {
boolean canDelete = false;
if (context instanceof LinkUsageContext) {
LinkUsageContext lc = (LinkUsageContext) context;
if (lc.isDeletable()) {
canDelete = true;
}
} else if (this.fp instanceof ODataFeatureProvider
&& ((ODataFeatureProvider) this.fp).isReadOnlyModel()) {
canDelete = false;
} else if (!PropertyUtil.isDeletableShape(context)
|| PropertyUtil.isLinkConnection(context.getPictogramElement())) {
canDelete = false;
} else {
canDelete = super.canDelete(context);
}
return canDelete;
}
/**
* Overridden for referenced entity types where we don't need to delete the
* original business object.
*
* @see org.eclipse.graphiti.ui.features.DefaultDeleteFeature#deleteBusinessObject(java.lang.Object)
*/
@Override
protected void deleteBusinessObject(Object bo) {
// Should not delete the business object
// if this is a referenced entity or
// which does not have referenced edmx set
PictogramElement pe = getFeatureProvider()
.getPictogramElementForBusinessObject(bo);
final IMarker[] markers = this.findMarkers((EObject)bo);
if (!(markers.length == 0)) {
for (int i = 0; i < markers.length; i++) {
String markerSourceId = null;
try {
markerSourceId = (String) markers[i]
.getAttribute(IMarker.SOURCE_ID);
} catch (CoreException e) {
// Nothing to log
}
if (this.isValidMarker((EObject)bo, markerSourceId, pe)){
try {
markers[i].delete();
} catch (CoreException e) {
//Nothing to log
}
}
}
}
if (bo instanceof EntityType) {
try {
if (ArtifactUtil.isReferencedEntityType(bo)) {
return;
}
} catch (NullPointerException e) {
return;
}
}
deleteAnnotations(bo);
super.deleteBusinessObject(bo);
}
/**
* this method is responsible to delete the annotations.
*
* @param bo
*/
private void deleteAnnotations(Object bo) {
// Added code to delete the annotations
List<EObject> collection = new ArrayList<EObject>();
collection.add((EObject) bo);
TreeIterator<Object> allContents = EcoreUtil.getAllContents(collection);
while (allContents.hasNext()) {
Object object = allContents.next();
// Added code to delete the annotations
if (object instanceof IAnnotationTarget) {
EList<Annotation> annotations = ((IAnnotationTarget) object)
.getAnnotations();
List<Annotation> tempList = new ArrayList<Annotation>();
tempList.addAll(annotations);
for (Annotation annotation : tempList) {
super.deleteBusinessObject(annotation);
}
}
}
}
private IMarker[] findMarkers(final EObject o) {
IMarker[] markers = null;
final IResource resource = ResourcesPlugin.getWorkspace().getRoot()
.findMember(o.eResource().getURI().toPlatformString(true));
try {
markers = resource.findMarkers(
IODataEditorConstants.PROBLEM_MARKER_ID, true,
IResource.DEPTH_INFINITE);
} catch (CoreException e) {
Logger.getLogger(Activator.PLUGIN_ID).logError(e);
e.printStackTrace();
}
return markers;
}
private boolean isValidMarker(final EObject pictogramObj,
final String markerSourceId, final PictogramElement pe) {
boolean isValidMarker = false;
final URI uri = URI.createURI(markerSourceId);
final EObject markerObj = pictogramObj.eResource().getResourceSet()
.getEObject(uri, true);
// get the selectable domain object for the current marker
final EObject selectableMarkerObj = ArtifactUtil
.getSelectableObject(markerObj);
// For domain object Association do not check for isTypeIdentifier.
if (selectableMarkerObj instanceof Association) {
isValidMarker = pictogramObj.equals(selectableMarkerObj)
&& !(PropertyUtil.isTitle(pe));
} else {
isValidMarker = pictogramObj.equals(selectableMarkerObj);
}
return isValidMarker;
}
}