| /******************************************************************************* |
| * 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(); |
| }
|
| }
|