| /******************************************************************************* |
| * 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.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Set; |
| |
| import org.eclipse.emf.common.util.EList; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.graphiti.dt.IDiagramTypeProvider; |
| import org.eclipse.graphiti.features.IDeleteFeature; |
| import org.eclipse.graphiti.features.IFeatureProvider; |
| import org.eclipse.graphiti.features.context.ICustomContext; |
| import org.eclipse.graphiti.features.context.impl.CreateConnectionContext; |
| import org.eclipse.graphiti.features.custom.AbstractCustomFeature; |
| import org.eclipse.graphiti.mm.pictograms.Anchor; |
| import org.eclipse.graphiti.mm.pictograms.AnchorContainer; |
| import org.eclipse.graphiti.mm.pictograms.Connection; |
| import org.eclipse.graphiti.mm.pictograms.PictogramElement; |
| import org.eclipse.graphiti.mm.pictograms.Shape; |
| import org.eclipse.graphiti.platform.IDiagramContainer; |
| import org.eclipse.graphiti.services.Graphiti; |
| import org.eclipse.ogee.designer.ODataEditor; |
| import org.eclipse.ogee.designer.actions.ODataShowUsageAction; |
| import org.eclipse.ogee.designer.contexts.LinkUsageContext; |
| import org.eclipse.ogee.designer.factories.ArtifactFactory; |
| import org.eclipse.ogee.designer.factories.ShapesFactory; |
| import org.eclipse.ogee.designer.messages.Messages; |
| import org.eclipse.ogee.designer.providers.ODataImageProvider; |
| import org.eclipse.ogee.designer.utils.ArtifactUtil; |
| import org.eclipse.ogee.designer.utils.IODataEditorConstants; |
| import org.eclipse.ogee.designer.utils.PropertyUtil; |
| import org.eclipse.ogee.model.odata.ComplexType; |
| import org.eclipse.ogee.model.odata.ComplexTypeUsage; |
| import org.eclipse.ogee.model.odata.EntityType; |
| import org.eclipse.ogee.model.odata.EntityTypeUsage; |
| import org.eclipse.ogee.model.odata.EnumType; |
| import org.eclipse.ogee.model.odata.EnumTypeUsage; |
| import org.eclipse.ogee.model.odata.FunctionImport; |
| import org.eclipse.ogee.model.odata.IFunctionReturnTypeUsage; |
| import org.eclipse.ogee.model.odata.IParameterTypeUsage; |
| import org.eclipse.ogee.model.odata.IPropertyTypeUsage; |
| import org.eclipse.ogee.model.odata.Parameter; |
| import org.eclipse.ogee.model.odata.Property; |
| import org.eclipse.ogee.model.odata.ReturnEntityTypeUsage; |
| import org.eclipse.ogee.model.odata.impl.ComplexTypeUsageImpl; |
| import org.eclipse.ogee.model.odata.impl.EntityTypeUsageImpl; |
| import org.eclipse.ogee.model.odata.impl.EnumTypeUsageImpl; |
| import org.eclipse.ogee.model.odata.impl.ReturnEntityTypeUsageImpl; |
| |
| /** |
| * This pattern class is created for 'LinkUsage' feature of the artifacts. This |
| * contains all the methods required to create the Show/Hide usage links Shape. |
| * This is used to make the feature work from the context menu. |
| * |
| */ |
| public class ODataLinkUsageFeature extends AbstractCustomFeature { |
| |
| /** |
| * artifact factory |
| */ |
| private ArtifactFactory artifactFactory; |
| /** |
| * shapes factory |
| */ |
| private ShapesFactory shapesFactory; |
| |
| /** |
| * Feature Provider |
| */ |
| private IFeatureProvider featureProvider; |
| |
| private boolean isToolBarReq = false; |
| private boolean isShown = false; |
| private boolean isHidden = false; |
| private boolean isUpdate = false; |
| |
| /** |
| * @param fp |
| * @param artifactFactory |
| * @param shapesFactory |
| */ |
| public ODataLinkUsageFeature(IFeatureProvider fp, |
| ArtifactFactory artifactFactory, ShapesFactory shapesFactory) { |
| |
| super(fp); |
| this.artifactFactory = artifactFactory; |
| this.shapesFactory = shapesFactory; |
| this.featureProvider = fp; |
| } |
| |
| /** |
| * @param fp |
| * @param artifactFactory |
| * @param shapesFactory |
| * @param isUpdate |
| * - if it called from the update method or delete method |
| */ |
| public ODataLinkUsageFeature(IFeatureProvider fp, |
| ArtifactFactory artifactFactory, ShapesFactory shapesFactory, |
| boolean isUpdate) { |
| |
| super(fp); |
| this.artifactFactory = artifactFactory; |
| this.shapesFactory = shapesFactory; |
| this.featureProvider = fp; |
| this.isUpdate = isUpdate; |
| } |
| |
| /** |
| * @param fp |
| * @param artifactFactory |
| * @param shapesFactory |
| * @param show |
| * @param isToolBarReq |
| * boolean - to check if the show/hide usage request is from |
| * eclipse tool bar. |
| */ |
| public ODataLinkUsageFeature(IFeatureProvider fp, |
| ArtifactFactory artifactFactory, ShapesFactory shapesFactory, |
| boolean show, boolean isToolBarReq) { |
| |
| this(fp, artifactFactory, shapesFactory); |
| this.isToolBarReq = isToolBarReq; |
| this.isShown = false; |
| this.isHidden = false; |
| } |
| |
| /** |
| * Enabled for Enum Type and Complex Type. |
| */ |
| @Override |
| public boolean canExecute(ICustomContext context) { |
| |
| boolean ret = false; |
| |
| PictogramElement[] pes = context.getPictogramElements(); |
| if (pes != null && pes.length == 1) { |
| Object bo = getBusinessObjectForPictogramElement(pes[0]); |
| if (bo instanceof EnumType || bo instanceof ComplexType |
| || bo instanceof EntityType) { |
| ret = true; |
| } |
| } |
| |
| return ret; |
| } |
| |
| @Override |
| public String getName() { |
| |
| return Messages.ODATAEDITOR_LINK_USAGE; |
| } |
| |
| @Override |
| public String getImageId() { |
| |
| return ODataImageProvider.IMG_DISPLAY_RELATION; |
| } |
| |
| @Override |
| public void execute(ICustomContext context) { |
| |
| // The following logic will un-check the Hide/Show All Usages button in |
| // case |
| // Hide/Show Usage is invoked from context menu of OData artifacts. |
| if (!this.isToolBarReq && this.featureProvider != null |
| && !this.isUpdate) { |
| final IDiagramTypeProvider dtp = this.featureProvider |
| .getDiagramTypeProvider(); |
| if (dtp != null) { |
| final IDiagramContainer editor = dtp.getDiagramBehavior().getDiagramContainer(); |
| if (editor != null && editor instanceof ODataEditor) { |
| final ODataEditor odataEditor = (ODataEditor) editor; |
| if (odataEditor != null |
| && odataEditor.getActionRegistry() != null) { |
| final ODataShowUsageAction action = (ODataShowUsageAction) odataEditor |
| .getActionRegistry() |
| .getAction( |
| IODataEditorConstants.ACTION_ID_SHOW_HIDE_USAGES); |
| if (action != null) { |
| action.setChecked(false); |
| } |
| } |
| } |
| if (PropertyUtil.isShowAllUsage(dtp.getDiagram())) { |
| PropertyUtil.setShowAllUsage(dtp.getDiagram(), false); |
| } |
| } |
| } |
| |
| // Get all the artifacts which use complex type and entity type |
| List<EntityType> etypes = this.artifactFactory |
| .getAllEntitiesIncludingReferenced(); |
| List<ComplexType> ctypes = this.artifactFactory |
| .getAllComplexTypesIncludingReferenced(); |
| List<FunctionImport> functionImports = this.artifactFactory |
| .getAllFunctionImports(); |
| // Create the list to populate the related usages |
| HashMap<EObject, Set<EObject>> linkMap = new HashMap<EObject, Set<EObject>>(); |
| PictogramElement[] pet = context.getPictogramElements(); |
| List<Connection> tempList = new ArrayList<Connection>(); |
| |
| // If isShowUsage returns true means the links are already shown |
| if (PropertyUtil.isShowUsage(pet[0])) { |
| |
| // Set it as hide as the links will be hidden |
| PropertyUtil.setHideUsage(pet[0]); |
| // Get all the link usages |
| tempList.addAll(getLinkConnections(pet[0])); |
| // Delete all the link usages |
| deleteLinkUsage(tempList); |
| this.isHidden = true; |
| |
| if (this.isUpdate) { |
| showUsageLinks(etypes, ctypes, functionImports, linkMap, pet); |
| } |
| } else { |
| showUsageLinks(etypes, ctypes, functionImports, linkMap, pet); |
| } |
| } |
| |
| /** |
| * Method is used to rebuild the linkages |
| * |
| * @param etypes |
| * @param ctypes |
| * @param functionImports |
| * @param linkMap |
| * @param pet |
| */ |
| public void showUsageLinks(List<EntityType> etypes, |
| List<ComplexType> ctypes, List<FunctionImport> functionImports, |
| HashMap<EObject, Set<EObject>> linkMap, PictogramElement[] pet) { |
| Object businessObject = getBusinessObjectForPictogramElement(pet[0]); |
| if (businessObject instanceof ComplexType |
| || businessObject instanceof EnumType |
| || businessObject instanceof EntityType) { |
| PropertyUtil.setShowUsage(pet[0]); |
| // Get all the complex types attached with the selected complex |
| // type |
| getLinkedComplexTypes(ctypes, linkMap, (EObject) businessObject); |
| // Get all the entity types attached with the selected complex |
| // type |
| getLinkedEntityTypes(etypes, linkMap, (EObject) businessObject); |
| // Get all the function imports attached with the selected |
| // complex type |
| getLinkedFunctionImports(functionImports, linkMap, |
| (EObject) businessObject); |
| Set<EObject> keySet = linkMap.keySet(); |
| for (EObject currnetKey : keySet) { |
| Set<EObject> valueSet = linkMap.get(currnetKey); |
| createLinkShape(valueSet, currnetKey); |
| this.isShown = true; |
| } |
| } |
| } |
| |
| /** |
| * @return boolean - if usage link is shown on canvas. |
| */ |
| public boolean isShown() { |
| |
| return this.isShown; |
| } |
| |
| /** |
| * @return boolean - if usage link is hidden on canvas. |
| */ |
| public boolean isHidden() { |
| |
| return this.isHidden; |
| } |
| |
| /** |
| * @param connectionContext |
| * @param complexType |
| * @param valueSet |
| */ |
| private void createLinkShape(Set<EObject> valueSet, EObject sourceObj) { |
| |
| CreateConnectionContext connectionContext = new CreateConnectionContext(); |
| |
| if (valueSet != null) { |
| |
| for (EObject currentArtifact : valueSet) { |
| connectionContext = new CreateConnectionContext(); |
| connectionContext.setSourceAnchor(Graphiti.getPeService() |
| .getChopboxAnchor(getTopContainerShape(sourceObj))); |
| connectionContext |
| .setTargetAnchor(Graphiti.getPeService() |
| .getChopboxAnchor( |
| getTopContainerShape(currentArtifact))); |
| this.shapesFactory.createLinkUsageShape(getFeatureProvider(), |
| connectionContext); |
| } |
| } |
| } |
| |
| /** |
| * @param complexType |
| * @return |
| */ |
| private Shape getTopContainerShape(EObject currentObject) { |
| |
| Shape topContainer = null; |
| |
| PictogramElement[] pes = getFeatureProvider() |
| .getAllPictogramElementsForBusinessObject(currentObject); |
| for (PictogramElement pe : pes) { |
| if (PropertyUtil.isTopContainer(pe)) { |
| topContainer = (Shape) pe; |
| break; |
| } |
| } |
| return topContainer; |
| } |
| |
| /** |
| * Get all the links which are going to be deleted |
| * |
| * @param pe |
| * @return |
| */ |
| private List<Connection> getLinkConnections(PictogramElement pe) { |
| |
| EList<Connection> connections = getFeatureProvider() |
| .getDiagramTypeProvider().getDiagram().getConnections(); |
| List<Connection> tempList = new ArrayList<Connection>(); |
| // Populate all the dependent usages |
| Anchor anchor; |
| AnchorContainer anchorContainer; |
| Object targetObject; |
| Object businessObject; |
| for (Connection connection : connections) { |
| if (PropertyUtil.isLinkConnection(connection)) { |
| anchor = connection.getStart(); |
| anchorContainer = anchor.getParent(); |
| targetObject = getBusinessObjectForPictogramElement(anchorContainer); |
| businessObject = getBusinessObjectForPictogramElement(pe); |
| if (businessObject instanceof ComplexType |
| || businessObject instanceof EnumType |
| || businessObject instanceof EntityType) { |
| |
| if (targetObject == businessObject) { |
| tempList.add(connection); |
| } |
| } |
| |
| } |
| } |
| |
| return tempList; |
| } |
| |
| /** |
| * To delete all the links to show usage |
| * |
| * @param tempList |
| */ |
| private void deleteLinkUsage(List<Connection> tempList) { |
| |
| // Delete all the link usages |
| LinkUsageContext deleteContext; |
| IDeleteFeature deleteFeature; |
| |
| for (Connection linkConnection : tempList) { |
| deleteContext = new LinkUsageContext(linkConnection); |
| deleteFeature = this.featureProvider |
| .getDeleteFeature(deleteContext); |
| if (deleteFeature != null |
| && deleteFeature.canExecute(deleteContext)) { |
| |
| deleteFeature.execute(deleteContext); |
| } |
| } |
| } |
| |
| /** |
| * Get all the function imports which are linked with the complex type or |
| * enum type |
| * |
| * @param functionImports |
| * @param linkMap |
| * @param ct |
| */ |
| private void getLinkedFunctionImports(List<FunctionImport> functionImports, |
| HashMap<EObject, Set<EObject>> linkMap, EObject type) { |
| |
| EObject currentObject; |
| IFunctionReturnTypeUsage returnType; |
| Set<EObject> currentValueSet; |
| |
| for (FunctionImport funcImport : functionImports) { |
| currentObject = null; |
| EList<Parameter> parameters = funcImport.getParameters(); |
| for (Parameter parameter : parameters) { |
| IParameterTypeUsage parameterUsage = parameter.getType(); |
| if (parameterUsage instanceof ComplexTypeUsageImpl) { |
| currentObject = ((ComplexTypeUsage) parameterUsage) |
| .getComplexType(); |
| } else if (parameterUsage instanceof EnumTypeUsageImpl) { |
| currentObject = ((EnumTypeUsage) parameterUsage) |
| .getEnumType(); |
| } else if (parameterUsage instanceof EntityTypeUsageImpl) { |
| currentObject = ((EntityTypeUsage) parameterUsage) |
| .getEntityType(); |
| } |
| if (type.equals(currentObject)) { |
| currentValueSet = linkMap.get(type); |
| if (currentValueSet == null) { |
| currentValueSet = new HashSet<EObject>(); |
| linkMap.put(type, currentValueSet); |
| } |
| currentValueSet.add(funcImport); |
| break; |
| } |
| } |
| returnType = funcImport.getReturnType(); |
| if (returnType instanceof ComplexTypeUsageImpl) { |
| currentObject = ((ComplexTypeUsage) returnType) |
| .getComplexType(); |
| } else if (returnType instanceof EnumTypeUsageImpl) { |
| currentObject = ((EnumTypeUsage) returnType).getEnumType(); |
| } else if (returnType instanceof ReturnEntityTypeUsageImpl) { |
| currentObject = ((ReturnEntityTypeUsage) returnType) |
| .getEntityType(); |
| } |
| if (type.equals(currentObject)) { |
| currentValueSet = linkMap.get(type); |
| if (currentValueSet == null) { |
| currentValueSet = new HashSet<EObject>(); |
| linkMap.put(type, currentValueSet); |
| } |
| currentValueSet.add(funcImport); |
| } |
| } |
| } |
| |
| /** |
| * Get all the entity types which are linked with the complex type or enum |
| * type |
| * |
| * @param etypes |
| * @param linkMap |
| * @param ct |
| */ |
| private void getLinkedEntityTypes(List<EntityType> etypes, |
| HashMap<EObject, Set<EObject>> linkMap, EObject type) { |
| |
| EList<Property> eproperties; |
| EObject currentObject; |
| IPropertyTypeUsage propertyUsage; |
| Set<EObject> currentValueSet; |
| |
| boolean isEntityType = ArtifactUtil.isEntityType(type); |
| EntityType baseType = null; |
| |
| for (EntityType entityType : etypes) { |
| |
| // Check for Base Type |
| if (isEntityType) { |
| |
| baseType = entityType.getBaseType(); |
| if (type.equals(baseType)) { |
| currentValueSet = linkMap.get(type); |
| if (currentValueSet == null) { |
| currentValueSet = new HashSet<EObject>(); |
| linkMap.put(type, currentValueSet); |
| } |
| currentValueSet.add(entityType); |
| continue; |
| } |
| } |
| |
| eproperties = entityType.getProperties(); |
| for (Property property : eproperties) { |
| currentObject = null; |
| propertyUsage = property.getType(); |
| if (propertyUsage instanceof ComplexTypeUsageImpl) { |
| currentObject = ((ComplexTypeUsage) propertyUsage) |
| .getComplexType(); |
| } else if (propertyUsage instanceof EnumTypeUsageImpl) { |
| currentObject = ((EnumTypeUsage) propertyUsage) |
| .getEnumType(); |
| } |
| if (type.equals(currentObject)) { |
| currentValueSet = linkMap.get(type); |
| if (currentValueSet == null) { |
| currentValueSet = new HashSet<EObject>(); |
| linkMap.put(type, currentValueSet); |
| } |
| currentValueSet.add(entityType); |
| break; |
| } |
| } |
| |
| eproperties = entityType.getKeys(); |
| for (Property property : eproperties) { |
| currentObject = null; |
| propertyUsage = property.getType(); |
| if (propertyUsage instanceof EnumTypeUsageImpl) { |
| currentObject = ((EnumTypeUsage) propertyUsage) |
| .getEnumType(); |
| } |
| if (type.equals(currentObject)) { |
| currentValueSet = linkMap.get(type); |
| if (currentValueSet == null) { |
| currentValueSet = new HashSet<EObject>(); |
| linkMap.put(type, currentValueSet); |
| } |
| currentValueSet.add(entityType); |
| break; |
| } |
| } |
| } |
| } |
| |
| /** |
| * Get all the complex types which are linked with the complex type or enum |
| * type |
| * |
| * @param ctypes |
| * @param linkMap |
| * @param type |
| */ |
| private void getLinkedComplexTypes(List<ComplexType> ctypes, |
| HashMap<EObject, Set<EObject>> linkMap, EObject type) { |
| |
| EList<Property> cproperties; |
| EObject currentObject; |
| IPropertyTypeUsage propertyUsage; |
| Set<EObject> currentValueSet; |
| |
| boolean isComplexType = ArtifactUtil.isComplexType(type); |
| ComplexType baseType = null; |
| |
| for (ComplexType complexType : ctypes) { |
| |
| // Check for Base Type |
| if (isComplexType) { |
| baseType = complexType.getBaseType(); |
| if (type.equals(baseType)) { |
| currentValueSet = linkMap.get(type); |
| if (currentValueSet == null) { |
| currentValueSet = new HashSet<EObject>(); |
| linkMap.put(type, currentValueSet); |
| } |
| currentValueSet.add(complexType); |
| continue; |
| } |
| } |
| |
| cproperties = complexType.getProperties(); |
| for (Property property : cproperties) { |
| currentObject = null; |
| propertyUsage = property.getType(); |
| if (propertyUsage instanceof ComplexTypeUsageImpl) { |
| currentObject = ((ComplexTypeUsage) propertyUsage) |
| .getComplexType(); |
| } else if (propertyUsage instanceof EnumTypeUsageImpl) { |
| currentObject = ((EnumTypeUsage) propertyUsage) |
| .getEnumType(); |
| } |
| if (type.equals(currentObject)) { |
| currentValueSet = linkMap.get(type); |
| if (currentValueSet == null) { |
| currentValueSet = new HashSet<EObject>(); |
| linkMap.put(type, currentValueSet); |
| } |
| currentValueSet.add(complexType); |
| break; |
| } |
| } |
| } |
| } |
| |
| } |