| /******************************************************************************* |
| * 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; |
| } |
| |
| } |