blob: 7c1cc3d2517e8af6fd59a4e014e086dea9a8cd24 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004-2008 Gabor Bergmann and Daniel Varro
* 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:
* Gabor Bergmann - initial API and implementation
*******************************************************************************/
package org.eclipse.viatra2.gtasm.patternmatcher.incremental.adapters;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.eclipse.viatra2.core.ICoreNotificationListener;
import org.eclipse.viatra2.core.IEntity;
import org.eclipse.viatra2.core.IModelElement;
import org.eclipse.viatra2.core.IRelation;
import org.eclipse.viatra2.core.notification.ICoreNotificationObject;
import org.eclipse.viatra2.core.notification.ICoreNotificationObjectCreateEntity;
import org.eclipse.viatra2.core.notification.ICoreNotificationObjectCreateInstanceOf;
import org.eclipse.viatra2.core.notification.ICoreNotificationObjectCreateRelation;
import org.eclipse.viatra2.core.notification.ICoreNotificationObjectCreateSupertypeOf;
import org.eclipse.viatra2.core.notification.ICoreNotificationObjectDeleteContainment;
import org.eclipse.viatra2.core.notification.ICoreNotificationObjectDeleteEntity;
import org.eclipse.viatra2.core.notification.ICoreNotificationObjectDeleteInstanceOf;
import org.eclipse.viatra2.core.notification.ICoreNotificationObjectDeleteRelation;
import org.eclipse.viatra2.core.notification.ICoreNotificationObjectDeleteSupertypeOf;
import org.eclipse.viatra2.core.notification.ICoreNotificationObjectMoveTo;
import org.eclipse.viatra2.core.notification.ICoreNotificationObjectSetName;
import org.eclipse.viatra2.core.notification.ICoreNotificationObjectSetRelationFrom;
import org.eclipse.viatra2.core.notification.ICoreNotificationObjectSetRelationTo;
import org.eclipse.viatra2.core.notification.ICoreNotificationObjectSetValue;
import org.eclipse.viatra2.framework.IFramework;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.boundary.IManipulationListener;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.boundary.PredicateEvaluatorNode;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.boundary.ReteBoundary;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.matcher.ReteEngine;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.network.Direction;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.network.ReteContainer;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.network.Tunnel;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.remote.Address;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.tuple.FlatTuple;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.tuple.Tuple;
/**
* Registering/unregistering is synchronized, as well as notification
* processing. Reason: thread safety of Registering/unregistering and message
* sending and action notifications
*
* @author Gabor Bergmann
*
*/
public class GlobalModelspaceListener implements ICoreNotificationListener,
IManipulationListener {
protected WeakReference<IFramework> framework;
protected ReteEngine<?> engine;
protected ReteBoundary<?> boundary;
protected ReteContainer headContainer;
// TermEvaluatorNodes that have to be notified on changes affecting a given ModelElement
protected Map<Object, Set<PredicateEvaluatorNode>> sensitiveTerms;
/**
* Prerequisite: engine has its network, framework and boundary fields
* initialized
*
* @param engine
*/
public GlobalModelspaceListener(ReteEngine<?> engine, IFramework framework) {
super();
this.engine = engine;
this.boundary = engine.getBoundary();
this.headContainer = engine.getReteNet().getHeadContainer();
this.sensitiveTerms = new HashMap<Object, Set<PredicateEvaluatorNode>>();
this.framework = new WeakReference<IFramework>(framework);
framework.getTopmodel().getNotificationManager()
.addAllListener(this);
engine.addDisconnectable(this);
}
public synchronized void actionPerformed(
ICoreNotificationObject notification) {
//System.out.println("Core notification: "+notification.getActionType())
// ;
// if (notification.getActionType().equals(ICoreNotificationObject.
// TA_TRANSACTION_BEGIN))
// {
// inTransaction = true;
// return;
// }
// else if (notification.getActionType().equals(ICoreNotificationObject.
// TA_UNDOABLE_TRANSACTION_BEGIN))
// {
// return;
// }
// else if (notification.getActionType().equals(ICoreNotificationObject.
// TA_TRANSACTION_END))
// {
// inTransaction = false;
// iTreeViewer.refresh();
// iContentProvider.setDirty(); // notify editor that the model has
// changed
// return;
// }
// if (inTransaction)
// return;
//
switch(notification.getActionTypeEnum()){
case ACTION_SET_NAME:
ICoreNotificationObjectSetName n = (ICoreNotificationObjectSetName) notification;
notifyElementChange(n.getElement());
break;
case ACTION_SET_VALUE:
ICoreNotificationObjectSetValue n1 = (ICoreNotificationObjectSetValue) notification;
notifyElementChange(n1.getEntity());
break;
case ACTION_CREATE_INSTANCEOF:
ICoreNotificationObjectCreateInstanceOf n2 = (ICoreNotificationObjectCreateInstanceOf) notification;
IModelElement instance = n2.getInstance();
if (instance instanceof IEntity)
boundary.updateUnary(Direction.INSERT, instance, n2.getType());
else if (instance instanceof IRelation) {
IRelation relation = (IRelation) instance;
boundary.updateTernaryEdge(Direction.INSERT, relation,
relation.getFrom(), relation.getTo(), n2.getType());
}
boundary.updateInstantiation(Direction.INSERT, n2.getType(),
n2.getInstance());
break;
case ACTION_DELETE_INSTANCEOF:
ICoreNotificationObjectDeleteInstanceOf n3 = (ICoreNotificationObjectDeleteInstanceOf) notification;
instance = n3.getInstance();
if (instance instanceof IEntity)
boundary.updateUnary(Direction.REVOKE, instance, n3.getType());
else if (instance instanceof IRelation) {
IRelation relation = (IRelation) instance;
boundary.updateTernaryEdge(Direction.REVOKE, relation,
relation.getFrom(), relation.getTo(), n3.getType());
}
boundary.updateInstantiation(Direction.REVOKE, n3.getType(),
n3.getInstance());
break;
case ACTION_CREATE_SUPERTYPEOF:
ICoreNotificationObjectCreateSupertypeOf n4 = (ICoreNotificationObjectCreateSupertypeOf) notification;
IModelElement superElement = n4.getSuper();
IModelElement subElement = n4.getSub();
boundary.updateGeneralization(Direction.INSERT, superElement,
subElement);
if (superElement instanceof IEntity) {
Address<? extends Tunnel> superRoot = boundary
.getUnaryRoot(superElement);
if (superRoot != null) // only if we have to keep track of the
// supertype
{
Address<? extends Tunnel> subRoot = boundary
.accessUnaryRoot(subElement);
engine.getReteNet().connectRemoteNodes(subRoot, superRoot,
true);
}
} else if (superElement instanceof IRelation) {
Address<? extends Tunnel> superRoot = boundary
.getTernaryEdgeRoot(superElement);
if (superRoot != null) // only if we have to keep track of the
// supertype
{
Address<? extends Tunnel> subRoot = boundary
.accessTernaryEdgeRoot(subElement);
engine.getReteNet().connectRemoteNodes(subRoot, superRoot,
true);
}
}
break;
case ACTION_DELETE_SUPERTYPEOF:
ICoreNotificationObjectDeleteSupertypeOf n5 = (ICoreNotificationObjectDeleteSupertypeOf) notification;
superElement = n5.getSuper();
subElement = n5.getSub();
boundary.updateGeneralization(Direction.REVOKE, superElement,
subElement);
if (superElement instanceof IEntity) {
Address<? extends Tunnel> superRoot = boundary
.getUnaryRoot(superElement);
if (superRoot != null) // only if we have to keep track of the
// supertype
{
Address<? extends Tunnel> subRoot = boundary
.accessUnaryRoot(subElement);
engine.getReteNet().disconnectRemoteNodes(subRoot,
superRoot, true);
}
} else if (superElement instanceof IRelation) {
Address<? extends Tunnel> superRoot = boundary
.getTernaryEdgeRoot(superElement);
if (superRoot != null) // only if we have to keep track of the
// supertype
{
Address<? extends Tunnel> subRoot = boundary
.accessTernaryEdgeRoot(subElement);
engine.getReteNet().disconnectRemoteNodes(subRoot,
superRoot, true);
}
}
break;
// case ACTION_SET_VIEW_INFO:
// ICoreNotificationObjectSetViewInfo n =
// (ICoreNotificationObjectSetViewInfo)notification;
// iTreeViewer.update(n.getElement(), new String[]{"name"});
// break;
case ACTION_CREATE_ENTITY:
ICoreNotificationObjectCreateEntity n6 = (ICoreNotificationObjectCreateEntity) notification;
IEntity entity = n6.getCreated();
// for (IModelElement type : entity.getTypes())
// boundary.updateEntity(Direction.INSERT, entity,
// type.getFullyQualifiedName());
boundary.updateUnary(Direction.INSERT, entity, null);
boundary.updateContainment(Direction.INSERT, n6.getContainer(),
entity);
break;
case ACTION_CREATE_RELATION:
ICoreNotificationObjectCreateRelation n7 = (ICoreNotificationObjectCreateRelation) notification;
IRelation relation = n7.getNewRelation();
// for (IModelElement type : relation.getTypes())
// boundary.updateRelation(Direction.INSERT, relation,
// relation.getFrom(), relation.getTo(),
// type.getFullyQualifiedName());
boundary.updateTernaryEdge(Direction.INSERT, relation,
n7.getFrom(), n7.getTo(), null);
break;
case ACTION_MOVE_ELEMENT_TO:
ICoreNotificationObjectMoveTo n8 = (ICoreNotificationObjectMoveTo) notification;
IEntity element = n8.getElement();
boundary.updateContainment(Direction.REVOKE, n8.getOldContainer(),
element);
boundary.updateContainment(Direction.INSERT, n8.getNewContainer(),
element);
notifyElementChange(n8.getElement());
break;
case ACTION_DELETE_ENTITY:
ICoreNotificationObjectDeleteEntity n9 = (ICoreNotificationObjectDeleteEntity) notification;
entity = n9.getDeleted();
// for (IModelElement type : entity.getTypes())
// boundary.updateEntity(Direction.REVOKE, entity,
// type.getFullyQualifiedName());
boundary.updateUnary(Direction.REVOKE, entity, null);
// boundary.revokeRelation(n.getParent(), entity,
// ReteBoundary.containmentLabel);
break;
case ACTION_DELETE_RELATION:
ICoreNotificationObjectDeleteRelation n10 = (ICoreNotificationObjectDeleteRelation) notification;
relation = n10.getDeleted();
// for (IModelElement type : relation.getTypes())
// boundary.updateRelation(Direction.REVOKE, relation,
// relation.getFrom(), relation.getTo(),
// type.getFullyQualifiedName());
boundary.updateTernaryEdge(Direction.REVOKE, relation,
n10.getFrom(), n10.getTo(), null);
break;
case ACTION_DELETE_CONTAINMENT:
ICoreNotificationObjectDeleteContainment n11 = (ICoreNotificationObjectDeleteContainment) notification;
boundary.updateContainment(Direction.REVOKE, n11.getParent(),
n11.getChild());
break;
case ACTION_SET_RELATION_FROM:
ICoreNotificationObjectSetRelationFrom n12 = (ICoreNotificationObjectSetRelationFrom) notification;
relation = n12.getRelation();
for (IModelElement type : relation.getTypes()) {
boundary.updateTernaryEdge(Direction.REVOKE, relation,
n12.getOldFrom(), relation.getTo(), type);
boundary.updateTernaryEdge(Direction.INSERT, relation,
n12.getNewFrom(), relation.getTo(), type);
}
boundary.updateTernaryEdge(Direction.REVOKE, relation,
n12.getOldFrom(), relation.getTo(), null);
boundary.updateTernaryEdge(Direction.INSERT, relation,
n12.getNewFrom(), relation.getTo(), null);
notifyElementChange(relation);
break;
case ACTION_SET_RELATION_TO:
ICoreNotificationObjectSetRelationTo n13 = (ICoreNotificationObjectSetRelationTo) notification;
relation = n13.getRelation();
for (IModelElement type : relation.getTypes()) {
boundary.updateTernaryEdge(Direction.REVOKE, relation,
relation.getFrom(), n13.getOldTo(), type);
boundary.updateTernaryEdge(Direction.INSERT, relation,
relation.getFrom(), n13.getNewTo(), type);
}
boundary.updateTernaryEdge(Direction.REVOKE, relation,
relation.getFrom(), n13.getOldTo(), null);
boundary.updateTernaryEdge(Direction.INSERT, relation,
relation.getFrom(), n13.getNewTo(), null);
notifyElementChange(relation);
break;
case TA_TRANSACTION_END:
engine.runAfterUpdateCallbacks();
break;
}
}
protected void notifyElementChange(Object element) {
synchronized (sensitiveTerms) {
Set<PredicateEvaluatorNode> nodes = sensitiveTerms.get(element);
if (nodes != null) {
Tuple tuple = new FlatTuple(element);
for (PredicateEvaluatorNode node : nodes)
boundary.notifyEvaluator(node.getElementChangeNotifier(), tuple);
}
}
}
public void registerSensitiveTerm(Object element, PredicateEvaluatorNode node) {
synchronized (sensitiveTerms) {
Set<PredicateEvaluatorNode> nodes = sensitiveTerms.get(element);
if (nodes == null) {
nodes = new HashSet<PredicateEvaluatorNode>();
sensitiveTerms.put(element, nodes);
}
nodes.add(node);
}
}
public void unregisterSensitiveTerm(Object element, PredicateEvaluatorNode node) {
synchronized (sensitiveTerms) {
Set<PredicateEvaluatorNode> nodes = sensitiveTerms.get(element);
nodes.remove(node);
if (nodes.isEmpty()) sensitiveTerms.remove(element);
}
}
public int getListenerCategory() {
// TODO Auto-generated method stub
return 0;
}
public void disconnect() {
framework.get().getTopmodel().getNotificationManager()
.removeAllListener(this);
}
}