/*******************************************************************************
* Copyright (c) 2010-2012, Tamas Szabo, Gabor Bergmann, Istvan Rath 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:
* Tamas Szabo - initial API and implementation
*******************************************************************************/
package org.eclipse.incquery.runtime.rete.single;
import java.util.Collection;
import org.eclipse.incquery.runtime.base.itc.alg.incscc.IncSCCAlg;
import org.eclipse.incquery.runtime.base.itc.alg.misc.Tuple;
import org.eclipse.incquery.runtime.base.itc.graphimpl.Graph;
import org.eclipse.incquery.runtime.base.itc.igraph.ITcDataSource;
import org.eclipse.incquery.runtime.base.itc.igraph.ITcObserver;
import org.eclipse.incquery.runtime.rete.network.Direction;
import org.eclipse.incquery.runtime.rete.network.ReteContainer;
import org.eclipse.incquery.runtime.rete.tuple.Clearable;
import org.eclipse.incquery.runtime.rete.tuple.FlatTuple;
// TODO egyelore (i,j) elek, majd helyette mask megoldas
// TODO bemeneti index
/**
* This class represents a transitive closure node in the rete net.
*
* @author Gabor Bergmann
*
*/
public class TransitiveClosureNode extends SingleInputNode implements Clearable, ITcObserver<Object> {
private Graph<Object> graphDataSource;
private ITcDataSource<Object> transitiveClosureAlgorithm;
/**
* Create a new transitive closure rete node. Initializes the graph data source with the given collection of tuples.
*
* @param reteContainer
* the rete container of the node
* @param tuples
* the initial collection of tuples
*/
public TransitiveClosureNode(ReteContainer reteContainer,
Collection<org.eclipse.incquery.runtime.rete.tuple.Tuple> tuples) {
super(reteContainer);
graphDataSource = new Graph<Object>();
for (org.eclipse.incquery.runtime.rete.tuple.Tuple t : tuples) {
graphDataSource.insertNode(t.get(0));
graphDataSource.insertNode(t.get(1));
graphDataSource.insertEdge(t.get(0), t.get(1));
}
transitiveClosureAlgorithm = new IncSCCAlg<Object>(graphDataSource);
transitiveClosureAlgorithm.attachObserver(this);
reteContainer.registerClearable(this);
}
public TransitiveClosureNode(ReteContainer reteContainer) {
super(reteContainer);
graphDataSource = new Graph<Object>();
transitiveClosureAlgorithm = new IncSCCAlg<Object>(graphDataSource);
transitiveClosureAlgorithm.attachObserver(this);
reteContainer.registerClearable(this);
}
@Override
public void pullInto(Collection<org.eclipse.incquery.runtime.rete.tuple.Tuple> collector) {
for (Tuple<Object> tuple : ((IncSCCAlg<Object>) transitiveClosureAlgorithm).getTcRelation()) {
collector.add(new FlatTuple(tuple.getSource(), tuple.getTarget()));
}
}
@Override
public void update(Direction direction, org.eclipse.incquery.runtime.rete.tuple.Tuple updateElement) {
if (updateElement.getSize() == 2) {
Object source = updateElement.get(0);
Object target = updateElement.get(1);
if (direction == Direction.INSERT) {
graphDataSource.insertNode(source);
graphDataSource.insertNode(target);
graphDataSource.insertEdge(source, target);
}
if (direction == Direction.REVOKE) {
graphDataSource.deleteEdge(source, target);
if (((IncSCCAlg<Object>) transitiveClosureAlgorithm).isIsolated(source)) {
graphDataSource.deleteNode(source);
}
if (!source.equals(target) && ((IncSCCAlg<Object>) transitiveClosureAlgorithm).isIsolated(target)) {
graphDataSource.deleteNode(target);
}
}
}
}
@Override
public void clear() {
transitiveClosureAlgorithm.dispose();
graphDataSource = new Graph<Object>();
transitiveClosureAlgorithm = new IncSCCAlg<Object>(graphDataSource);
}
@Override
public void tupleInserted(Object source, Object target) {
org.eclipse.incquery.runtime.rete.tuple.Tuple tuple = new FlatTuple(source, target);
propagateUpdate(Direction.INSERT, tuple);
}
@Override
public void tupleDeleted(Object source, Object target) {
org.eclipse.incquery.runtime.rete.tuple.Tuple tuple = new FlatTuple(source, target);
propagateUpdate(Direction.REVOKE, tuple);
}
@Override
protected void propagateUpdate(Direction direction, org.eclipse.incquery.runtime.rete.tuple.Tuple updateElement) {
super.propagateUpdate(direction, updateElement);
}
}