août
2009
A l’étape du billet précédant [step11] nous avons représenté graphiquement les instances EMF Connection par des flêches draw2d. Mais la synchronisation des couches Model/View n’est pas encore tout à fait terminée. En effet si par exemple vous supprimez dans la page Source ou dans un autre éditeur XML, un element XML state qui est lié par une action (via l’attribut fromState ou toState) vous pourrez constater que la vue graphique n’est pas reflétée (le state disparaît de la page graphiques mais la connection reste affichée) :
En effet à cette étape nous n’avons pas gérer le cas où les connection EMF sont supprimées/ajoutées d’un StateType/ActionType (ConnectableNode). Dans ce billet nous allons expliquer comment détecter l’ajout/suppression des Connections EMF et les refléter à l’éditeur GEF Graphics.
Vous pouvez télécharger le projet org.example.workflow_step12.zip présenté dans ce billet.
ConnectableNode – Adapter
La détection d’un ajout/suppression d’une connection doit s’effectuer via un Adpater EMF comme ce que nous avons fait par exemple pour détecter la modification du nom d’un state. Autrement dit l’EditPart ConnectableNodePart doit surveiller les ajout/suppression d’une connection et rafraichîr ainsi les connections draw2d.
Pour cela ajouter le code suivant dans la classe org.example.workflow.presentation.graphical.parts.ConnectableNode :
int type = notification.getEventType();
int featureId = notification.getFeatureID(WorkflowPackage.class);
switch (type) {
case Notification.ADD:
case Notification.REMOVE:
switch (featureId) {
case WorkflowPackage.CONNECTABLE_NODE__SOURCE_CONNECTIONS:
refreshSourceConnections();
break;
case WorkflowPackage.CONNECTABLE_NODE__TARGET_CONNECTIONS:
refreshTargetConnections();
break;
}
}
}
Ce code permet de détecter les ajouts/suppression d’une Connection EMF (avec featureID Notification.ADD (ajout d’une Connection), et Notification.REMOVE (suppression d’une Connection)) et :
- rafraîchit les connections sources draw2d en appelant la méthode AbstractGraphicalEditPart#refreshSourceConnections() lorsque une Connection EMF est ajoutée/supprimée dans la liste des connections sources ConnectableNode#getSourceConnections().
- rafraîchit les connections cibles (target) draw2d en appelant la méthode AbstractGraphicalEditPart#refreshTargetConnections() lorsque une Connection EMF est ajoutée/supprimée dans la liste des connections cible (target) ConnectableNode#getTargetConnections().
Voici le code en entier de la classe org.example.workflow.presentation.graphical.parts.ConnectableNode :
import java.util.List;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.gef.NodeEditPart;
import org.example.workflow.model.ConnectableNode;
import org.example.workflow.model.Connection;
import org.example.workflow.model.WorkflowPackage;
public abstract class ConnectableNodePart extends
AbstractEMFModelGraphicalEditPart implements NodeEditPart {
@Override
protected List<Connection> getModelSourceConnections() {
return getConnectableNode().getSourceConnections();
}
@Override
protected List<Connection> getModelTargetConnections() {
return getConnectableNode().getTargetConnections();
}
public ConnectableNode getConnectableNode() {
return (ConnectableNode) super.getModel();
}
public void notifyChanged(Notification notification) {
int type = notification.getEventType();
int featureId = notification.getFeatureID(WorkflowPackage.class);
switch (type) {
case Notification.ADD:
case Notification.REMOVE:
switch (featureId) {
case WorkflowPackage.CONNECTABLE_NODE__SOURCE_CONNECTIONS:
refreshSourceConnections();
break;
case WorkflowPackage.CONNECTABLE_NODE__TARGET_CONNECTIONS:
refreshTargetConnections();
break;
}
}
}
}
Modification StateTypePart – Adapter
Il faut modifier la classe StateTypePart pour quelle puisse appeler la méthode ConnectableNode#notifyChanged(Notification notification) que nous venons d’implémenter. Pour cela modifiez la méthode StateTypePart#notifyChanged(Notification notification) comme ceci :
int type = notification.getEventType();
int featureId = notification.getFeatureID(WorkflowPackage.class);
switch (type) {
case Notification.SET:
switch (featureId) {
case WorkflowPackage.STATE_TYPE__NAME:
refreshVisuals();
break;
}
default:
super.notifyChanged(notification);
}
}
Modification ActionTypePart – Adapter
Modifiez la méthode ActionTypePart#notifyChanged(Notification notification) pour appeler la méthode ConnectableNode#notifyChanged(Notification notification) que nous venons d’implémenter :
int type = notification.getEventType();
int featureId = notification.getFeatureID(WorkflowPackage.class);
switch (type) {
case Notification.SET:
switch (featureId) {
case WorkflowPackage.ACTION_TYPE__NAME:
refreshVisuals();
break;
}
default:
super.notifyChanged(notification);
}
}
Relancez le plugin. Si vous supprimez un element state, la connection se supprimera aussi (par contre l’attribut fromState n’est pas mis à jour correctement) :
StateType – Adapter
A cette étape la partie GEF concernant les connections a été mise en place. La mise a jour des Connections EMF en fonction des propriétés fromState et toState a été mis en place via des Adapter EMF WorkflowTypeAdapter et ActionTypeAdapter qui surveille les modifications des instances EMF ActionType et WorkflowType. Cependant il reste encore quelques problèmes liés aux modification d’un StateType :
- la modification de la propriété name d’un state ne met pas à jour fromState/toState. Par exemple, si vous modifiez le nom du state « s1″ par « s3″, l’attribut « fromState » n’est pas modifié :
- Suppression un state ne met pas à jour fromState/toState. Par exemple, si vous supprimez le state « s1″ l’attribut « fromState » n’est pas mis à jour correctement :
- 2 states avec le même nom posent problème (voir scénario expliqué dans ce lien).
Dans cette partie nous allons travailler sur le projet org.example.workflow pour bien finaliser la mise à jour des connections EMF en fonction des modifications d’un StateType.
Initialisation Adpater StateType
Pour mettre à jour les connections en fonction des modifications de la propriété name d’un state, il faut pouvoir observer les modifications de cette propriétés. Pour cela nous allons crééer un Adapter EMF StatetypeAdapter comme ceux que nous avons fait dans le [billet 10] pour observer les modifications d’un ActionType (via l’Adapter EMF ActionTypeAdapter) et les modifications d’un WorkflowType (via l’Adapter EMF WorkflowTypeAdapter).
Créer la classe org.example.workflow.model.util.StateTypeAdapter qui permet d’observer les changements de la propriété name d’un StateType comme suit :
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.Notifier;
import org.example.workflow.model.StateType;
import org.example.workflow.model.WorkflowPackage;
public class StateTypeAdapter implements Adapter {
private Notifier target;
public boolean isAdapterForType(Object type) {
return type.getClass() == StateTypeAdapter.class;
}
public void notifyChanged(Notification notification) {
int type = notification.getEventType();
int featureId = notification.getFeatureID(WorkflowPackage.class);
switch (type) {
case Notification.SET:
switch (featureId) {
case WorkflowPackage.STATE_TYPE__NAME:
if (notification.getOldValue() != null
&& notification.getOldValue().equals(
notification.getNewValue()))
return;
// state name has changed.
StateType state = (StateType) notification.getNotifier();
}
}
}
public Notifier getTarget() {
return target;
}
public void setTarget(Notifier target) {
this.target = target;
}
}
Il faut ensuite enregistrer notre Adapter EMF StateTypeAdapter sur chacune des instances EMF StateType. Pour cela ajouter dans la classe org.example.workflow.model.util.WorkflowTypeAdapter la méthode WorkflowTypeAdapter#addStateAdpaterIfNeed(StateType state) comme suit :
if (EcoreUtil.getExistingAdapter(state, StateTypeAdapter.class) != null)
return;
state.eAdapters().add(new StateTypeAdapter());
}
Puis appeler cette méthode (comme ce que nous avons pu faire avec la méthode WorkflowTypeAdapter#addActionAdpaterIfNeed(StateType state) :
case WorkflowPackage.WORKFLOW_TYPE__STATE:
StateType state = (StateType) notification.getNewValue();
addStateAdpaterIfNeed(state);
break;
...
ID Resource
A cette étape nous pouvons observer les modifications de la propriété name des StateType EMF (qui ne fait rien pour l’instant). Nous allons profiter de cet Adapter EMF pour enregistrer l’instance StateType EMF dans la resource EMF en tant que ID en utilisant le nom name de StateType.
En effet à ce stade, pour retrouver les valeurs des attributs XML fromState et toState, nous avons créés un Translator org.example.workflow.model.util.HRefTranslator qui est capable de retrouver de retrouver l’instance EMF StateType par son nom en utilisant la resource EMF :
if (strValue == null)
return null;
Resource resource = owner.eResource();
if (resource == null)
return null;
return resource.getEObject(strValue);
}
Par exemple si nous avons le contenu XML suivant :
<workflow xmlns="http://www.example.org/workflow">
<state name="s1"/>
<state name="s2"/>
<action name="a2" fromState="s1" toState="s2"/>
</workflow>
Ce translator recherche le StateType enregistré avec l’ID s1 dans la resource EMF pour associer ce StateType à la propriéte EMF fromState de l’ActionType « a2″. Cette recherche par ID est possible car nous avons préalablement enregistré le StateType dans la ressource EMF en utilisant la propriété name en tant que ID via le Translator org.example.workflow.model.util.MyIdTranslator.
L’idée est de se passer de ce translator est d’effectuer l’enregistrement du StateType dans la resource EMF (par ID) via nos Adapter EMF. La mise à jour de par ID dans la resource EMF d’un StateType doit s’effectuer à plusieurs endroits :
- lorsque le StateType est ajouté au WorkflowType.
- lorsque le nom d’un StateType est modifié.
Avant de commencer ceci, nous allons créer une méthode utilitaire qui enregistre le StateType dans la resource EMF par ID.
Dans la classe org.example.workflow.model.util.ConnectionUtils, créez la méthode ConnectionUtils#setIDState(StateType state) comme suit :
public static void setIDState(StateType state) {
XMIResource res = (XMIResource) state.eResource();
String id = state.getName();
if (id != null && id.length() > 0 && res.getEObject(id) == null) {
res.setID(state, state.getName());
}
}
Ce code met à jour la resource EMF avec le StateType que si la propriété name est renseignée. On peut maintenant appeler cette méthode.
Resource ID – StateType ajouté au WorkflowType
Appelez la méthode ConnectionUtils#setIDState(StateType state) dans StateTypeAdapter comme ceci :
// state name has changed.
StateType state = (StateType) notification.getNotifier();
ConnectionUtils.setIDState(state);
Resource ID – nom StateType est modifié
Appelez la méthode ConnectionUtils#setIDState(StateType state) dans WorkflowTypeAdapter comme ceci :
case WorkflowPackage.WORKFLOW_TYPE__STATE:
StateType state = (StateType) notification.getNewValue();
ConnectionUtils.setIDState(state);
addStateAdpaterIfNeed(state);
break;
Remplacez dans la classe WorkflowTranslator, MyIdTranslator par Translator pour la propriété name de StateType :
translator.setChildren(new Translator[] { new Translator("name",
WorkflowPackage.eINSTANCE.getStateType_Name(),
Translator.DOM_ATTRIBUTE) });
Relancez le plugin pour vérifier que les connections soient bien mise à jour correctement.
Modification de la propriété name d’un state ne met pas à jour fromState/toState
Nous allons régler ici le problème de la modification d’un nom StateType qui ne modifie pas la propriété fromState et toState d’un Actiontype. Lorsque le nom d’un state change ou lorsqu’il est supprimé, les propriétés fromState et toState doivent se mettrent à jour. Nous allons mettre en commun le code qui gère ceci en créant dans la classe ConnectionUtils la méthode ConnectionUtils#updateState(StateType state, boolean clearConnections) :
public static void updateState(StateType state, boolean clearConnections) {
// Target
List<ActionType> actionSources = null;
EList<Connection> targetConnections = state
.getTargetConnections();
if (targetConnections.size() > 0) {
actionSources = new ArrayList<ActionType>();
for (Connection targetConnection : targetConnections) {
ActionType actionSource = (ActionType) targetConnection
.getSource();
actionSources.add(actionSource);
}
}
if (clearConnections)
ConnectionUtils.clearTargetConnections(state);
// Source
List<ActionType> actionTargets = null;
EList<Connection> sourceConnections = state
.getSourceConnections();
if (sourceConnections.size() > 0) {
actionTargets = new ArrayList<ActionType>();
for (Connection sourceConnection : sourceConnections) {
ActionType actionTarget = (ActionType) sourceConnection
.getTarget();
actionTargets.add(actionTarget);
}
}
if (clearConnections)
ConnectionUtils.clearSourceConnections(state);
// Update toState/fromState from action to null
if (actionSources != null) {
for (ActionType action : actionSources) {
if (clearConnections)
action.setToState(null);
else
action.setToState(state);
}
}
if (actionTargets != null) {
for (ActionType action : actionTargets) {
if (clearConnections)
action.setFromState(null);
else
action.setFromState(state);
}
}
}
Cette méthode attent un state et un boolean qui indique si les connections associées à ce state doivent être supprimées ou non. On peut appeler ensuite cette méthode dans la classe StateTypeAdapter comme suit :
import java.util.ArrayList;
import java.util.List;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.util.EList;
import org.example.workflow.model.ActionType;
import org.example.workflow.model.Connection;
import org.example.workflow.model.StateType;
import org.example.workflow.model.WorkflowPackage;
public class StateTypeAdapter implements Adapter {
private Notifier target;
public boolean isAdapterForType(Object type) {
return type.getClass() == StateTypeAdapter.class;
}
public void notifyChanged(Notification notification) {
int type = notification.getEventType();
int featureId = notification.getFeatureID(WorkflowPackage.class);
switch (type) {
case Notification.SET:
switch (featureId) {
case WorkflowPackage.STATE_TYPE__NAME:
if (notification.getOldValue() != null
&& notification.getOldValue().equals(
notification.getNewValue()))
return;
// state name has changed.
StateType state = (StateType) notification.getNotifier();
ConnectionUtils.setIDState(state);
String stateName = (String) notification.getNewValue();
boolean clearConnections = stateName == null
|| stateName.length() < 1;
ConnectionUtils.updateState(state, clearConnections);
}
}
}
public Notifier getTarget() {
return target;
}
public void setTarget(Notifier target) {
this.target = target;
}
}
Ce code permet de gérer les probléme suivants :
- lorsque le nom d’un state change qu’il devient vide, on supprime toutes les connections associées (le boolean clearConnections vaut true). Par exemple si vous remplacez « s1″ par « », l’attribut fromState disparaîtra.
- lorsque le nom d’un state change, les connections sont conservées mais les propriétés fromState/toState sont mises à jour avec le nouveau nom du state. Par exemple si vous remplacez « s1″ par « a », l’attribut fromState se modifiera avec la valeur « a ».
Suppression un state ne met pas à jour fromState/toState
Pour régler ce problème nous devons appeler la méthode ConnectionUtils#updateState(StateType state, boolean clearConnections) sur le state qui est supprimé du workflow. Ceci peut s’effectuer dans l’Adapter EMF WorkflowTypeAdapter qui est capable de détecter les suprresions des StateType. Modifier la méthode WorkflowTypeAdapter#notifyChanged(Notification notification) en ajoutant ce code :
case WorkflowPackage.WORKFLOW_TYPE__STATE:
StateType state = (StateType) notification.getOldValue();
ConnectionUtils.updateState(state, true);
break;
...
Voici le code en entier de WorkflowTypeAdapter :
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.example.workflow.model.ActionType;
import org.example.workflow.model.ConnectableNode;
import org.example.workflow.model.StateType;
import org.example.workflow.model.WorkflowPackage;
public class WorkflowTypeAdapter implements Adapter {
private Notifier target;
public boolean isAdapterForType(Object type) {
return type.getClass() == WorkflowTypeAdapter.class;
}
public void notifyChanged(Notification notification) {
int type = notification.getEventType();
int featureId = notification.getFeatureID(WorkflowPackage.class);
switch (type) {
case Notification.REMOVE:
switch (featureId) {
case WorkflowPackage.WORKFLOW_TYPE__STATE:
StateType state = (StateType) notification.getOldValue();
ConnectionUtils.updateState(state, true);
break;
case WorkflowPackage.WORKFLOW_TYPE__ACTION:
// Suppression state/action => suppression des
// connections
ConnectableNode node = (ConnectableNode) notification
.getOldValue();
if (node != null) {
// Target
ConnectionUtils.clearTargetConnections(node);
// Source
ConnectionUtils.clearSourceConnections(node);
}
break;
}
break;
case Notification.ADD:
switch (featureId) {
case WorkflowPackage.WORKFLOW_TYPE__ACTION:
ActionType action = (ActionType) notification.getNewValue();
addActionAdpaterIfNeed(action);
break;
case WorkflowPackage.WORKFLOW_TYPE__STATE:
StateType state = (StateType) notification.getNewValue();
ConnectionUtils.setIDState(state);
addStateAdpaterIfNeed(state);
break;
}
}
}
private void addActionAdpaterIfNeed(ActionType action) {
if (EcoreUtil.getExistingAdapter(action, ActionTypeAdapter.class) != null)
return;
action.eAdapters().add(new ActionTypeAdapter());
}
private void addStateAdpaterIfNeed(StateType state) {
if (EcoreUtil.getExistingAdapter(state, StateTypeAdapter.class) != null)
return;
state.eAdapters().add(new StateTypeAdapter());
}
public Notifier getTarget() {
return target;
}
public void setTarget(Notifier target) {
this.target = target;
}
}
2 states avec le même nom posent problèmes
Il existe encore un dernier problème a cette étape. Voici le scénario :
Créer 2 states avec le nom « a » :
<workflow xmlns="http://www.example.org/workflow">
<state name="s1"/>
<state name="s2"/>
<state name="a"/>
<state name="a"/>
<action name="a2" fromState="s1" toState="s2"/>
</workflow>
Le premier state est enregistre dans la Resource EMF par ID de valeur « a » (via L’adpater EMF StateTypeAdapter). Le 2ème StateType n’est pas enregistré puisqu’il existe déja un StateType par l’id « a ».
Modifier le premier state « a » par « b » :
<workflow xmlns="http://www.example.org/workflow">
<state name="s1"/>
<state name="s2"/>
<state name="b"/>
<state name="a"/>
<action name="a2" fromState="s1" toState="s2"/>
</workflow>
Ici le le state « b » (anciennement notre 1er state « a ») est enregistré dans la resource EMF. Le state « a » (anciennement notre 2ème state « a ») n’est toujours pas enregistré dans la resource EMF.
Lier fromState à « a » :
<workflow xmlns="http://www.example.org/workflow">
<state name="s1"/>
<state name="s2"/>
<state name="b"/>
<state name="a"/>
<action name="a2" fromState="a" toState="s2"/>
</workflow>
La connection entre l’action et le state « a » ne se met pas à jour, ce qui est normal car le StateType « a » ne peut pas être retrouvé par son ID dans la resource EMF.
Pour règler ce probblème, créez la classe org.example.workflow.model.util.ActionTranslator comme suit :
import java.util.List;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.xmi.XMIResource;
import org.example.workflow.model.ActionType;
import org.example.workflow.model.StateType;
import org.example.workflow.model.WorkflowType;
public class ActionTranslator extends HRefTranslator {
public ActionTranslator(String domNameAndPath, EStructuralFeature aFeature,
int style) {
super(domNameAndPath, aFeature, style);
}
public Object convertStringToValue(String strValue, EObject owner) {
Object o = super.convertStringToValue(strValue, owner);
if (o != null)
return o;
if (strValue == null)
return null;
XMIResource resource = (XMIResource) owner.eResource();
ActionType action = (ActionType) owner;
WorkflowType workflow = (WorkflowType) action.eContainer();
List<StateType> states = workflow.getState();
for (StateType state : states) {
if (strValue.equals(state.getName())) {
resource.setID(state, state.getName());
return state;
}
}
return null;
}
}
Cette classe hérite de org.example.workflow.model.util.HRefTranslator et étend la méthode HRefTranslator#convertStringToValue(String strValue, EObject owner). Elle recherche dans un premier temps le StateType par son ID, et si il n’est pas trouvé, elle itère sur chacun des StateType pour tenter de retrouver un StateType qui correspondrait. Dans le cas où le StateType est retrouvé la ressource EMF est mise à jour et le StateType est retourné.
Pour utiliser notre classe ActionTranslator, remplacez dans la classe WorkflowTranslator, HrefTranslator par ActionTranslator pour les propriétés fromState et toState : :
new ActionTranslator("fromState", WorkflowPackage.eINSTANCE.getActionType_FromState(), Translator.DOM_ATTRIBUTE),
new ActionTranslator("toState", WorkflowPackage.eINSTANCE.getActionType_ToState(), Translator.DOM_ATTRIBUTE), });
Voici la classe WorkflowTranslator en entière :
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.wst.common.internal.emf.resource.GenericTranslator;
import org.eclipse.wst.common.internal.emf.resource.RootTranslator;
import org.eclipse.wst.common.internal.emf.resource.Translator;
import org.example.workflow.model.WorkflowPackage;
public class WorkflowTranslator extends RootTranslator {
public static RootTranslator INSTANCE = new WorkflowTranslator();
public WorkflowTranslator() {
super("workflow", WorkflowPackage.eINSTANCE.getWorkflowType());
}
protected Translator[] getChildren() {
return new Translator[] { createStateTranslator(),
createActionTranslator() };
}
private Translator createStateTranslator() {
GenericTranslator translator = new GenericTranslator("state",
WorkflowPackage.eINSTANCE.getWorkflowType_State());
translator.setChildren(new Translator[] { new Translator("name",
WorkflowPackage.eINSTANCE.getStateType_Name(),
Translator.DOM_ATTRIBUTE) });
return translator;
}
private Translator createActionTranslator() {
GenericTranslator translator = new GenericTranslator("action",
WorkflowPackage.eINSTANCE.getWorkflowType_Action());
translator.setChildren(new Translator[] {
new Translator("name", WorkflowPackage.eINSTANCE
.getActionType_Name(), Translator.DOM_ATTRIBUTE),
new ActionTranslator("fromState", WorkflowPackage.eINSTANCE
.getActionType_FromState(), Translator.DOM_ATTRIBUTE),
new ActionTranslator("toState", WorkflowPackage.eINSTANCE
.getActionType_ToState(), Translator.DOM_ATTRIBUTE), });
return translator;
}
@Override
public EObject createEMFObject(String nodeName, String readAheadName) {
EObject eObject = super.createEMFObject(nodeName, readAheadName);
if (EcoreUtil.getExistingAdapter(eObject, WorkflowTypeAdapter.class) == null) {
eObject.eAdapters().add(new WorkflowTypeAdapter());
}
return eObject;
}
}
Conclusion
A cette étape nous avons fini de mettre en place les connections. Vous pouvez saisir le XML du workflow et le diagramme GEF du workflow devrait se mettre à jour correctement avec les connections. J’ai tenté au mieux de couvrir le maximum de scénario de tests, mais si vous trouvez des scénarios qui posent problème, n’hésitez pas à me faire un retour. Merci.
Dans le prochain billet nous mettrons en place le layout « automatique » qui permettra de positionner les figures aux mieux et non aléatoirement comme ce qui est fait aujourd’hui.
2 Commentaires + Ajouter un commentaire
Articles récents
- Conception d’un client Eclipse RCP et serveur OSGI avec Spring DM [step5]
- Conception d’un client Eclipse RCP et serveur OSGI avec Spring DM [step4]
- Conception d’un client Eclipse RCP et serveur OSGI avec Spring DM [step3]
- Conception d’un client Eclipse RCP et serveur OSGI avec Spring DM [step2]
- Conception d’un client Eclipse RCP et serveur OSGI avec Spring DM [step1]
Commentaires récents
- Conception d’un Editeur Eclipse de workflow XML [step 0] dans
- Conception d’un Editeur Eclipse de workflow XML [step 19] dans
- Conception d’un Editeur Eclipse de workflow XML [step 7] dans
- Conception d’un Editeur Eclipse de workflow XML [step 7] dans
- Conception d’un Editeur Eclipse de workflow XML [step 7] dans
Bonjour,
C’est difficile pour moi de t’aider, je n’ai jamais eu ce probleme. Il va falloir mettre les mains dans le code malheureusement. Bon courage!
Angelo
Salut Angelo,
tout d’abord, merci pour cette mine d’informations! Step 12/19, je commence à voir le bout du tunnel…
Ceci dit, j’aurais une question à te poser: je suis en train de développer un outil de modélisation tel que celui que tu proposes, mais sur base d’un xsd plus complexe et dont le design n’est peut-être pas optimal. Jusqu’ici, j’ai réussi à adapter tes explications en conservant l’architecture générale, mais je bute sur une exception lors de l’utilisation des méthodes (toutes!) de type « action.setToState(state) » dans les méthodes d’update. Voici la stack:
!MESSAGE assertion failed: <br />
!STACK 0 <br />
org.eclipse.core.runtime.AssertionFailedException: assertion failed: <br />
at org.eclipse.core.runtime.Assert.isTrue(Assert.java:110) <br />
at org.eclipse.core.runtime.Assert.isTrue(Assert.java:96) <br />
at org.eclipse.ui.internal.texteditor.quickdiff.DocumentLineDiffer.handleAboutToBeChanged(DocumentLineDiffer.java:794) <br />
at org.eclipse.ui.internal.texteditor.quickdiff.DocumentLineDiffer.documentAboutToBeChanged(DocumentLineDiffer.java:763) <br />
at org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument._fireDocumentAboutToChange(BasicStructuredDocument.java:389) <br />
at org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument.fireDocumentAboutToChanged(BasicStructuredDocument.java:1120) <br />
at org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument.internalReplaceText(BasicStructuredDocument.java:1912) <br />
at org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument.replaceText(BasicStructuredDocument.java:2419) <br />
at org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument.replaceText(BasicStructuredDocument.java:2415) <br />
at org.eclipse.wst.sse.core.internal.text.JobSafeStructuredDocument.access$3(JobSafeStructuredDocument.java:1) <br />
at org.eclipse.wst.sse.core.internal.text.JobSafeStructuredDocument$4.run(JobSafeStructuredDocument.java:163) <br />
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42) <br />
at org.eclipse.wst.sse.ui.EditorExecutionContext.execute(EditorExecutionContext.java:149) <br />
at org.eclipse.wst.sse.core.internal.text.JobSafeStructuredDocument.replaceText(JobSafeStructuredDocument.java:171) <br />
at org.eclipse.wst.xml.core.internal.document.XMLModelUpdater.replaceSource(XMLModelUpdater.java:1612) <br />
at org.eclipse.wst.xml.core.internal.document.XMLModelUpdater.changeAttrValue(XMLModelUpdater.java:187) <br />
at org.eclipse.wst.xml.core.internal.document.XMLModelUpdater.changeValue(XMLModelUpdater.java:600) <br />
at org.eclipse.wst.xml.core.internal.document.DOMModelImpl.valueChanged(DOMModelImpl.java:903) <br />
at org.eclipse.wst.xml.core.internal.document.AttrImpl.notifyValueChanged(AttrImpl.java:626) <br />
at org.eclipse.wst.xml.core.internal.document.AttrImpl.setValueSource(AttrImpl.java:767) <br />
at org.eclipse.wst.xml.core.internal.document.AttrImpl.setValue(AttrImpl.java:748) <br />
at org.eclipse.wst.xml.core.internal.document.ElementImpl.setAttribute(ElementImpl.java:1218) <br />
at org.eclipse.wst.common.internal.emf.resource.EMF2DOMAdapterImpl.primUpdateDOMFeature(EMF2DOMAdapterImpl.java:1380) <br />
at org.eclipse.wst.common.internal.emf.resource.EMF2DOMAdapterImpl.updateDOMFeature(EMF2DOMAdapterImpl.java:1618) <br />
at org.eclipse.wst.common.internal.emf.resource.EMF2DOMAdapterImpl.notifyChanged(EMF2DOMAdapterImpl.java:1099) <br />
at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:380) <br />
at ch.ge.ael.parameter.model.impl.ChainTypeImpl.setActor(ChainTypeImpl.java:293) <br />
at ch.ge.ael.parameter.model.util.ConnectionUtils.updateActor(ConnectionUtils.java:216) <br />
at ch.ge.ael.parameter.model.adapter.ActorTypeAdapter.notifyChanged(ActorTypeAdapter.java:46) <br />
at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:380) <br />
at ch.ge.ael.parameter.model.impl.ActorTypeImpl.setName(ActorTypeImpl.java:142) <br />
at ch.ge.ael.parameter.model.impl.ActorTypeImpl.eSet(ActorTypeImpl.java:239) <br />
at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eSet(BasicEObjectImpl.java:1081) <br />
at org.eclipse.wst.common.internal.emf.utilities.ExtendedEcoreUtil.eSetOrAdd(ExtendedEcoreUtil.java:155) <br />
at org.eclipse.wst.common.internal.emf.resource.Translator.setMOFValue(Translator.java:620) <br />
at org.eclipse.wst.common.internal.emf.resource.Translator.setMOFValue(Translator.java:635) <br />
at org.eclipse.wst.common.internal.emf.resource.EMF2DOMAdapterImpl.primUpdateMOFFeature(EMF2DOMAdapterImpl.java:1497) <br />
at org.eclipse.wst.common.internal.emf.resource.EMF2DOMAdapterImpl.updateMOFFeature(EMF2DOMAdapterImpl.java:1840) <br />
at org.eclipse.wst.xml.core.internal.emf2xml.EMF2DOMSSEAdapter.notifyChanged(EMF2DOMSSEAdapter.java:236) <br />
at org.eclipse.wst.sse.core.internal.provisional.AbstractNotifier.notify(AbstractNotifier.java:202) <br />
at org.eclipse.wst.xml.core.internal.document.XMLModelNotifierImpl.notify(XMLModelNotifierImpl.java:238) <br />
at org.eclipse.wst.xml.core.internal.document.XMLModelNotifierImpl.notifyDeferred(XMLModelNotifierImpl.java:340) <br />
at org.eclipse.wst.xml.core.internal.document.XMLModelNotifierImpl.endChanging(XMLModelNotifierImpl.java:178) <br />
at org.eclipse.wst.xml.core.internal.document.DOMModelImpl.changedModel(DOMModelImpl.java:163) <br />
at org.eclipse.wst.sse.core.internal.model.AbstractStructuredModel$DocumentToModelNotifier.regionChanged(AbstractStructuredModel.java:164) <br />
at org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument._fireEvent(BasicStructuredDocument.java:542) <br />
at org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument.fireStructuredDocumentEvent(BasicStructuredDocument.java:1181) <br />
at org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument.internalReplaceText(BasicStructuredDocument.java:1964) <br />
at org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument.replaceText(BasicStructuredDocument.java:2419) <br />
at org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument.replaceText(BasicStructuredDocument.java:2404) <br />
at org.eclipse.wst.sse.core.internal.text.JobSafeStructuredDocument.access$2(JobSafeStructuredDocument.java:1) <br />
at org.eclipse.wst.sse.core.internal.text.JobSafeStructuredDocument$3.run(JobSafeStructuredDocument.java:141) <br />
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42) <br />
at org.eclipse.wst.sse.ui.EditorExecutionContext.execute(EditorExecutionContext.java:149) <br />
at org.eclipse.wst.sse.core.internal.text.JobSafeStructuredDocument.replaceText(JobSafeStructuredDocument.java:144) <br />
at org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument.replace(BasicStructuredDocument.java:2364) <br />
at org.eclipse.wst.sse.core.internal.text.JobSafeStructuredDocument.access$0(JobSafeStructuredDocument.java:1) <br />
at org.eclipse.wst.sse.core.internal.text.JobSafeStructuredDocument$1.run(JobSafeStructuredDocument.java:103) <br />
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42) <br />
at org.eclipse.wst.sse.ui.EditorExecutionContext.execute(EditorExecutionContext.java:149) <br />
at org.eclipse.wst.sse.core.internal.text.JobSafeStructuredDocument.replace(JobSafeStructuredDocument.java:106) <br />
at org.eclipse.jface.text.projection.ProjectionTextStore.replace(ProjectionTextStore.java:111) <br />
at org.eclipse.jface.text.AbstractDocument.replace(AbstractDocument.java:1184) <br />
at org.eclipse.jface.text.AbstractDocument.replace(AbstractDocument.java:1210) <br />
at org.eclipse.jface.text.projection.ProjectionDocument.replace(ProjectionDocument.java:629) <br />
at org.eclipse.jface.text.DefaultDocumentAdapter.replaceTextRange(DefaultDocumentAdapter.java:248) <br />
at org.eclipse.swt.custom.StyledText.modifyContent(StyledText.java:7168) <br />
at org.eclipse.swt.custom.StyledText.sendKeyEvent(StyledText.java:7975) <br />
at org.eclipse.swt.custom.StyledText.doContent(StyledText.java:2456) <br />
at org.eclipse.swt.custom.StyledText.handleKey(StyledText.java:5928) <br />
at org.eclipse.swt.custom.StyledText.handleKeyDown(StyledText.java:5958) <br />
at org.eclipse.swt.custom.StyledText$7.handleEvent(StyledText.java:5652) <br />
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84) <br />
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053) <br />
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1077) <br />
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1062) <br />
at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:1103) <br />
at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:1099) <br />
at org.eclipse.swt.widgets.Widget.wmChar(Widget.java:1508) <br />
at org.eclipse.swt.widgets.Control.WM_CHAR(Control.java:4268) <br />
at org.eclipse.swt.widgets.Canvas.WM_CHAR(Canvas.java:345) <br />
at org.eclipse.swt.widgets.Control.windowProc(Control.java:4160) <br />
at org.eclipse.swt.widgets.Canvas.windowProc(Canvas.java:341) <br />
at org.eclipse.swt.widgets.Display.windowProc(Display.java:4873) <br />
at org.eclipse.swt.internal.win32.OS.DispatchMessageW(Native Method) <br />
at org.eclipse.swt.internal.win32.OS.DispatchMessage(OS.java:2459) <br />
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3655) <br />
at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2629) <br />
at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2593) <br />
at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2427) <br />
at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:670) <br />
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332) <br />
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:663) <br />
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149) <br />
at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:115) <br />
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196) <br />
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110) <br />
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79) <br />
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:369) <br />
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179) <br />
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) <br />
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) <br />
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) <br />
at java.lang.reflect.Method.invoke(Unknown Source) <br />
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:619) <br />
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:574) <br />
at org.eclipse.equinox.launcher.Main.run(Main.java:1407) <br />
at org.eclipse.equinox.launcher.Main.main(Main.java:1383) <br />
<br />
!ENTRY org.eclipse.wst.sse.core 4 4 2010-07-21 14:48:33.187 <br />
!MESSAGE <br />
!STACK 0 <br />
java.lang.NullPointerException <br />
at org.eclipse.jface.text.projection.ProjectionDocument.normalize(ProjectionDocument.java:671) <br />
at org.eclipse.jface.text.projection.ProjectionDocument.masterDocumentAboutToBeChanged(ProjectionDocument.java:721) <br />
at org.eclipse.jface.text.projection.ProjectionDocumentManager.fireDocumentEvent(ProjectionDocumentManager.java:121) <br />
at org.eclipse.jface.text.projection.ProjectionDocumentManager.documentAboutToBeChanged(ProjectionDocumentManager.java:138) <br />
at org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument._fireDocumentAboutToChange(BasicStructuredDocument.java:389) <br />
at org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument.fireDocumentAboutToChanged(BasicStructuredDocument.java:1120) <br />
at org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument.internalReplaceText(BasicStructuredDocument.java:1912) <br />
at org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument.replaceText(BasicStructuredDocument.java:2419) <br />
at org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument.replaceText(BasicStructuredDocument.java:2415) <br />
at org.eclipse.wst.sse.core.internal.text.JobSafeStructuredDocument.access$3(JobSafeStructuredDocument.java:1) <br />
at org.eclipse.wst.sse.core.internal.text.JobSafeStructuredDocument$4.run(JobSafeStructuredDocument.java:163) <br />
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42) <br />
at org.eclipse.wst.sse.ui.EditorExecutionContext.execute(EditorExecutionContext.java:149) <br />
at org.eclipse.wst.sse.core.internal.text.JobSafeStructuredDocument.replaceText(JobSafeStructuredDocument.java:171) <br />
at org.eclipse.wst.xml.core.internal.document.XMLModelUpdater.replaceSource(XMLModelUpdater.java:1612) <br />
at org.eclipse.wst.xml.core.internal.document.XMLModelUpdater.changeAttrValue(XMLModelUpdater.java:187) <br />
at org.eclipse.wst.xml.core.internal.document.XMLModelUpdater.changeValue(XMLModelUpdater.java:600) <br />
at org.eclipse.wst.xml.core.internal.document.DOMModelImpl.valueChanged(DOMModelImpl.java:903) <br />
at org.eclipse.wst.xml.core.internal.document.AttrImpl.notifyValueChanged(AttrImpl.java:626) <br />
at org.eclipse.wst.xml.core.internal.document.AttrImpl.setValueSource(AttrImpl.java:767) <br />
at org.eclipse.wst.xml.core.internal.document.AttrImpl.setValue(AttrImpl.java:748) <br />
at org.eclipse.wst.xml.core.internal.document.ElementImpl.setAttribute(ElementImpl.java:1218) <br />
at org.eclipse.wst.common.internal.emf.resource.EMF2DOMAdapterImpl.primUpdateDOMFeature(EMF2DOMAdapterImpl.java:1380) <br />
at org.eclipse.wst.common.internal.emf.resource.EMF2DOMAdapterImpl.updateDOMFeature(EMF2DOMAdapterImpl.java:1618) <br />
at org.eclipse.wst.common.internal.emf.resource.EMF2DOMAdapterImpl.notifyChanged(EMF2DOMAdapterImpl.java:1099) <br />
at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:380) <br />
at ch.ge.ael.parameter.model.impl.ChainTypeImpl.setActor(ChainTypeImpl.java:293) <br />
at ch.ge.ael.parameter.model.util.ConnectionUtils.updateActor(ConnectionUtils.java:216) <br />
at ch.ge.ael.parameter.model.adapter.ActorTypeAdapter.notifyChanged(ActorTypeAdapter.java:46) <br />
at org.eclipse.emf.common.notify.impl.BasicNotifierImpl.eNotify(BasicNotifierImpl.java:380) <br />
at ch.ge.ael.parameter.model.impl.ActorTypeImpl.setName(ActorTypeImpl.java:142) <br />
at ch.ge.ael.parameter.model.impl.ActorTypeImpl.eSet(ActorTypeImpl.java:239) <br />
at org.eclipse.emf.ecore.impl.BasicEObjectImpl.eSet(BasicEObjectImpl.java:1081) <br />
at org.eclipse.wst.common.internal.emf.utilities.ExtendedEcoreUtil.eSetOrAdd(ExtendedEcoreUtil.java:155) <br />
at org.eclipse.wst.common.internal.emf.resource.Translator.setMOFValue(Translator.java:620) <br />
at org.eclipse.wst.common.internal.emf.resource.Translator.setMOFValue(Translator.java:635) <br />
at org.eclipse.wst.common.internal.emf.resource.EMF2DOMAdapterImpl.primUpdateMOFFeature(EMF2DOMAdapterImpl.java:1497) <br />
at org.eclipse.wst.common.internal.emf.resource.EMF2DOMAdapterImpl.updateMOFFeature(EMF2DOMAdapterImpl.java:1840) <br />
at org.eclipse.wst.xml.core.internal.emf2xml.EMF2DOMSSEAdapter.notifyChanged(EMF2DOMSSEAdapter.java:236) <br />
at org.eclipse.wst.sse.core.internal.provisional.AbstractNotifier.notify(AbstractNotifier.java:202) <br />
at org.eclipse.wst.xml.core.internal.document.XMLModelNotifierImpl.notify(XMLModelNotifierImpl.java:238) <br />
at org.eclipse.wst.xml.core.internal.document.XMLModelNotifierImpl.notifyDeferred(XMLModelNotifierImpl.java:340) <br />
at org.eclipse.wst.xml.core.internal.document.XMLModelNotifierImpl.endChanging(XMLModelNotifierImpl.java:178) <br />
at org.eclipse.wst.xml.core.internal.document.DOMModelImpl.changedModel(DOMModelImpl.java:163) <br />
at org.eclipse.wst.sse.core.internal.model.AbstractStructuredModel$DocumentToModelNotifier.regionChanged(AbstractStructuredModel.java:164) <br />
at org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument._fireEvent(BasicStructuredDocument.java:542) <br />
at org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument.fireStructuredDocumentEvent(BasicStructuredDocument.java:1181) <br />
at org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument.internalReplaceText(BasicStructuredDocument.java:1964) <br />
at org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument.replaceText(BasicStructuredDocument.java:2419) <br />
at org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument.replaceText(BasicStructuredDocument.java:2404) <br />
at org.eclipse.wst.sse.core.internal.text.JobSafeStructuredDocument.access$2(JobSafeStructuredDocument.java:1) <br />
at org.eclipse.wst.sse.core.internal.text.JobSafeStructuredDocument$3.run(JobSafeStructuredDocument.java:141) <br />
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42) <br />
at org.eclipse.wst.sse.ui.EditorExecutionContext.execute(EditorExecutionContext.java:149) <br />
at org.eclipse.wst.sse.core.internal.text.JobSafeStructuredDocument.replaceText(JobSafeStructuredDocument.java:144) <br />
at org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument.replace(BasicStructuredDocument.java:2364) <br />
at org.eclipse.wst.sse.core.internal.text.JobSafeStructuredDocument.access$0(JobSafeStructuredDocument.java:1) <br />
at org.eclipse.wst.sse.core.internal.text.JobSafeStructuredDocument$1.run(JobSafeStructuredDocument.java:103) <br />
at org.eclipse.core.runtime.SafeRunner.run(SafeRunner.java:42) <br />
at org.eclipse.wst.sse.ui.EditorExecutionContext.execute(EditorExecutionContext.java:149) <br />
at org.eclipse.wst.sse.core.internal.text.JobSafeStructuredDocument.replace(JobSafeStructuredDocument.java:106) <br />
at org.eclipse.jface.text.projection.ProjectionTextStore.replace(ProjectionTextStore.java:111) <br />
at org.eclipse.jface.text.AbstractDocument.replace(AbstractDocument.java:1184) <br />
at org.eclipse.jface.text.AbstractDocument.replace(AbstractDocument.java:1210) <br />
at org.eclipse.jface.text.projection.ProjectionDocument.replace(ProjectionDocument.java:629) <br />
at org.eclipse.jface.text.DefaultDocumentAdapter.replaceTextRange(DefaultDocumentAdapter.java:248) <br />
at org.eclipse.swt.custom.StyledText.modifyContent(StyledText.java:7168) <br />
at org.eclipse.swt.custom.StyledText.sendKeyEvent(StyledText.java:7975) <br />
at org.eclipse.swt.custom.StyledText.doContent(StyledText.java:2456) <br />
at org.eclipse.swt.custom.StyledText.handleKey(StyledText.java:5928) <br />
at org.eclipse.swt.custom.StyledText.handleKeyDown(StyledText.java:5958) <br />
at org.eclipse.swt.custom.StyledText$7.handleEvent(StyledText.java:5652) <br />
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84) <br />
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1053) <br />
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1077) <br />
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1062) <br />
at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:1103) <br />
at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:1099) <br />
at org.eclipse.swt.widgets.Widget.wmChar(Widget.java:1508) <br />
at org.eclipse.swt.widgets.Control.WM_CHAR(Control.java:4268) <br />
at org.eclipse.swt.widgets.Canvas.WM_CHAR(Canvas.java:345) <br />
at org.eclipse.swt.widgets.Control.windowProc(Control.java:4160) <br />
at org.eclipse.swt.widgets.Canvas.windowProc(Canvas.java:341) <br />
at org.eclipse.swt.widgets.Display.windowProc(Display.java:4873) <br />
at org.eclipse.swt.internal.win32.OS.DispatchMessageW(Native Method) <br />
at org.eclipse.swt.internal.win32.OS.DispatchMessage(OS.java:2459) <br />
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3655) <br />
at org.eclipse.ui.internal.Workbench.runEventLoop(Workbench.java:2629) <br />
at org.eclipse.ui.internal.Workbench.runUI(Workbench.java:2593) <br />
at org.eclipse.ui.internal.Workbench.access$4(Workbench.java:2427) <br />
at org.eclipse.ui.internal.Workbench$7.run(Workbench.java:670) <br />
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332) <br />
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:663) <br />
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149) <br />
at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:115) <br />
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196) <br />
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110) <br />
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79) <br />
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:369) <br />
at org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:179) <br />
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) <br />
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) <br />
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) <br />
at java.lang.reflect.Method.invoke(Unknown Source) <br />
at org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:619) <br />
at org.eclipse.equinox.launcher.Main.basicRun(Main.java:574) <br />
at org.eclipse.equinox.launcher.Main.run(Main.java:1407) <br />
at org.eclipse.equinox.launcher.Main.main(Main.java:1383) <br />
As-tu déjà été confronté à ce problème?
J’avoue que j’ai un peu peur de descendre dans les couches d’EMF (j’y suis déjà allé un peu mais sans trop savoir quoi en penser…)
Merci beaucoup!