blob: f93bb03e964589ff6e23a35477379031de64c58d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004-2008 Akos Horvath, Gergely Varro 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:
* Akos Horvath, Gergely Varro - initial API and implementation
*******************************************************************************/
package org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.rgg;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Queue;
import java.util.Vector;
import org.eclipse.viatra2.gtasm.interpreter.exception.ViatraTransformationException;
import org.eclipse.viatra2.gtasm.patternmatcher.IMatching;
import org.eclipse.viatra2.gtasm.patternmatcher.exceptions.PatternMatcherRuntimeException;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.IKeyGenerator;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.MatchingFrame;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.MatchingKey;
import org.eclipse.viatra2.gtasm.patternmatcher.impl.patternmatcher.internal.callgraph.PatternNode;
public class RemoteGoal extends Goal implements Iterable<MatchingFrame> {
protected String id;
protected PatternNode pattern;
private Vector<Rule> children;
private Vector<Queue<MatchingFrame>> queues;
private Map<MatchingKey, List<MatchingFrame>> mapWithAdornedIndex;
private Map<MatchingKey, List<MatchingFrame>> map;
private Queue<MatchingFrame> newFrames;
protected MagicSet ms;
protected Boolean[] adornment;
protected IKeyGenerator<MatchingKey, IMatching> adornedKeyGenerator;
protected IKeyGenerator<MatchingKey, IMatching> keyGenerator;
public RemoteGoal(PatternNode pattern, Boolean[] adornment) {
this.pattern = pattern;
this.id = generateID(pattern, adornment);
this.children = new Vector<Rule>();
this.queues = new Vector<Queue<MatchingFrame>>();
this.newFrames = new LinkedList<MatchingFrame>();
this.adornment = adornment;
this.mapWithAdornedIndex = new HashMap<MatchingKey, List<MatchingFrame>>();
this.map = new HashMap<MatchingKey, List<MatchingFrame>>();
ms = new MagicSet(adornment);
Vector<Integer> adornedVector = new Vector<Integer>();
Vector<Integer> vector = new Vector<Integer>();
for (int i = 0; i < adornment.length; i++) {
if (adornment[i]) {
adornedVector.add(i);
}
vector.add(i);
}
final Integer[] key1 = new Integer[adornedVector.size()];
adornedVector.toArray(key1);
adornedKeyGenerator = new IKeyGenerator<MatchingKey, IMatching>() {
public MatchingKey calculateKey(IMatching value) {
Object[] matchingKey = new Object[key1.length];
for (int i = 0; i < key1.length; i++) {
matchingKey[i] = value.lookup(key1[i]);
}
return new MatchingKey(matchingKey);
}
public int size() {
return key1.length;
}
};
final Integer[] key2 = new Integer[vector.size()];
vector.toArray(key2);
keyGenerator = new IKeyGenerator<MatchingKey, IMatching>() {
public MatchingKey calculateKey(IMatching value) {
Object[] matchingKey = new Object[key2.length];
for (int i = 0; i < key2.length; i++) {
matchingKey[i] = value.lookup(key2[i]);
}
return new MatchingKey(matchingKey);
}
public int size() {
return key2.length;
}
};
}
public static String generateID(PatternNode pattern, Boolean[] adornment) {
StringBuffer b = new StringBuffer();
for (int i = 0; i < adornment.length; i++) {
b.append(adornment[i] ? 'b' : 'f');
}
return pattern.getPattern().getName() + "^" + b.toString();
}
public void calculateAllDeltas(IndexedRule parent, Queue<MatchingFrame> output) throws PatternMatcherRuntimeException {
// --->
// left |><| right
Queue<MatchingFrame> input = parent.getQueue();
for (Iterator<MatchingFrame> i = input.iterator(); i.hasNext();) {
MatchingFrame leftFrame = i.next();
MatchingKey keyForLeftFrame = parent.getBoundHeader(leftFrame);
List<MatchingFrame> list = mapWithAdornedIndex.get(keyForLeftFrame);
if (list != null) {
for (MatchingFrame rightFrame : list) {
MatchingFrame newFrame = (MatchingFrame) leftFrame.clone();
parent.merge(newFrame, rightFrame);
output.offer(newFrame);
}
}
ms.addArray(keyForLeftFrame);
i.remove();
}
// <---
// left |><| right
for (Iterator<MatchingFrame> j = newFrames.iterator(); j.hasNext();) {
MatchingFrame rightFrame = j.next();
Vector<Object> v = new Vector<Object>();
int size = 0;
for (int i = 0; i < adornment.length; i++) {
if (adornment[i]) {
v.add(rightFrame.getValue(i));
size++;
}
}
final Object[] key = new Object[size];
v.toArray(key);
HistoryList<MatchingKey, MatchingFrame> queue =
parent.getQueue();
List<MatchingFrame> list = queue.get(new MatchingKey(key));
if (list != null) {
for (MatchingFrame leftFrame : list) {
MatchingFrame newFrame = (MatchingFrame) leftFrame.clone();
parent.merge(newFrame, rightFrame);
output.offer(newFrame);
}
}
}
}
public MagicSet getMagicSet() {
return ms;
}
public void addChild(Rule child, Queue<MatchingFrame> queue) {
children.add(child);
queues.add(queue);
}
public boolean equals(Object other) {
if (other != null && other instanceof RemoteGoal) {
RemoteGoal rg = (RemoteGoal) other;
return id.equals(rg.id);
} else {
return false;
}
}
public String toString() {
return id;
}
public boolean synchronize() throws ViatraTransformationException {
boolean result = false;
for (Iterator<MatchingFrame> i = newFrames.iterator(); i.hasNext();) {
MatchingFrame frame = i.next();
MatchingKey keyForFrame = adornedKeyGenerator.calculateKey(frame);
List<MatchingFrame> currentList =
mapWithAdornedIndex.get(keyForFrame);
if (currentList == null) {
currentList = new LinkedList<MatchingFrame>();
}
currentList.add(frame);
mapWithAdornedIndex.put(keyForFrame, currentList);
i.remove();
}
assert newFrames.isEmpty();
for (Queue<MatchingFrame> queue : queues) {
for (Iterator<MatchingFrame> i = queue.iterator(); i.hasNext();) {
MatchingFrame frame = i.next();
MatchingKey keyForFrame = keyGenerator.calculateKey(frame);
List<MatchingFrame> currentList = map.get(keyForFrame);
if (currentList == null) {
currentList = new LinkedList<MatchingFrame>();
newFrames.add(frame);
result = true;
}
currentList.add(frame);
map.put(keyForFrame, currentList);
i.remove();
}
}
for (Rule rule : children) {
rule.synchronize();
}
return (ms.synchronizeFromGoal() ? true : result);
}
public void init() {
ms.init();
map.clear();
mapWithAdornedIndex.clear();
for (Queue<MatchingFrame> queue : queues) {
queue.clear();
}
newFrames.clear();
//TODO akos: HistoryList in the IndexedRule-s are not properly initialised
//and always saves information after pattern matching! In some cases multiple times!
for(Rule r:children)
r.init();
}
/*
public MatchingFrame match(PatternCallSignature[] signature, Vector<Integer> freeVariables) throws PatternMatcherRuntimeException {
// init();
assert children.size() == queues.size();
for (int i = 0; i < children.size(); i++) {
Rule rule = children.get(i);
MatchingFrame template = new MatchingFrame(rule.pattern);
MatchingFrame frame = rule.traverse(queues.get(i), template);
for (Integer varID : freeVariables) {
Scope s = signature[varID].getParameterScope();
if (s.getContainmentMode() == ContainmentMode.IN &&
!((IEntity) s.getParent()).getContents().contains(frame.getValue(varID)) ||
s.getContainmentMode() == ContainmentMode.BELOW &&
!((IEntity) s.getParent()).getAllComponents().contains(frame.getValue(varID))) {
break;
}
return frame;
}
}
return null;
}
*/
public void matchAll() throws PatternMatcherRuntimeException {
// init();
assert children.size() == queues.size();
for (int i = 0; i < children.size(); i++) {
Rule rule = children.get(i);
MatchingFrame template = new MatchingFrame(rule.pattern);
rule.traverseAll(queues.get(i), template);
}
}
public Iterator<MatchingFrame> iterator() {
return new ResultFrameIterator();
}
private class ResultFrameIterator implements Iterator<MatchingFrame> {
Iterator<List<MatchingFrame>> listIterator;
Iterator<MatchingFrame> frameIterator;
private ResultFrameIterator() {
listIterator = map.values().iterator();
frameIterator = (listIterator.hasNext() ? listIterator.next().iterator() : null);
}
public boolean hasNext() {
while (frameIterator != null && !frameIterator.hasNext()) {
frameIterator = (listIterator.hasNext() ? listIterator.next().iterator() : null);
}
return frameIterator != null;
}
public MatchingFrame next() {
if (hasNext()) {
return frameIterator.next();
} else {
throw new NoSuchElementException();
}
}
public void remove() {
throw new UnsupportedOperationException();
}
}
public void debug() {
for(Rule rule: children)
if(rule instanceof UnindexedRule)
((UnindexedRule)rule).debug();
}
}