Merge "Bug 385193 - Provide ID pattern to lower development effort"
diff --git a/examples/org.eclipse.graphiti.examples.filesystem/src/org/eclipse/graphiti/examples/filesystem/diagram/FilesystemFeatureProvider.java b/examples/org.eclipse.graphiti.examples.filesystem/src/org/eclipse/graphiti/examples/filesystem/diagram/FilesystemFeatureProvider.java
index 8141a4b..63d9d94 100644
--- a/examples/org.eclipse.graphiti.examples.filesystem/src/org/eclipse/graphiti/examples/filesystem/diagram/FilesystemFeatureProvider.java
+++ b/examples/org.eclipse.graphiti.examples.filesystem/src/org/eclipse/graphiti/examples/filesystem/diagram/FilesystemFeatureProvider.java
@@ -23,6 +23,7 @@
import org.eclipse.graphiti.examples.filesystem.features.AddContainmentConnectionFeature;
import org.eclipse.graphiti.examples.filesystem.features.CreateContainmentConnectionFeature;
import org.eclipse.graphiti.examples.filesystem.features.GradientColorFeature;
+import org.eclipse.graphiti.examples.filesystem.patterns.FilePattern;
import org.eclipse.graphiti.examples.filesystem.patterns.FolderPattern;
import org.eclipse.graphiti.examples.filesystem.ui.FilesystemPredefinedColoredAreas;
import org.eclipse.graphiti.features.IAddFeature;
@@ -42,6 +43,7 @@
public FilesystemFeatureProvider(IDiagramTypeProvider dtp) {
super(dtp);
addPattern(new FolderPattern());
+ addPattern(new FilePattern());
}
@Override
@@ -67,4 +69,4 @@
ret = retList.toArray(ret);
return ret;
}
-}
\ No newline at end of file
+}
diff --git a/examples/org.eclipse.graphiti.examples.filesystem/src/org/eclipse/graphiti/examples/filesystem/patterns/FilePattern.java b/examples/org.eclipse.graphiti.examples.filesystem/src/org/eclipse/graphiti/examples/filesystem/patterns/FilePattern.java
new file mode 100644
index 0000000..03303cb
--- /dev/null
+++ b/examples/org.eclipse.graphiti.examples.filesystem/src/org/eclipse/graphiti/examples/filesystem/patterns/FilePattern.java
@@ -0,0 +1,222 @@
+package org.eclipse.graphiti.examples.filesystem.patterns;
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.graphiti.examples.mm.filesystem.File;
+import org.eclipse.graphiti.examples.mm.filesystem.FilesystemFactory;
+import org.eclipse.graphiti.features.IReason;
+import org.eclipse.graphiti.features.context.IAddContext;
+import org.eclipse.graphiti.features.context.ICreateContext;
+import org.eclipse.graphiti.features.context.IDirectEditingContext;
+import org.eclipse.graphiti.features.impl.Reason;
+import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;
+import org.eclipse.graphiti.mm.algorithms.Rectangle;
+import org.eclipse.graphiti.mm.algorithms.RoundedRectangle;
+import org.eclipse.graphiti.mm.algorithms.Text;
+import org.eclipse.graphiti.mm.algorithms.styles.Orientation;
+import org.eclipse.graphiti.mm.pictograms.ContainerShape;
+import org.eclipse.graphiti.mm.pictograms.Diagram;
+import org.eclipse.graphiti.mm.pictograms.PictogramElement;
+import org.eclipse.graphiti.mm.pictograms.Shape;
+import org.eclipse.graphiti.pattern.IPattern;
+import org.eclipse.graphiti.pattern.id.IdAddContext;
+import org.eclipse.graphiti.pattern.id.IdLayoutContext;
+import org.eclipse.graphiti.pattern.id.IdPattern;
+import org.eclipse.graphiti.pattern.id.IdUpdateContext;
+import org.eclipse.graphiti.services.Graphiti;
+import org.eclipse.graphiti.services.IGaService;
+import org.eclipse.graphiti.services.IPeCreateService;
+import org.eclipse.graphiti.util.PredefinedColoredAreas;
+
+public class FilePattern extends IdPattern implements IPattern {
+
+ private static final String ID_NAME_TEXT = "nameText";
+ private static final String ID_OUTER_RECTANGLE = "outerRectangle";
+ private static final String ID_MAIN_RECTANGLE = "mainRectangle";
+
+ public FilePattern() {
+ super();
+ }
+
+ @Override
+ public String getCreateName() {
+ return "File";
+ }
+
+ @Override
+ public boolean isMainBusinessObjectApplicable(Object mainBusinessObject) {
+ return mainBusinessObject instanceof File;
+ }
+
+ @Override
+ public boolean canCreate(ICreateContext context) {
+ return context.getTargetContainer() instanceof Diagram;
+ }
+
+ @Override
+ public Object[] create(ICreateContext context) {
+ File newFile = FilesystemFactory.eINSTANCE.createFile();
+ newFile.setName(createNewName());
+
+ getDiagram().eResource().getContents().add(newFile);
+
+ addGraphicalRepresentation(context, newFile);
+ return new Object[] { newFile };
+ }
+
+ @Override
+ public boolean canAdd(IAddContext context) {
+ return super.canAdd(context) && context.getTargetContainer() instanceof Diagram;
+ }
+
+ @Override
+ public PictogramElement add(IdAddContext context) {
+ Diagram targetDiagram = (Diagram) context.getTargetContainer();
+ File addedDomainObject = (File) context.getNewObject();
+ IPeCreateService peCreateService = Graphiti.getPeCreateService();
+ IGaService gaService = Graphiti.getGaService();
+
+ // Outer container (invisible)
+ ContainerShape outerContainerShape = peCreateService.createContainerShape(targetDiagram, true);
+ Rectangle outerRectangle = gaService.createInvisibleRectangle(outerContainerShape);
+ setId(outerRectangle, ID_OUTER_RECTANGLE);
+ gaService.setLocationAndSize(outerRectangle, context.getX(), context.getY(), context.getWidth(),
+ context.getHeight());
+
+ // Register tab
+ RoundedRectangle registerRectangle = gaService.createRoundedRectangle(outerRectangle, 5, 5);
+ gaService.setLocationAndSize(registerRectangle, 0, 0, 20, 20);
+ registerRectangle.setFilled(true);
+ gaService.setRenderingStyle(registerRectangle, PredefinedColoredAreas.getSilverWhiteGlossAdaptions());
+
+ // Main contents area
+ Rectangle mainRectangle = gaService.createRectangle(outerRectangle);
+ setId(mainRectangle, ID_MAIN_RECTANGLE);
+ mainRectangle.setFilled(true);
+ gaService.setRenderingStyle(mainRectangle, PredefinedColoredAreas.getSilverWhiteGlossAdaptions());
+
+ // File name
+ Shape shape = peCreateService.createShape(outerContainerShape, false);
+ Text text = gaService.createText(shape, addedDomainObject.getName());
+ setId(text, ID_NAME_TEXT);
+ text.setHorizontalAlignment(Orientation.ALIGNMENT_CENTER);
+ text.setVerticalAlignment(Orientation.ALIGNMENT_CENTER);
+
+ peCreateService.createChopboxAnchor(outerContainerShape);
+
+ link(outerContainerShape, addedDomainObject);
+ link(shape, addedDomainObject);
+
+ return outerContainerShape;
+ }
+
+ @Override
+ protected boolean layout(IdLayoutContext context, String id) {
+ boolean changesDone = false;
+
+ Rectangle outerRectangle = (Rectangle) context.getRootPictogramElement().getGraphicsAlgorithm();
+
+ if (id.equals(ID_MAIN_RECTANGLE) || id.equals(ID_NAME_TEXT)) {
+ GraphicsAlgorithm ga = context.getGraphicsAlgorithm();
+ Graphiti.getGaService().setLocationAndSize(ga, 0, 10, outerRectangle.getWidth(),
+ outerRectangle.getHeight() - 10);
+ changesDone = true;
+ }
+
+ return changesDone;
+ }
+
+ @Override
+ protected IReason updateNeeded(IdUpdateContext context, String id) {
+ if (id.equals(ID_NAME_TEXT)) {
+ Text nameText = (Text) context.getGraphicsAlgorithm();
+ File domainObject = (File) context.getDomainObject();
+ if (domainObject.getName() == null || !domainObject.getName().equals(nameText.getValue())) {
+ return Reason.createTrueReason("Name differs. Expected: '" + domainObject.getName() + "'");
+ }
+ }
+
+ return Reason.createFalseReason();
+ }
+
+ @Override
+ protected boolean update(IdUpdateContext context, String id) {
+ if (id.equals(ID_NAME_TEXT)) {
+ Text nameText = (Text) context.getGraphicsAlgorithm();
+ File domainObject = (File) context.getDomainObject();
+ nameText.setValue(domainObject.getName());
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public int getEditingType() {
+ return TYPE_TEXT;
+ }
+
+ @Override
+ public boolean canDirectEdit(IDirectEditingContext context) {
+ Object domainObject = getBusinessObjectForPictogramElement(context.getPictogramElement());
+ GraphicsAlgorithm ga = context.getGraphicsAlgorithm();
+ if (domainObject instanceof File && ga instanceof Text) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public String getInitialValue(IDirectEditingContext context) {
+ File file = (File) getBusinessObjectForPictogramElement(context.getPictogramElement());
+ return file.getName();
+ }
+
+ @Override
+ public String checkValueValid(String value, IDirectEditingContext context) {
+ if (value == null || value.length() == 0) {
+ return "File name must not be empty";
+ }
+
+ File file = (File) getBusinessObjectForPictogramElement(context.getPictogramElement());
+ EList<Shape> children = getDiagram().getChildren();
+ for (Shape child : children) {
+ Object domainObject = getBusinessObjectForPictogramElement(child);
+ if (domainObject instanceof File) {
+ if (!domainObject.equals(file) && value.equals(((File) domainObject).getName())) {
+ return "A file with name '" + ((File) domainObject).getName() + "' already exists.";
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void setValue(String value, IDirectEditingContext context) {
+ File file = (File) getBusinessObjectForPictogramElement(context.getPictogramElement());
+ file.setName(value);
+ updatePictogramElement(context.getPictogramElement());
+ }
+
+ private String createNewName() {
+ String initialName = "NewFile";
+ String name = initialName;
+ int number = 0;
+ while (findFile(name) != null) {
+ number++;
+ name = initialName + number;
+ }
+ return name;
+ }
+
+ private File findFile(String name) {
+ EList<EObject> contents = getDiagram().eResource().getContents();
+ for (EObject eObject : contents) {
+ if (eObject instanceof File) {
+ if (name.equals(((File) eObject).getName())) {
+ return (File) eObject;
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/plugins/org.eclipse.graphiti.pattern/META-INF/MANIFEST.MF b/plugins/org.eclipse.graphiti.pattern/META-INF/MANIFEST.MF
index 7b15654..f7267a6 100644
--- a/plugins/org.eclipse.graphiti.pattern/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.graphiti.pattern/META-INF/MANIFEST.MF
@@ -8,6 +8,7 @@
Bundle-Localization: plugin
Export-Package: org.eclipse.graphiti.pattern;version="0.10.0",
org.eclipse.graphiti.pattern.config;version="0.10.0",
+ org.eclipse.graphiti.pattern.id,
org.eclipse.graphiti.pattern.mapping;version="0.10.0",
org.eclipse.graphiti.pattern.mapping.data;version="0.10.0"
Bundle-ActivationPolicy: lazy
diff --git a/plugins/org.eclipse.graphiti.pattern/src/org/eclipse/graphiti/pattern/TypedPattern.java b/plugins/org.eclipse.graphiti.pattern/src/org/eclipse/graphiti/pattern/TypedPattern.java
new file mode 100644
index 0000000..f1589a2
--- /dev/null
+++ b/plugins/org.eclipse.graphiti.pattern/src/org/eclipse/graphiti/pattern/TypedPattern.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * <copyright>
+ *
+ * Copyright (c) 2012, 2012 SAP AG.
+ * 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 AG - initial API, implementation and documentation
+ *
+ * </copyright>
+ *
+ *******************************************************************************/
+package org.eclipse.graphiti.pattern;
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.graphiti.mm.Property;
+import org.eclipse.graphiti.mm.PropertyContainer;
+import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;
+import org.eclipse.graphiti.mm.pictograms.ContainerShape;
+import org.eclipse.graphiti.mm.pictograms.Diagram;
+import org.eclipse.graphiti.mm.pictograms.PictogramElement;
+import org.eclipse.graphiti.mm.pictograms.Shape;
+import org.eclipse.graphiti.pattern.config.IPatternConfiguration;
+import org.eclipse.graphiti.services.Graphiti;
+
+/**
+ * This class provides the basis for all specific pattern types. It provides
+ * functionality to tag a shape as being created and maintained by a specific
+ * pattern type. Type type is identified using a special {@link Property} with
+ * the key PROPERTY_KEY_PATTERN_TYPE.
+ *
+ * @since 0.10
+ */
+public abstract class TypedPattern extends AbstractPattern {
+
+ protected static final String PROPERTY_KEY_PATTERN_TYPE = "org.eclipse.graphiti.pattern.patternType";
+
+ public TypedPattern() {
+ super();
+ }
+
+ public TypedPattern(IPatternConfiguration patternConfiguration) {
+ super(patternConfiguration);
+ }
+
+ /**
+ * Sets the property that indicates that the given root shape of the pattern
+ * is created and maintained by a specific pattern type.
+ *
+ * @param patternRootShape
+ * The {@link PropertyContainer} object that is used as root
+ * shape of the pattern.
+ * @param patternType
+ * The {@link String} type of the pattern.
+ */
+ protected void setPatternType(PropertyContainer patternRootShape, String patternType) {
+ Graphiti.getPeService().setPropertyValue(patternRootShape, PROPERTY_KEY_PATTERN_TYPE, patternType);
+ }
+
+ /**
+ * Returns the property that indicates that the given root shape of the
+ * pattern is created and maintained by a specific pattern type if it is set
+ * for the given shape or one of its parents. If the property is set for the
+ * given shape it is returned, otherwise the parents are asked for the
+ * property; first the parent {@link ContainerShape} in the shape hierarchy
+ * is asked if there is no parent the {@link GraphicsAlgorithm} parent is
+ * asked.
+ *
+ * @param patternRootShape
+ * The {@link PropertyContainer} object that is used as root
+ * shape of the pattern.
+ * @return The {@link String} type of the pattern.
+ */
+ protected String getPatternType(PropertyContainer patternRootShape) {
+ EList<Property> properties = patternRootShape.getProperties();
+ for (Property property : properties) {
+ if (PROPERTY_KEY_PATTERN_TYPE.equals(property.getKey())) {
+ return property.getValue();
+ }
+ }
+ if (patternRootShape instanceof Shape) {
+ ContainerShape parent = ((Shape) patternRootShape).getContainer();
+ if (parent != null && !(parent instanceof Diagram)) {
+ return getPatternType(parent);
+ }
+ } else if (patternRootShape instanceof GraphicsAlgorithm) {
+ PictogramElement pictogramElement = ((GraphicsAlgorithm) patternRootShape).getPictogramElement();
+ if (pictogramElement != null) {
+ return getPatternType(pictogramElement);
+ } else {
+ GraphicsAlgorithm parentGraphicsAlgorithm = ((GraphicsAlgorithm) patternRootShape)
+ .getParentGraphicsAlgorithm();
+ if (parentGraphicsAlgorithm != null) {
+ return getPatternType(parentGraphicsAlgorithm);
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/plugins/org.eclipse.graphiti.pattern/src/org/eclipse/graphiti/pattern/id/IdAddContext.java b/plugins/org.eclipse.graphiti.pattern/src/org/eclipse/graphiti/pattern/id/IdAddContext.java
new file mode 100644
index 0000000..a2b8df5
--- /dev/null
+++ b/plugins/org.eclipse.graphiti.pattern/src/org/eclipse/graphiti/pattern/id/IdAddContext.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * <copyright>
+ *
+ * Copyright (c) 2012, 2012 SAP AG.
+ * 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 AG - initial API, implementation and documentation
+ *
+ * </copyright>
+ *
+ *******************************************************************************/
+package org.eclipse.graphiti.pattern.id;
+
+import org.eclipse.graphiti.features.context.IAreaContext;
+import org.eclipse.graphiti.features.context.impl.AddContext;
+
+/**
+ * @since 0.10
+ * @experimental This API is in an experimental state and should be used by
+ * clients, as it not final and can be removed or changed without
+ * prior notice!
+ */
+public class IdAddContext extends AddContext {
+
+ public IdAddContext() {
+ super();
+ }
+
+ public IdAddContext(IAreaContext context, Object newObject) {
+ super(context, newObject);
+ }
+}
diff --git a/plugins/org.eclipse.graphiti.pattern/src/org/eclipse/graphiti/pattern/id/IdLayoutContext.java b/plugins/org.eclipse.graphiti.pattern/src/org/eclipse/graphiti/pattern/id/IdLayoutContext.java
new file mode 100644
index 0000000..7100190
--- /dev/null
+++ b/plugins/org.eclipse.graphiti.pattern/src/org/eclipse/graphiti/pattern/id/IdLayoutContext.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * <copyright>
+ *
+ * Copyright (c) 2012, 2012 SAP AG.
+ * 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 AG - initial API, implementation and documentation
+ *
+ * </copyright>
+ *
+ *******************************************************************************/
+package org.eclipse.graphiti.pattern.id;
+
+import org.eclipse.graphiti.features.context.impl.LayoutContext;
+import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;
+import org.eclipse.graphiti.mm.pictograms.PictogramElement;
+
+/**
+ * @since 0.10
+ * @experimental This API is in an experimental state and should be used by
+ * clients, as it not final and can be removed or changed without
+ * prior notice!
+ */
+public class IdLayoutContext extends LayoutContext {
+
+ private GraphicsAlgorithm graphicsAlgorithm;
+ private PictogramElement rootPictogramElement;
+
+ public IdLayoutContext(PictogramElement pictogramElement, GraphicsAlgorithm graphicsAlgorithm,
+ PictogramElement rootPictogramElement) {
+ super(pictogramElement);
+ this.graphicsAlgorithm = graphicsAlgorithm;
+ this.rootPictogramElement = rootPictogramElement;
+ }
+
+ public GraphicsAlgorithm getGraphicsAlgorithm() {
+ return graphicsAlgorithm;
+ }
+
+ public void setGraphicsAlgorithm(GraphicsAlgorithm graphicsAlgorithm) {
+ this.graphicsAlgorithm = graphicsAlgorithm;
+ }
+
+ public PictogramElement getRootPictogramElement() {
+ return rootPictogramElement;
+ }
+
+ public void setRootPictogramElement(PictogramElement rootPictogramElement) {
+ this.rootPictogramElement = rootPictogramElement;
+ }
+}
diff --git a/plugins/org.eclipse.graphiti.pattern/src/org/eclipse/graphiti/pattern/id/IdPattern.java b/plugins/org.eclipse.graphiti.pattern/src/org/eclipse/graphiti/pattern/id/IdPattern.java
new file mode 100644
index 0000000..90f6cfa
--- /dev/null
+++ b/plugins/org.eclipse.graphiti.pattern/src/org/eclipse/graphiti/pattern/id/IdPattern.java
@@ -0,0 +1,577 @@
+/*******************************************************************************
+ * <copyright>
+ *
+ * Copyright (c) 2012, 2012 SAP AG.
+ * 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 AG - initial API, implementation and documentation
+ *
+ * </copyright>
+ *
+ *******************************************************************************/
+package org.eclipse.graphiti.pattern.id;
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.graphiti.features.IReason;
+import org.eclipse.graphiti.features.context.IAddContext;
+import org.eclipse.graphiti.features.context.IDirectEditingContext;
+import org.eclipse.graphiti.features.context.ILayoutContext;
+import org.eclipse.graphiti.features.context.IUpdateContext;
+import org.eclipse.graphiti.features.context.impl.AreaContext;
+import org.eclipse.graphiti.features.context.impl.LayoutContext;
+import org.eclipse.graphiti.features.impl.Reason;
+import org.eclipse.graphiti.mm.Property;
+import org.eclipse.graphiti.mm.PropertyContainer;
+import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;
+import org.eclipse.graphiti.mm.pictograms.ContainerShape;
+import org.eclipse.graphiti.mm.pictograms.PictogramElement;
+import org.eclipse.graphiti.mm.pictograms.Shape;
+import org.eclipse.graphiti.pattern.IPattern;
+import org.eclipse.graphiti.pattern.TypedPattern;
+import org.eclipse.graphiti.services.Graphiti;
+
+/**
+ * Base class for ID patterns. The basic idea behind is to tag single parts of a
+ * pattern shape with IDs (using {@link Property} objects). These IDs are used
+ * to identify the parts of that shape and to call the update and layout methods
+ * for the shapes with IDs. Clients do not need to search through the shape
+ * hierarchy to find the shapes to update and layout.
+ *
+ * @since 0.10
+ * @experimental This API is in an experimental state and should be used by
+ * clients, as it not final and can be removed or changed without
+ * prior notice!
+ */
+public abstract class IdPattern extends TypedPattern implements IPattern {
+
+ protected static final String PROPERTY_VALUE_PATTERN_TYPE_ID = "org.eclipse.graphiti.pattern.idpattern"; //$NON-NLS-1$
+ protected static final String PROPERTY_KEY_ID = "org.eclipse.graphiti.pattern.id.id"; //$NON-NLS-1$
+
+ public IdPattern() {
+ super();
+ }
+
+ /*
+ * Base functionality
+ */
+
+ @Override
+ protected boolean isPatternControlled(PictogramElement pictogramElement) {
+ Object domainObject = getBusinessObjectForPictogramElement(pictogramElement);
+ return isMainBusinessObjectApplicable(domainObject);
+ }
+
+ @Override
+ protected boolean isPatternRoot(PictogramElement pictogramElement) {
+ Object domainObject = getBusinessObjectForPictogramElement(pictogramElement);
+ if (!isMainBusinessObjectApplicable(domainObject)) {
+ return false;
+ }
+ EList<Property> properties = pictogramElement.getProperties();
+ boolean rootPropertyFound = false;
+ for (Property property : properties) {
+ if (PROPERTY_KEY_PATTERN_TYPE.equals(property.getKey())
+ && PROPERTY_VALUE_PATTERN_TYPE_ID.equals(property.getValue())) {
+ rootPropertyFound = true;
+ }
+ }
+ return rootPropertyFound;
+ }
+
+ /*
+ * ID handling
+ */
+
+ protected void setId(PropertyContainer container, String id) {
+ Graphiti.getPeService().setPropertyValue(container, PROPERTY_KEY_ID, id);
+ }
+
+ protected String getId(PropertyContainer container) {
+ EList<Property> properties = container.getProperties();
+ for (Property property : properties) {
+ if (PROPERTY_KEY_ID.equals(property.getKey())) {
+ return property.getValue();
+ }
+ }
+ return null;
+ }
+
+ protected PropertyContainer findById(PictogramElement pictogramElement, String idToFind) {
+ if (idToFind == null || idToFind.length() == 0) {
+ return null;
+ }
+
+ // Check id for PE
+ String id = getId(pictogramElement);
+ if (idToFind.equals(id)) {
+ return pictogramElement;
+ }
+
+ // Check id for GA
+ GraphicsAlgorithm graphicsAlgorithm = pictogramElement.getGraphicsAlgorithm();
+ id = getId(graphicsAlgorithm);
+ if (idToFind.equals(id)) {
+ return graphicsAlgorithm;
+ }
+
+ // Check children of PE
+ if (pictogramElement instanceof ContainerShape) {
+ EList<Shape> children = ((ContainerShape) pictogramElement).getChildren();
+ for (Shape shape : children) {
+ PropertyContainer propertyContainer = findById(shape, idToFind);
+ if (propertyContainer != null) {
+ return propertyContainer;
+ }
+ }
+ }
+
+ // Check children of GA
+ PropertyContainer propertyContainer = findByIdInGraphicsAlgorithmChildren(graphicsAlgorithm, idToFind);
+ if (propertyContainer != null) {
+ return propertyContainer;
+ }
+
+ return null;
+ }
+
+ private PropertyContainer findByIdInGraphicsAlgorithmChildren(GraphicsAlgorithm graphicsAlgorithm, String idToFind) {
+ EList<GraphicsAlgorithm> graphicsAlgorithmChildren = graphicsAlgorithm.getGraphicsAlgorithmChildren();
+ for (GraphicsAlgorithm graphicsAlgorithmChild : graphicsAlgorithmChildren) {
+ String id = getId(graphicsAlgorithmChild);
+ if (idToFind.equals(id)) {
+ return graphicsAlgorithmChild;
+ }
+
+ PropertyContainer propertyContainer = findByIdInGraphicsAlgorithmChildren(graphicsAlgorithmChild, idToFind);
+ if (propertyContainer != null) {
+ return propertyContainer;
+ }
+ }
+ return null;
+ }
+
+ /*
+ * Add functionality
+ */
+
+ @Override
+ public boolean canAdd(IAddContext context) {
+ return isMainBusinessObjectApplicable(context.getNewObject());
+ }
+
+ @Override
+ public PictogramElement add(IAddContext context) {
+ AreaContext areaContext = new AreaContext();
+ areaContext.setHeight(context.getHeight());
+ areaContext.setWidth(context.getWidth());
+ areaContext.setLocation(context.getX(), context.getY());
+ IdAddContext addContext = new IdAddContext(areaContext, context.getNewObject());
+ addContext.setTargetConnection(context.getTargetConnection());
+ addContext.setTargetConnectionDecorator(context.getTargetConnectionDecorator());
+ addContext.setTargetContainer(context.getTargetContainer());
+ PictogramElement pictogramElement = add(addContext);
+ setPatternType(pictogramElement, PROPERTY_VALUE_PATTERN_TYPE_ID);
+ layout(new LayoutContext(pictogramElement));
+ return pictogramElement;
+ }
+
+ abstract protected PictogramElement add(IdAddContext context);
+
+ /*
+ * Layout functionality
+ */
+
+ @Override
+ public boolean canLayout(ILayoutContext context) {
+ return PROPERTY_VALUE_PATTERN_TYPE_ID.equals(getPatternType(context.getPictogramElement()))
+ && isMainBusinessObjectApplicable(getBusinessObjectForPictogramElement(context.getPictogramElement()));
+ }
+
+ @Override
+ public boolean layout(ILayoutContext context) {
+ boolean changesDone = false;
+
+ PictogramElement rootPictogramElement;
+ if (context instanceof IdLayoutContext) {
+ rootPictogramElement = ((IdLayoutContext) context).getRootPictogramElement();
+ } else {
+ rootPictogramElement = context.getPictogramElement();
+ while (!isPatternRoot(rootPictogramElement)) {
+ if (rootPictogramElement instanceof Shape) {
+ ContainerShape container = ((Shape) rootPictogramElement).getContainer();
+ if (container != null) {
+ rootPictogramElement = container;
+ } else {
+ break;
+ }
+ } else {
+ if (rootPictogramElement instanceof GraphicsAlgorithm) {
+ PictogramElement pictogramElement = ((GraphicsAlgorithm) rootPictogramElement)
+ .getPictogramElement();
+ if (pictogramElement != null) {
+ rootPictogramElement = pictogramElement;
+ } else {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // Check id for PE
+ PictogramElement pictogramElement = context.getPictogramElement();
+ String id = getId(pictogramElement);
+ if (id != null) {
+ IdLayoutContext layoutContext = new IdLayoutContext(pictogramElement,
+ pictogramElement.getGraphicsAlgorithm(), rootPictogramElement);
+ if (layout(layoutContext, id)) {
+ changesDone = true;
+ }
+ }
+
+ // Check id for GA
+ GraphicsAlgorithm graphicsAlgorithm = pictogramElement.getGraphicsAlgorithm();
+ id = getId(graphicsAlgorithm);
+ if (id != null) {
+ IdLayoutContext layoutContext = new IdLayoutContext(graphicsAlgorithm.getPictogramElement(),
+ graphicsAlgorithm, rootPictogramElement);
+ if (layout(layoutContext, id)) {
+ changesDone = true;
+ }
+ }
+
+ // Check children of PE
+ if (pictogramElement instanceof ContainerShape) {
+ EList<Shape> children = ((ContainerShape) pictogramElement).getChildren();
+ for (Shape shape : children) {
+ LayoutContext idContext = new IdLayoutContext(shape, shape.getGraphicsAlgorithm(), rootPictogramElement);
+ if (layout(idContext)) {
+ changesDone = true;
+ }
+ }
+ }
+
+ // Check children of GA
+ IdLayoutContext layoutContext;
+ if (context instanceof IdLayoutContext) {
+ layoutContext = (IdLayoutContext) context;
+ } else {
+ layoutContext = new IdLayoutContext(null, graphicsAlgorithm, rootPictogramElement);
+ }
+ if (checkLayoutChildren(graphicsAlgorithm, layoutContext)) {
+ changesDone = true;
+ }
+
+ return changesDone;
+ }
+
+ protected boolean checkLayoutChildren(GraphicsAlgorithm graphicsAlgorithm, IdLayoutContext context) {
+ boolean changesDone = false;
+ EList<GraphicsAlgorithm> graphicsAlgorithmChildren = graphicsAlgorithm.getGraphicsAlgorithmChildren();
+ for (GraphicsAlgorithm graphicsAlgorithmChild : graphicsAlgorithmChildren) {
+ String id = getId(graphicsAlgorithmChild);
+ if (id != null) {
+ IdLayoutContext layoutContext = new IdLayoutContext(graphicsAlgorithmChild.getPictogramElement(),
+ graphicsAlgorithmChild, context.getRootPictogramElement());
+ if (layout(layoutContext, id)) {
+ changesDone = true;
+ }
+ }
+ if (checkLayoutChildren(graphicsAlgorithmChild, context)) {
+ changesDone = true;
+ }
+ }
+ return changesDone;
+ }
+
+ abstract protected boolean layout(IdLayoutContext context, String id);
+
+ /*
+ * Update functionality
+ */
+
+ @Override
+ public boolean canUpdate(IUpdateContext context) {
+ return PROPERTY_VALUE_PATTERN_TYPE_ID.equals(getPatternType(context.getPictogramElement()))
+ && isMainBusinessObjectApplicable(getBusinessObjectForPictogramElement(context.getPictogramElement()));
+ }
+
+ @Override
+ public IReason updateNeeded(IUpdateContext context) {
+
+ PictogramElement rootPictogramElement;
+ if (context instanceof IdUpdateContext) {
+ rootPictogramElement = ((IdUpdateContext) context).getRootPictogramElement();
+ } else {
+ rootPictogramElement = context.getPictogramElement();
+ }
+
+ // Check id for PE
+ PictogramElement pictogramElement = context.getPictogramElement();
+ String id = getId(pictogramElement);
+ if (id != null) {
+ IdUpdateContext updateContext = new IdUpdateContext(pictogramElement,
+ pictogramElement.getGraphicsAlgorithm(), rootPictogramElement,
+ getBusinessObjectForPictogramElement(pictogramElement));
+ IReason reason = updateNeeded(updateContext, id);
+ if (reason.toBoolean()) {
+ return reason;
+ }
+ }
+
+ // Check id for GA
+ GraphicsAlgorithm graphicsAlgorithm = pictogramElement.getGraphicsAlgorithm();
+ id = getId(graphicsAlgorithm);
+ if (id != null) {
+ PictogramElement element = graphicsAlgorithm.getPictogramElement();
+ IdUpdateContext updateContext = new IdUpdateContext(element, graphicsAlgorithm, rootPictogramElement,
+ getBusinessObjectForPictogramElement(element));
+ IReason reason = updateNeeded(updateContext, id);
+ if (reason.toBoolean()) {
+ return reason;
+ }
+ }
+
+ // Check children of PE
+ if (pictogramElement instanceof ContainerShape) {
+ EList<Shape> children = ((ContainerShape) pictogramElement).getChildren();
+ for (Shape shape : children) {
+ IdUpdateContext updateContext = new IdUpdateContext(shape, shape.getGraphicsAlgorithm(),
+ rootPictogramElement, getBusinessObjectForPictogramElement(shape));
+ IReason reason = updateNeeded(updateContext);
+ if (reason.toBoolean()) {
+ return reason;
+ }
+ }
+ }
+
+ // Check children of GA
+ IdUpdateContext updateContext;
+ if (context instanceof IdUpdateContext) {
+ updateContext = (IdUpdateContext) context;
+ } else {
+ updateContext = new IdUpdateContext(null, graphicsAlgorithm, rootPictogramElement, null);
+ }
+ IReason reason = checkUpdateNeededChildren(graphicsAlgorithm, updateContext);
+ if (reason.toBoolean()) {
+ return reason;
+ }
+
+ return Reason.createFalseReason();
+ }
+
+ protected IReason checkUpdateNeededChildren(GraphicsAlgorithm graphicsAlgorithm, IdUpdateContext context) {
+ EList<GraphicsAlgorithm> graphicsAlgorithmChildren = graphicsAlgorithm.getGraphicsAlgorithmChildren();
+ for (GraphicsAlgorithm graphicsAlgorithmChild : graphicsAlgorithmChildren) {
+ String id = getId(graphicsAlgorithmChild);
+ if (id != null) {
+ PictogramElement pictogramElement = graphicsAlgorithmChild.getPictogramElement();
+ IdUpdateContext updateContext = new IdUpdateContext(pictogramElement, graphicsAlgorithmChild,
+ context.getRootPictogramElement(), getBusinessObjectForPictogramElement(pictogramElement));
+ IReason reason = updateNeeded(updateContext, id);
+ if (reason.toBoolean()) {
+ return reason;
+ }
+ }
+ IReason reason = checkUpdateNeededChildren(graphicsAlgorithmChild, context);
+ if (reason.toBoolean()) {
+ return reason;
+ }
+ }
+ return Reason.createFalseReason();
+ }
+
+ abstract protected IReason updateNeeded(IdUpdateContext context, String id);
+
+ @Override
+ public boolean update(IUpdateContext context) {
+ boolean result = false;
+
+ PictogramElement rootPictogramElement;
+ if (context instanceof IdUpdateContext) {
+ rootPictogramElement = ((IdUpdateContext) context).getRootPictogramElement();
+ } else {
+ rootPictogramElement = context.getPictogramElement();
+ }
+
+ // Check id for PE
+ PictogramElement pictogramElement = context.getPictogramElement();
+ String id = getId(pictogramElement);
+ if (id != null) {
+ IdUpdateContext updateContext = new IdUpdateContext(pictogramElement,
+ pictogramElement.getGraphicsAlgorithm(), rootPictogramElement,
+ getBusinessObjectForPictogramElement(pictogramElement));
+ if (update(updateContext, id)) {
+ result = true;
+ }
+ }
+
+ // Check id for GA
+ GraphicsAlgorithm graphicsAlgorithm = pictogramElement.getGraphicsAlgorithm();
+ id = getId(graphicsAlgorithm);
+ if (id != null) {
+ PictogramElement element = graphicsAlgorithm.getPictogramElement();
+ IdUpdateContext updateContext = new IdUpdateContext(element, graphicsAlgorithm, rootPictogramElement,
+ getBusinessObjectForPictogramElement(element));
+ if (update(updateContext, id)) {
+ result = true;
+ }
+ }
+
+ // Check children of PE
+ if (pictogramElement instanceof ContainerShape) {
+ EList<Shape> children = ((ContainerShape) pictogramElement).getChildren();
+ for (Shape shape : children) {
+ IdUpdateContext updateContext = new IdUpdateContext(shape, shape.getGraphicsAlgorithm(),
+ rootPictogramElement, getBusinessObjectForPictogramElement(shape));
+ if (update(updateContext)) {
+ result = true;
+ }
+ }
+ }
+
+ // Check children of GA
+ IdUpdateContext updateContext;
+ if (context instanceof IdUpdateContext) {
+ updateContext = (IdUpdateContext) context;
+ } else {
+ updateContext = new IdUpdateContext(null, graphicsAlgorithm, rootPictogramElement, null);
+ }
+ if (checkUpdateChildren(graphicsAlgorithm, updateContext)) {
+ result = true;
+ }
+
+ return result;
+ }
+
+ protected boolean checkUpdateChildren(GraphicsAlgorithm graphicsAlgorithm, IdUpdateContext context) {
+ boolean result = false;
+ EList<GraphicsAlgorithm> graphicsAlgorithmChildren = graphicsAlgorithm.getGraphicsAlgorithmChildren();
+ for (GraphicsAlgorithm graphicsAlgorithmChild : graphicsAlgorithmChildren) {
+ String id = getId(graphicsAlgorithmChild);
+ if (id != null) {
+ PictogramElement pictogramElement = graphicsAlgorithmChild.getPictogramElement();
+ IdUpdateContext updateContext = new IdUpdateContext(pictogramElement, graphicsAlgorithmChild,
+ context.getRootPictogramElement(), getBusinessObjectForPictogramElement(pictogramElement));
+ if (update(updateContext, id)) {
+ result = true;
+ }
+ }
+ if (checkUpdateChildren(graphicsAlgorithmChild, context)) {
+ result = true;
+ }
+ }
+ return result;
+ }
+
+ abstract protected boolean update(IdUpdateContext context, String id);
+
+ /*
+ * Direct editing functionality
+ */
+
+ @Override
+ public int getEditingType() {
+ // TODO how to use different editing types for different parts of the
+ // pattern? No context to identify id...
+ return TYPE_TEXT;
+ }
+
+ @Override
+ public boolean canDirectEdit(IDirectEditingContext context) {
+ PictogramElement pictogramElement = context.getPictogramElement();
+ Object domainObject = getBusinessObjectForPictogramElement(pictogramElement);
+ boolean patternResponsible = PROPERTY_VALUE_PATTERN_TYPE_ID.equals(getPatternType(pictogramElement))
+ && isMainBusinessObjectApplicable(domainObject);
+
+ if (patternResponsible) {
+ String id = getId(pictogramElement);
+ if (id == null) {
+ id = getId(context.getGraphicsAlgorithm());
+
+ if (id != null) {
+ return canDirectEdit(context, id);
+ }
+ }
+ }
+ return false;
+ }
+
+ protected boolean canDirectEdit(IDirectEditingContext context, String id) {
+ return false;
+ }
+
+ @Override
+ public String getInitialValue(IDirectEditingContext context) {
+ PictogramElement pictogramElement = context.getPictogramElement();
+ Object domainObject = getBusinessObjectForPictogramElement(pictogramElement);
+ boolean patternResponsible = PROPERTY_VALUE_PATTERN_TYPE_ID.equals(getPatternType(pictogramElement))
+ && isMainBusinessObjectApplicable(domainObject);
+
+ if (patternResponsible) {
+ String id = getId(pictogramElement);
+ if (id == null) {
+ id = getId(context.getGraphicsAlgorithm());
+
+ if (id != null) {
+ return getInitialValue(context, id);
+ }
+ }
+ }
+ return null;
+ }
+
+ protected String getInitialValue(IDirectEditingContext context, String id) {
+ return null;
+ }
+
+ @Override
+ public String checkValueValid(String value, IDirectEditingContext context) {
+ PictogramElement pictogramElement = context.getPictogramElement();
+ Object domainObject = getBusinessObjectForPictogramElement(pictogramElement);
+ boolean patternResponsible = PROPERTY_VALUE_PATTERN_TYPE_ID.equals(getPatternType(pictogramElement))
+ && isMainBusinessObjectApplicable(domainObject);
+
+ if (patternResponsible) {
+ String id = getId(pictogramElement);
+ if (id == null) {
+ id = getId(context.getGraphicsAlgorithm());
+
+ if (id != null) {
+ return checkValueValid(value, context, id);
+ }
+ }
+ }
+ return null;
+ }
+
+ protected String checkValueValid(String value, IDirectEditingContext context, String id) {
+ return null;
+ }
+
+ @Override
+ public void setValue(String value, IDirectEditingContext context) {
+ PictogramElement pictogramElement = context.getPictogramElement();
+ Object domainObject = getBusinessObjectForPictogramElement(pictogramElement);
+ boolean patternResponsible = PROPERTY_VALUE_PATTERN_TYPE_ID.equals(getPatternType(pictogramElement))
+ && isMainBusinessObjectApplicable(domainObject);
+
+ if (patternResponsible) {
+ String id = getId(pictogramElement);
+ if (id == null) {
+ id = getId(context.getGraphicsAlgorithm());
+
+ if (id != null) {
+ setValue(value, context, id);
+ }
+ }
+ }
+ }
+
+ protected void setValue(String value, IDirectEditingContext context, String id) {
+ }
+}
diff --git a/plugins/org.eclipse.graphiti.pattern/src/org/eclipse/graphiti/pattern/id/IdUpdateContext.java b/plugins/org.eclipse.graphiti.pattern/src/org/eclipse/graphiti/pattern/id/IdUpdateContext.java
new file mode 100644
index 0000000..b9e8510
--- /dev/null
+++ b/plugins/org.eclipse.graphiti.pattern/src/org/eclipse/graphiti/pattern/id/IdUpdateContext.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * <copyright>
+ *
+ * Copyright (c) 2012, 2012 SAP AG.
+ * 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 AG - initial API, implementation and documentation
+ *
+ * </copyright>
+ *
+ *******************************************************************************/
+package org.eclipse.graphiti.pattern.id;
+
+import org.eclipse.graphiti.features.context.impl.UpdateContext;
+import org.eclipse.graphiti.mm.algorithms.GraphicsAlgorithm;
+import org.eclipse.graphiti.mm.pictograms.PictogramElement;
+
+/**
+ * @since 0.10
+ * @experimental This API is in an experimental state and should be used by
+ * clients, as it not final and can be removed or changed without
+ * prior notice!
+ */
+public class IdUpdateContext extends UpdateContext {
+
+ private GraphicsAlgorithm graphicsAlgorithm;
+ private PictogramElement rootPictogramElement;
+ private Object domainObject;
+
+ public IdUpdateContext(PictogramElement pictogramElement, GraphicsAlgorithm graphicsAlgorithm,
+ PictogramElement rootPictogramElement, Object domainObject) {
+ super(pictogramElement);
+ this.graphicsAlgorithm = graphicsAlgorithm;
+ this.rootPictogramElement = rootPictogramElement;
+ this.setDomainObject(domainObject);
+ }
+
+ public GraphicsAlgorithm getGraphicsAlgorithm() {
+ return graphicsAlgorithm;
+ }
+
+ public void setGraphicsAlgorithm(GraphicsAlgorithm graphicsAlgorithm) {
+ this.graphicsAlgorithm = graphicsAlgorithm;
+ }
+
+ public PictogramElement getRootPictogramElement() {
+ return rootPictogramElement;
+ }
+
+ public void setRootPictogramElement(PictogramElement rootPictogramElement) {
+ this.rootPictogramElement = rootPictogramElement;
+ }
+
+ public Object getDomainObject() {
+ return domainObject;
+ }
+
+ public void setDomainObject(Object domainObject) {
+ this.domainObject = domainObject;
+ }
+}