blob: f2b4c3e653bee0069adbbf88c4ed495a186087ba [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.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import org.eclipse.emf.common.util.EList;
import org.eclipse.viatra2.gtasm.interpreter.executionEnvironment.ASMFunctionContent;
import org.eclipse.viatra2.gtasm.interpreter.executionEnvironment.ASMFunctionContentChangeListener;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.boundary.IPredicateTraceListener;
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.tuple.FlatTuple;
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.tuple.Tuple;
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.definitions.ASMFunction;
/**
* Registering/unregistering is synchronized, as well as change notification
* sending. Reason: thread safety of Registering/unregistering and message
* sending to registered ones
*
* @author Gabor Bergmann
*
*/
public class ASMFunctionListener implements ASMFunctionContentChangeListener, IPredicateTraceListener {
// each registered tuple consists of (a) the ASM function (b) the actual
// parameter sequence
protected Map<Tuple, Set<PredicateEvaluatorNode>> asmSensitiveTerms;
protected ReteEngine<?> engine;
protected ReteBoundary<?> boundary;
/**
* Prerequisite: disconnectables
*
* @param engine
*/
public ASMFunctionListener(ReteEngine<?> engine) {
this.engine = engine;
this.boundary = engine.getBoundary();
this.asmSensitiveTerms = new HashMap<Tuple, Set<PredicateEvaluatorNode>>();
ASMFunctionContent.getInstance().addListener(null, this);
engine.addDisconnectable(this);
}
public void disconnect() {
asmSensitiveTerms.clear();
ASMFunctionContent.getInstance().removeListener(null, this);
}
/* (non-Javadoc)
* @see org.eclipse.viatra2.gtasm.patternmatcher.incremental.adapters.IPredicateTraceListener#registerASMSensitiveTerm(org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.tuple.Tuple, org.eclipse.viatra2.gtasm.patternmatcher.incremental.adapters.PredicateEvaluatorNode)
*/
public synchronized void registerSensitiveTrace(Tuple trace,
PredicateEvaluatorNode node) {
Set<PredicateEvaluatorNode> nodes = asmSensitiveTerms.get(trace);
if (nodes == null) {
nodes = new HashSet<PredicateEvaluatorNode>();
asmSensitiveTerms.put(trace, nodes);
}
nodes.add(node);
}
/* (non-Javadoc)
* @see org.eclipse.viatra2.gtasm.patternmatcher.incremental.adapters.IPredicateTraceListener#unregisterASMSensitiveTerm(org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.tuple.Tuple, org.eclipse.viatra2.gtasm.patternmatcher.incremental.adapters.PredicateEvaluatorNode)
*/
public synchronized void unregisterSensitiveTrace(Tuple trace,
PredicateEvaluatorNode node) {
Set<PredicateEvaluatorNode> nodes = asmSensitiveTerms.get(trace);
nodes.remove(node);
if (nodes.isEmpty()) {
asmSensitiveTerms.remove(trace);
}
}
public void valueChanged(ASMFunction f, EList<Object> key, Object newValue) {
//System.out.println("value changed for key:"+key.toString()+", value: "
// +newValue.toString());
Object[] traceElements = new Object[key.size() + 1];
int k = 0;
traceElements[k++] = f;
for (Object o : key)
traceElements[k++] = o;
Tuple trace = new FlatTuple(traceElements);
synchronized (this) {
Set<PredicateEvaluatorNode> nodes = asmSensitiveTerms.get(trace);
if (nodes != null) {
// copy to avoid concurrency exceptions
LinkedList<PredicateEvaluatorNode> nodesCopy = new LinkedList<PredicateEvaluatorNode>(
nodes);
for (PredicateEvaluatorNode node : nodesCopy) {
boundary.notifyEvaluator(
node.getAsmFunctionTraceNotifier(), trace);
}
}
}
}
}