Browse Source

Substatecharts are saved by statechartId and substatechart is linked on load

benjamin.schwertfeger@gmail.com 13 years ago
parent
commit
cb272f942e

+ 1 - 0
plugins/org.yakindu.sct.model.sgraph.edit/plugin.properties

@@ -46,6 +46,7 @@ _UI_Transition_region_feature = Region
 _UI_Transition_target_feature = Target
 _UI_ScopedElement_namespace_feature = Namespace
 _UI_State_region_feature = Region
+_UI_State_substatechartId_feature = Substatechart
 _UI_Unknown_feature = Unspecified
 
 _UI_Choice_type = Choice

+ 2 - 1
plugins/org.yakindu.sct.model.sgraph/META-INF/MANIFEST.MF

@@ -17,5 +17,6 @@ Require-Bundle: org.eclipse.core.runtime,
  org.eclipse.emf.ecore.xmi,
  org.eclipse.xtext,
  de.itemis.xtext.utils.gmf,
- org.eclipse.gmf.runtime.emf.core
+ org.eclipse.gmf.runtime.emf.core,
+ org.apache.commons.lang
 Bundle-ActivationPolicy: lazy

+ 6 - 3
plugins/org.yakindu.sct.model.sgraph/src/org/yakindu/sct/model/sgraph/naming/SGraphNameProvider.java

@@ -24,6 +24,12 @@ import org.yakindu.sct.model.sgraph.Statechart;
 
 import com.google.inject.Inject;
 
+/**
+ * NameProvider for SGraph elements like statecharts, scopes and declarations.
+ * 
+ * @author benjamin schwertfeger
+ * 
+ */
 public class SGraphNameProvider extends DefaultDeclarativeQualifiedNameProvider {
 	@Inject
 	IQualifiedNameConverter nameConverter;
@@ -46,9 +52,6 @@ public class SGraphNameProvider extends DefaultDeclarativeQualifiedNameProvider
 		String nameString = SimpleAttributeResolver.NAME_RESOLVER.apply(ele);
 		if (!Strings.isEmpty(nameString)) {
 			name = nameConverter.toQualifiedName(nameString);
-		} else if (nameString == null) {
-			// Default interface
-			name = nameConverter.toQualifiedName("");
 		}
 
 		QualifiedName namespace = getNamespace(ele);

+ 143 - 6
plugins/org.yakindu.sct.model.sgraph/src/org/yakindu/sct/model/sgraph/resource/SGraphInjectMembersResource.java

@@ -1,14 +1,33 @@
+/**
+ * Copyright (c) 2011 committers of YAKINDU and others.
+ * 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:
+ *     committers of YAKINDU - initial API and implementation
+ */
 package org.yakindu.sct.model.sgraph.resource;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 
+import org.apache.commons.lang.StringUtils;
+import org.eclipse.emf.common.notify.Adapter;
+import org.eclipse.emf.common.notify.Notification;
+import org.eclipse.emf.common.notify.impl.AdapterImpl;
+import org.eclipse.emf.common.util.BasicDiagnostic;
 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.EStructuralFeature;
 import org.eclipse.emf.ecore.util.EcoreUtil;
 import org.eclipse.xtext.naming.IQualifiedNameConverter;
+import org.eclipse.xtext.naming.IQualifiedNameProvider;
 import org.eclipse.xtext.resource.IEObjectDescription;
 import org.eclipse.xtext.scoping.IGlobalScopeProvider;
 import org.eclipse.xtext.scoping.IScope;
@@ -21,6 +40,13 @@ import com.google.inject.Inject;
 
 import de.itemis.xtext.utils.gmf.resource.InjectMembersResource;
 
+/**
+ * Implementation of InjectMembersResource that handles substatecharts set in
+ * states by qualifiedName
+ * 
+ * @author benjamin schwertfeger
+ * 
+ */
 public class SGraphInjectMembersResource extends InjectMembersResource {
 
 	@Inject
@@ -29,6 +55,9 @@ public class SGraphInjectMembersResource extends InjectMembersResource {
 	@Inject
 	IQualifiedNameConverter nameConverter;
 
+	@Inject
+	IQualifiedNameProvider nameProvider;
+
 	public SGraphInjectMembersResource(URI uri) {
 		super(uri);
 	}
@@ -40,22 +69,67 @@ public class SGraphInjectMembersResource extends InjectMembersResource {
 		linkSubStatecharts();
 	}
 
+	private void linkSubStatecharts(State currentState) {
+		removeDiagnostics(currentState);
+		Statechart substatechart = getStatechart(currentState,
+				currentState.getSubstatechartId());
+		currentState.setSubstatechart(substatechart);
+		registerRelinkAdapter(currentState);
+	}
+
+	private void removeDiagnostics(State currentState) {
+		List<org.eclipse.emf.common.util.Diagnostic> diagnostics = getDiagnostics();
+		Iterator<org.eclipse.emf.common.util.Diagnostic> iter = diagnostics
+				.iterator();
+		while (iter.hasNext()) {
+			org.eclipse.emf.common.util.Diagnostic d = iter.next();
+			if (d instanceof BrokenLinkDiagnostic && !d.getData().isEmpty()
+					&& d.getData().get(0) == currentState) {
+				iter.remove();
+			}
+		}
+
+	}
+
+	/**
+	 * Adds a relinkAdapter that observes the source feature and links the model
+	 * element in case of changes again.
+	 * 
+	 * @param object
+	 */
+	private void registerRelinkAdapter(State object) {
+		Adapter existingAdapter = EcoreUtil.getExistingAdapter(object,
+				RelinkAdapter.class);
+		if (existingAdapter == null) {
+			object.eAdapters().add(
+					new RelinkAdapter(object,
+							SGraphPackage.Literals.STATE__SUBSTATECHART_ID));
+		}
+	}
+
 	private void linkSubStatecharts() {
 		TreeIterator<EObject> iter = getAllContents();
 		while (iter.hasNext()) {
 			EObject currentObject = iter.next();
 			if (currentObject instanceof State) {
 				State state = (State) currentObject;
-				if (state.getSubstatechartId() != null) {
-					Statechart substatechart = getStatechart(state,
-							state.getSubstatechartId());
-					state.setSubstatechart(substatechart);
+				if (state.getSubstatechartId() == null
+						&& state.getSubstatechart() != null) {
+					// For compatibility added. If a substate is set, but not
+					// the ID, the ID is updated.
+					state.setSubstatechartId(nameProvider
+							.getFullyQualifiedName(state.getSubstatechart())
+							.toString());
 				}
+				linkSubStatecharts(state);
 			}
 		}
 	}
 
 	private Statechart getStatechart(EObject context, String substatechartId) {
+		if (StringUtils.isEmpty(substatechartId)) {
+			return null;
+		}
 		IScope scope = scopeProvider.getScope(context.eResource(),
 				SGraphPackage.Literals.STATE__SUBSTATECHART,
 				Predicates.<IEObjectDescription> alwaysTrue());
@@ -65,13 +139,76 @@ public class SGraphInjectMembersResource extends InjectMembersResource {
 		if (statechartDescription != null) {
 			Statechart statechart = null;
 			statechart = (Statechart) statechartDescription.getEObjectOrProxy();
-			if (statechart != null && statechart.eIsProxy()) {
+			if (statechart.eIsProxy()) {
 				statechart = (Statechart) EcoreUtil
 						.resolve(statechart, context);
 			}
 			return statechart;
-
+		} else {
+			getDiagnostics()
+					.add(new BrokenLinkDiagnostic(
+							org.eclipse.emf.common.util.Diagnostic.ERROR,
+							"source", 0, "Sub statechart '" + substatechartId
+									+ "' not linked", new Object[] { context }));
 		}
 		return null;
 	}
+
+	@Override
+	public void attached(EObject eObject) {
+		super.attached(eObject);
+		if (isLoading() || isParsing())
+			return;
+		if (eObject instanceof State) {
+			linkSubStatecharts((State) eObject);
+		}
+	}
+
+	@Override
+	public void detached(EObject eObject) {
+		super.detached(eObject);
+		Adapter existingAdapter = EcoreUtil.getExistingAdapter(eObject,
+				RelinkAdapter.class);
+		if (existingAdapter != null) {
+			eObject.eAdapters().remove(existingAdapter);
+		}
+	}
+
+	private final class BrokenLinkDiagnostic extends BasicDiagnostic {
+		public BrokenLinkDiagnostic(int severity, String source, int code,
+				String message, Object[] data) {
+			super(severity, source, code, message, data);
+		}
+	}
+
+	/**
+	 * ReparseAdapter listens for feature changes and reparses the whole model.
+	 * 
+	 * @author benjamin schwertfeger
+	 * 
+	 */
+	private final class RelinkAdapter extends AdapterImpl {
+		public final EStructuralFeature expressionFeature;
+
+		private RelinkAdapter(State currentObject,
+				EStructuralFeature expressionFeature) {
+			this.expressionFeature = expressionFeature;
+		}
+
+		@Override
+		public void notifyChanged(Notification msg) {
+			if (msg.getFeature() == expressionFeature) {
+				if (!(msg.getNotifier() instanceof State)) {
+					throw new IllegalStateException(
+							"Changed StatechartID should only rise for states");
+				}
+				linkSubStatecharts((State) msg.getNotifier());
+			}
+		}
+
+		@Override
+		public boolean isAdapterForType(Object type) {
+			return RelinkAdapter.class == type;
+		}
+	}
 }

+ 0 - 3
plugins/org.yakindu.sct.model.stext/src/org/yakindu/sct/model/stext/naming/StextNameProvider.java

@@ -18,9 +18,6 @@ public class StextNameProvider extends SGraphNameProvider {
 		QualifiedName name = null;
 		if (!Strings.isEmpty(ele.getName())) {
 			name = nameConverter.toQualifiedName(ele.getName());
-		} else if (ele.getName() == null) {
-			// Default interface
-			name = nameConverter.toQualifiedName("");
 		}
 
 		QualifiedName namespace = getNamespace(ele);

+ 6 - 11
plugins/org.yakindu.sct.ui.editor/src/org/yakindu/sct/ui/editor/dialogs/SelectSubmachineDialog.java

@@ -15,7 +15,6 @@ import java.util.List;
 
 import org.eclipse.emf.ecore.EObject;
 import org.eclipse.emf.ecore.resource.Resource;
-import org.eclipse.emf.ecore.util.EcoreUtil;
 import org.eclipse.jface.dialogs.IDialogConstants;
 import org.eclipse.jface.dialogs.IDialogSettings;
 import org.eclipse.jface.viewers.ILabelProvider;
@@ -34,6 +33,7 @@ import org.eclipse.ui.PlatformUI;
 import org.eclipse.ui.dialogs.ElementListSelectionDialog;
 import org.eclipse.ui.internal.dialogs.NewWizard;
 import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
+import org.eclipse.xtext.naming.QualifiedName;
 import org.eclipse.xtext.resource.IEObjectDescription;
 import org.eclipse.xtext.scoping.IGlobalScopeProvider;
 import org.eclipse.xtext.scoping.IScope;
@@ -140,7 +140,7 @@ public class SelectSubmachineDialog extends ElementListSelectionDialog {
 	}
 
 	private IStructuredSelection getSelection() {
-		Statechart selectedSubmachine = getSelectedSubmachine();
+		QualifiedName selectedSubmachine = getSelectedSubmachine();
 		if (selectedSubmachine != null) {
 			return new StructuredSelection(selectedSubmachine);
 		} else {
@@ -149,18 +149,13 @@ public class SelectSubmachineDialog extends ElementListSelectionDialog {
 
 	}
 
-	public Statechart getSelectedSubmachine() {
+	public QualifiedName getSelectedSubmachine() {
 		Object[] result = getResult();
 		if (result != null && result.length == 1) {
-			Statechart statechart = null;
+			QualifiedName statechart = null;
 			if (result[0] instanceof IEObjectDescription) {
-				statechart = (Statechart) ((IEObjectDescription) result[0])
-						.getEObjectOrProxy();
-			}
-			if (statechart != null && statechart.eIsProxy()) {
-				statechart = (Statechart) EcoreUtil
-						.resolve(statechart, context);
-				;
+				statechart = ((IEObjectDescription) result[0])
+						.getQualifiedName();
 			}
 			return statechart;
 		}

+ 4 - 4
plugins/org.yakindu.sct.ui.editor/src/org/yakindu/sct/ui/editor/edithelper/StateEditHelper.java

@@ -16,11 +16,11 @@ import org.eclipse.gmf.runtime.emf.type.core.requests.ConfigureRequest;
 import org.eclipse.gmf.runtime.emf.type.core.requests.SetRequest;
 import org.eclipse.jface.dialogs.Dialog;
 import org.eclipse.swt.widgets.Shell;
+import org.eclipse.xtext.naming.QualifiedName;
 import org.yakindu.sct.model.sgraph.Region;
 import org.yakindu.sct.model.sgraph.SGraphFactory;
 import org.yakindu.sct.model.sgraph.SGraphPackage;
 import org.yakindu.sct.model.sgraph.State;
-import org.yakindu.sct.model.sgraph.Statechart;
 import org.yakindu.sct.ui.editor.dialogs.SelectSubmachineDialog;
 import org.yakindu.sct.ui.editor.editor.StatechartElementTypes;
 
@@ -55,12 +55,12 @@ public class StateEditHelper extends VertexEditHelper {
 				req.getElementToConfigure().eResource());
 		dialog.setElements(new Object[] { req.getElementToConfigure() });
 		if (Dialog.OK == dialog.open()) {
-			Statechart selectedSubmachine = dialog.getSelectedSubmachine();
+			QualifiedName selectedSubmachine = dialog.getSelectedSubmachine();
 			if (selectedSubmachine != null) {
 				return new SetValueCommand(new SetRequest(
 						req.getElementToConfigure(),
-						SGraphPackage.Literals.STATE__SUBSTATECHART,
-						selectedSubmachine));
+						SGraphPackage.Literals.STATE__SUBSTATECHART_ID,
+						selectedSubmachine.toString()));
 			}
 		}
 		return null;

+ 12 - 37
plugins/org.yakindu.sct.ui.editor/src/org/yakindu/sct/ui/editor/propertysheets/SubmachineSelectionDialogPropertyDescriptor.java

@@ -18,9 +18,6 @@ import org.eclipse.draw2d.ColorConstants;
 import org.eclipse.emf.common.notify.Notification;
 import org.eclipse.emf.common.notify.impl.AdapterImpl;
 import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
-import org.eclipse.emf.transaction.util.TransactionUtil;
-import org.eclipse.gmf.runtime.emf.commands.core.command.CompositeTransactionalCommand;
 import org.eclipse.gmf.runtime.emf.type.core.commands.SetValueCommand;
 import org.eclipse.gmf.runtime.emf.type.core.requests.SetRequest;
 import org.eclipse.jface.dialogs.Dialog;
@@ -33,12 +30,9 @@ import org.eclipse.swt.widgets.Event;
 import org.eclipse.swt.widgets.Label;
 import org.eclipse.swt.widgets.Listener;
 import org.eclipse.ui.forms.widgets.FormToolkit;
-import org.eclipse.xtext.naming.IQualifiedNameProvider;
+import org.eclipse.xtext.naming.QualifiedName;
 import org.yakindu.sct.model.sgraph.SGraphPackage;
 import org.yakindu.sct.model.sgraph.State;
-import org.yakindu.sct.model.sgraph.Statechart;
-import org.yakindu.sct.model.sgraph.provider.SGraphItemProviderAdapterFactory;
-import org.yakindu.sct.model.sgraph.ui.Activator;
 import org.yakindu.sct.ui.editor.dialogs.SelectSubmachineDialog;
 
 import de.itemis.gmf.runtime.commons.properties.descriptors.IFormPropertyDescriptor;
@@ -54,7 +48,7 @@ public class SubmachineSelectionDialogPropertyDescriptor implements
 	private final class UpdateLabelAdapter extends AdapterImpl {
 		@Override
 		public void notifyChanged(Notification msg) {
-			if (msg.getFeature() == SGraphPackage.Literals.STATE__SUBSTATECHART) {
+			if (msg.getFeature() == SGraphPackage.Literals.STATE__SUBSTATECHART_ID) {
 				updateLabel(state);
 			}
 		}
@@ -76,11 +70,9 @@ public class SubmachineSelectionDialogPropertyDescriptor implements
 	}
 
 	private void updateLabel(State state) {
-		Statechart substatechart = state.getSubstatechart();
-		if (substatechart != null) {
-			AdapterFactoryLabelProvider provider = new AdapterFactoryLabelProvider(
-					new SGraphItemProviderAdapterFactory());
-			label.setText(provider.getText(substatechart));
+		String substatechartId = state.getSubstatechartId();
+		if (substatechartId != null) {
+			label.setText(substatechartId);
 		} else {
 			label.setText("");
 		}
@@ -115,30 +107,18 @@ public class SubmachineSelectionDialogPropertyDescriptor implements
 						parent.getShell(), state.eResource());
 				dialog.setElements(new Object[] { context });
 				if (Dialog.OK == dialog.open()) {
-					Statechart selectedSubmachine = dialog
+					QualifiedName selectedSubmachine = dialog
 							.getSelectedSubmachine();
 					if (selectedSubmachine != null || dialog.isClearSelected()) {
-						CompositeTransactionalCommand transactionalCommand = new CompositeTransactionalCommand(
-								TransactionUtil.getEditingDomain(state), "");
-						// TODO set only one, the model should keep both in sync
-						transactionalCommand
-								.add(new SetValueCommand(
-										new SetRequest(
-												state,
-												SGraphPackage.Literals.STATE__SUBSTATECHART,
-												selectedSubmachine)));
-						transactionalCommand
-								.add(new SetValueCommand(
-										new SetRequest(
-												state,
-												SGraphPackage.Literals.STATE__SUBSTATECHART_ID,
-												getNameProvider()
-														.getFullyQualifiedName(
-																selectedSubmachine))));
+						SetValueCommand command = new SetValueCommand(
+								new SetRequest(
+										state,
+										SGraphPackage.Literals.STATE__SUBSTATECHART_ID,
+										selectedSubmachine.toString()));
 
 						try {
 							OperationHistoryFactory.getOperationHistory()
-									.execute(transactionalCommand,
+									.execute(command,
 											new NullProgressMonitor(), null);
 						} catch (ExecutionException e) {
 							e.printStackTrace();
@@ -149,11 +129,6 @@ public class SubmachineSelectionDialogPropertyDescriptor implements
 		});
 	}
 
-	private IQualifiedNameProvider getNameProvider() {
-		return Activator.getDefault().getInjector()
-				.getInstance(IQualifiedNameProvider.class);
-	}
-
 	public void createHelpColumn(Composite parent) {
 		// No help provided
 	}