blob: dd87a24cd809ecfd76c931297d19b3fbfbd37031 [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.providers;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.graphiti.dt.IDiagramTypeProvider;
import org.eclipse.graphiti.features.IAddFeature;
import org.eclipse.graphiti.features.ICopyFeature;
import org.eclipse.graphiti.features.ICreateConnectionFeature;
import org.eclipse.graphiti.features.ICreateFeature;
import org.eclipse.graphiti.features.IDeleteFeature;
import org.eclipse.graphiti.features.IDirectEditingFeature;
import org.eclipse.graphiti.features.ILayoutFeature;
import org.eclipse.graphiti.features.IMoveConnectionDecoratorFeature;
import org.eclipse.graphiti.features.IMoveShapeFeature;
import org.eclipse.graphiti.features.IPasteFeature;
import org.eclipse.graphiti.features.IReconnectionFeature;
import org.eclipse.graphiti.features.IResizeShapeFeature;
import org.eclipse.graphiti.features.IUpdateFeature;
import org.eclipse.graphiti.features.context.IAddContext;
import org.eclipse.graphiti.features.context.ICopyContext;
import org.eclipse.graphiti.features.context.ICustomContext;
import org.eclipse.graphiti.features.context.IDeleteContext;
import org.eclipse.graphiti.features.context.IDirectEditingContext;
import org.eclipse.graphiti.features.context.ILayoutContext;
import org.eclipse.graphiti.features.context.IMoveConnectionDecoratorContext;
import org.eclipse.graphiti.features.context.IMoveShapeContext;
import org.eclipse.graphiti.features.context.IPasteContext;
import org.eclipse.graphiti.features.context.IReconnectionContext;
import org.eclipse.graphiti.features.context.IResizeShapeContext;
import org.eclipse.graphiti.features.context.IUpdateContext;
import org.eclipse.graphiti.features.custom.ICustomFeature;
import org.eclipse.graphiti.mm.algorithms.Image;
import org.eclipse.graphiti.mm.pictograms.PictogramElement;
import org.eclipse.graphiti.pattern.AddFeatureForPattern;
import org.eclipse.graphiti.pattern.DefaultFeatureProviderWithPatterns;
import org.eclipse.graphiti.platform.IDiagramContainer;
import org.eclipse.ogee.designer.ODataEditor;
import org.eclipse.ogee.designer.contexts.AddReferencedEntityContext;
import org.eclipse.ogee.designer.contexts.AssociationAddConnectionContext;
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.features.ODataAddBiDirectionalAssociationFeature;
import org.eclipse.ogee.designer.features.ODataAddComplexPropertyFeature;
import org.eclipse.ogee.designer.features.ODataAddComplexTypeFeature;
import org.eclipse.ogee.designer.features.ODataAddEntitySetFeature;
import org.eclipse.ogee.designer.features.ODataAddEntityTypeFeature;
import org.eclipse.ogee.designer.features.ODataAddEnumMemberFeature;
import org.eclipse.ogee.designer.features.ODataAddEnumPropertyFeature;
import org.eclipse.ogee.designer.features.ODataAddFunctionImportFeature;
import org.eclipse.ogee.designer.features.ODataAddParameterFeature;
import org.eclipse.ogee.designer.features.ODataAddPropertyFeature;
import org.eclipse.ogee.designer.features.ODataAddReturnTypeFeature;
import org.eclipse.ogee.designer.features.ODataAddUniDirectionalAssociationFeature;
import org.eclipse.ogee.designer.features.ODataCommonLayoutFeature;
import org.eclipse.ogee.designer.features.ODataCopyFeature;
import org.eclipse.ogee.designer.features.ODataCreateBiDirectionalAssociationFeature;
import org.eclipse.ogee.designer.features.ODataCreateComplexTypeFeature;
import org.eclipse.ogee.designer.features.ODataCreateEntityTypeFeature;
import org.eclipse.ogee.designer.features.ODataCreateFunctionImportFeature;
import org.eclipse.ogee.designer.features.ODataCreateUniDirectionalAssociationFeature;
import org.eclipse.ogee.designer.features.ODataDeleteFeature;
import org.eclipse.ogee.designer.features.ODataDirectEditingFeature;
import org.eclipse.ogee.designer.features.ODataLinkUsageFeature;
import org.eclipse.ogee.designer.features.ODataPasteFeature;
import org.eclipse.ogee.designer.features.ODataReferencedEntityDirectEditingFeature;
import org.eclipse.ogee.designer.features.ODataResizeFeature;
import org.eclipse.ogee.designer.features.ODataReturnTypeDirectEditingFeature;
import org.eclipse.ogee.designer.features.ODataUpdateFeature;
import org.eclipse.ogee.designer.patterns.ReferenceEntityTypePattern;
import org.eclipse.ogee.designer.types.AssociationType;
import org.eclipse.ogee.designer.types.FunctionImportReturnType;
import org.eclipse.ogee.designer.utils.ArtifactUtil;
import org.eclipse.ogee.designer.utils.PropertyUtil;
import org.eclipse.ogee.model.odata.impl.AssociationImpl;
import org.eclipse.ogee.model.odata.impl.ComplexTypeImpl;
import org.eclipse.ogee.model.odata.impl.EntityTypeImpl;
import org.eclipse.ogee.model.odata.impl.FunctionImportImpl;
/**
*
* All the patterns and Features will be registered in this feature provider
* class.
*
*/
public class ODataFeatureProvider extends DefaultFeatureProviderWithPatterns {
/**
* ShapesFactory instance used to create all the shapes.
*/
private ShapesFactory shapesFactory;
/**
* ArtifactFactory instance used to create all the Business objects.
*/
private ArtifactFactory artifactFactory;
/**
* Initializing feature provider and Registers entity type pattern.
*
* @param dtp
*/
private ReferenceEntityTypePattern referenceEntityTypePattern = null;
public ODataFeatureProvider(IDiagramTypeProvider dtp) {
super(dtp);
// Create a new ShapesFactory. This will in turn create all the
// necessary shapes for the artifacts
this.shapesFactory = new ShapesFactory(this);
// New ArtifactFactory creates the necessary artifacts
this.artifactFactory = new ArtifactFactory();
}
/**
* Returns ArtifactFactory associated with this FeatureProvider
*
* @return ArtifactFactory
*/
public ArtifactFactory getArtifactFactory() {
return this.artifactFactory;
}
/**
* Returns ShapesFactory associated with this FeatureProvider
*
* @return ShapesFactory
*/
public ShapesFactory getShapesFactory() {
return this.shapesFactory;
}
/**
* Returns the IDirectEditingFeature
*
* @param context
* IDirectEditingContext instance
* @return IDirectEditingFeature
*/
@Override
public IDirectEditingFeature getDirectEditingFeature(
IDirectEditingContext context) {
if (this.isReadOnlyModel()) {
return null;
}
// Pictogram element on which direct editing is invoked from the UI
PictogramElement pe = context.getPictogramElement();
// Business object from the UI element
Object obj = getBusinessObjectForPictogramElement((PictogramElement) pe
.eContainer());
// Only enable editing on Entity name
if (ArtifactUtil.isEditable(obj)) {
if (ArtifactUtil.isFunctionImportReturnType(obj)) {
return new ODataReturnTypeDirectEditingFeature(this,
this.artifactFactory, this.shapesFactory);
} else if (ArtifactUtil.isEnumType(obj)) {
if (PropertyUtil.isEnumTypeName(pe)) {
return new ODataDirectEditingFeature(this,
this.artifactFactory, this.shapesFactory);
}
} else if (ArtifactUtil.isReferencedEntityType(obj)) {
return new ODataReferencedEntityDirectEditingFeature(this,
this.artifactFactory, this.shapesFactory);
}
return new ODataDirectEditingFeature(this, this.artifactFactory,
this.shapesFactory);
}
return super.getDirectEditingFeature(context);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.graphiti.pattern.DefaultFeatureProviderWithPatterns#
* getUpdateFeature(org.eclipse.graphiti.features.context.IUpdateContext)
*/
/**
*
*/
@Override
public IUpdateFeature getUpdateFeature(IUpdateContext context) {
// Pictogram element on which direct editing is invoked from the UI
PictogramElement pe = context.getPictogramElement();
if (this.isReadOnlyModel()) {
// This condition to update expand/Collapse Image
boolean isCollapsableImage = PropertyUtil.isTitle(pe)
&& pe.getGraphicsAlgorithm() instanceof Image;
if (!isCollapsableImage) {
return null;
}
}
// Business object from the UI element
Object obj = getBusinessObjectForPictogramElement(pe);
if (ArtifactUtil.isEditable(obj) && PropertyUtil.canUpdate(pe)) {
return new ODataUpdateFeature(this);
}
return super.getUpdateFeature(context);
}
/**
* AddProperty Feature is added to Custom Features List. This method will be
* called on creation of context menu.
*/
@Override
public ICustomFeature[] getCustomFeatures(ICustomContext context) {
if (this.isReadOnlyModel()) {
return null;
}
ICustomFeature[] ret = super.getCustomFeatures(context);
List<ICustomFeature> retList = new ArrayList<ICustomFeature>();
retList.addAll(Arrays.asList(ret));
PictogramElement[] pictogramElements = context.getPictogramElements();
if (pictogramElements != null && pictogramElements.length > 0) {
Object businessObject = getBusinessObjectForPictogramElement(pictogramElements[0]);
if (ArtifactUtil.isEntityType(businessObject)) {
retList.add(new ODataAddPropertyFeature(this,
this.artifactFactory, this.shapesFactory));
// to add entity set from the context menu of entity type
retList.add(new ODataAddEntitySetFeature(this,
this.artifactFactory, this.shapesFactory));
// to add complex type from the context menu of entity type
retList.add(new ODataAddComplexPropertyFeature(this,
this.artifactFactory, this.shapesFactory));
// to add enum type from the context menu of entity type
retList.add(new ODataAddEnumPropertyFeature(this,
this.artifactFactory, this.shapesFactory));
} else if (ArtifactUtil.isFunctionImport(businessObject)) {
// to add parameter from the context menu of Function Import
retList.add(new ODataAddParameterFeature(this,
this.artifactFactory, this.shapesFactory));
// to add return type from the context menu of Function Import
retList.add(new ODataAddReturnTypeFeature(this,
this.artifactFactory, this.shapesFactory,
FunctionImportReturnType.SIMPLE));
// to add return type from the context menu of Function Import
retList.add(new ODataAddReturnTypeFeature(this,
this.artifactFactory, this.shapesFactory,
FunctionImportReturnType.COMPLEX));
// to add return type from the context menu of Function Import
retList.add(new ODataAddReturnTypeFeature(this,
this.artifactFactory, this.shapesFactory,
FunctionImportReturnType.ENTITY));
// to add return type from the context menu of Function Import
retList.add(new ODataAddReturnTypeFeature(this,
this.artifactFactory, this.shapesFactory,
FunctionImportReturnType.ENUM));
} else if (ArtifactUtil.isComplexType(businessObject)) {
retList.add(new ODataAddPropertyFeature(this,
this.artifactFactory, this.shapesFactory));
// to add complex type from the context menu of entity type
retList.add(new ODataAddComplexPropertyFeature(this,
this.artifactFactory, this.shapesFactory));
// to add enum type from the context menu of entity type
retList.add(new ODataAddEnumPropertyFeature(this,
this.artifactFactory, this.shapesFactory));
// to add complex type from the context menu of entity type
retList.add(new ODataLinkUsageFeature(this,
this.artifactFactory, this.shapesFactory));
} else if (ArtifactUtil.isEnumType(businessObject)) {
retList.add(new ODataAddEnumMemberFeature(this,
this.artifactFactory, this.shapesFactory));
}
}
return retList.toArray(new ICustomFeature[] {});
}
@Override
public IMoveShapeFeature getMoveShapeFeature(IMoveShapeContext context) {
if (!PropertyUtil.isMovableShape(context)) {
return null;
}
return super.getMoveShapeFeature(context);
}
@Override
public IDeleteFeature getDeleteFeature(IDeleteContext context) {
if (context instanceof LinkUsageContext) {
LinkUsageContext lc = (LinkUsageContext) context;
if (lc.isDeletable()) {
return new ODataDeleteFeature(this);
}
}
return new ODataDeleteFeature(this);
}
@Override
protected IDeleteFeature getDeleteFeatureAdditional(IDeleteContext context) {
if (this.isReadOnlyModel()) {
return null;
}
return new ODataDeleteFeature(this);
}
/**
* To restrict connection decorator moving (for multiplicity)
*/
@Override
public IMoveConnectionDecoratorFeature getMoveConnectionDecoratorFeature(
IMoveConnectionDecoratorContext context) {
return null;
}
/**
* The following method checks if the current model is a read-only model.
*
* @return boolean
*/
public boolean isReadOnlyModel() {
boolean isReadOnlyModel = false;
final IDiagramContainer diagramEditor = this.getDiagramTypeProvider()
.getDiagramBehavior().getDiagramContainer();
if (diagramEditor instanceof ODataEditor) {
if (((ODataEditor) diagramEditor).isReadOnly()) {
isReadOnlyModel = true;
}
}
return isReadOnlyModel;
}
/**
* This is overridden so as to not allow movement of associations/links
*
*/
@Override
public IReconnectionFeature getReconnectionFeature(
IReconnectionContext context) {
return null;
}
@Override
public IAddFeature getAddFeature(IAddContext context) {
if (context instanceof AddReferencedEntityContext) {
if (referenceEntityTypePattern != null) {
if (referenceEntityTypePattern.canAdd(context)) {
return new AddFeatureForPattern(this,
referenceEntityTypePattern);
}
}
} else if (context.getNewObject() instanceof EntityTypeImpl) {
return new ODataAddEntityTypeFeature(this, this.artifactFactory,
this.shapesFactory);
} else if (context.getNewObject() instanceof ComplexTypeImpl) {
return new ODataAddComplexTypeFeature(this, this.artifactFactory,
this.shapesFactory);
} else if (context.getNewObject() instanceof FunctionImportImpl) {
return new ODataAddFunctionImportFeature(this,
this.artifactFactory, this.shapesFactory);
} else if (context.getNewObject() instanceof AssociationImpl) {
AssociationType type = ((AssociationAddConnectionContext) context)
.getAssociationType();
if (type == AssociationType.UNIDIR || type == AssociationType.NONE) {
return new ODataAddUniDirectionalAssociationFeature(this,
this.artifactFactory, this.shapesFactory);
} else if (type == AssociationType.BIDIR) {
return new ODataAddBiDirectionalAssociationFeature(this,
this.artifactFactory, this.shapesFactory);
}
}
return super.getAddFeature(context);
}
@Override
public ICopyFeature getCopyFeature(ICopyContext context) {
return new ODataCopyFeature(this);
}
@Override
public IPasteFeature getPasteFeature(IPasteContext context) {
return new ODataPasteFeature(this);
}
@Override
public ICreateFeature[] getCreateFeatures() {
return new ICreateFeature[] {
new ODataCreateEntityTypeFeature(this, this.shapesFactory,
this.artifactFactory),
new ODataCreateComplexTypeFeature(this, this.shapesFactory,
this.artifactFactory),
new ODataCreateFunctionImportFeature(this, this.shapesFactory,
this.artifactFactory) };
}
@Override
public ILayoutFeature getLayoutFeature(ILayoutContext context) {
return new ODataCommonLayoutFeature(this);
}
@Override
public IResizeShapeFeature getResizeShapeFeature(IResizeShapeContext context) {
if (!PropertyUtil.isMovableShape(context)) {
return null;
}
return new ODataResizeFeature(this);
}
@Override
public ICreateConnectionFeature[] getCreateConnectionFeatures() {
return new ICreateConnectionFeature[] {
new ODataCreateUniDirectionalAssociationFeature(this,
shapesFactory, artifactFactory),
new ODataCreateBiDirectionalAssociationFeature(this,
shapesFactory, artifactFactory) };
}
}