/******************************************************************************* * 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.incquery.runtime.rete.single; import java.util.ArrayList; import java.util.Collection; import org.eclipse.incquery.runtime.rete.index.MemoryIdentityIndexer; import org.eclipse.incquery.runtime.rete.index.MemoryNullIndexer; import org.eclipse.incquery.runtime.rete.index.ProjectionIndexer; import org.eclipse.incquery.runtime.rete.network.Direction; import org.eclipse.incquery.runtime.rete.network.ReteContainer; import org.eclipse.incquery.runtime.rete.network.StandardNode; import org.eclipse.incquery.runtime.rete.network.Supplier; import org.eclipse.incquery.runtime.rete.network.Tunnel; import org.eclipse.incquery.runtime.rete.tuple.Tuple; import org.eclipse.incquery.runtime.rete.tuple.TupleMask; import org.eclipse.incquery.runtime.rete.tuple.TupleMemory; import org.eclipse.incquery.runtime.rete.util.Options; /** * Ensures that no identical copies get to the output. Only one replica of each pattern substitution may traverse this * node. * * @author Gabor Bergmann */ public class UniquenessEnforcerNode extends StandardNode implements Tunnel { protected Collection<Supplier> parents; protected TupleMemory memory; public TupleMemory getMemory() { return memory; } protected MemoryNullIndexer memoryNullIndexer; protected MemoryIdentityIndexer memoryIdentityIndexer; protected final int tupleWidth; private final TupleMask nullMask; private final TupleMask identityMask; public UniquenessEnforcerNode(ReteContainer reteContainer, int tupleWidth) { super(reteContainer); parents = new ArrayList<Supplier>(); memory = new TupleMemory(); this.tupleWidth = tupleWidth; reteContainer.registerClearable(memory); nullMask = TupleMask.linear(0, tupleWidth); identityMask = TupleMask.identity(tupleWidth); // if (Options.employTrivialIndexers) { // memoryNullIndexer = new MemoryNullIndexer(reteContainer, tupleWidth, memory, this, this); // reteContainer.getLibrary().registerSpecializedProjectionIndexer(this, memoryNullIndexer); // memoryIdentityIndexer = new MemoryIdentityIndexer(reteContainer, tupleWidth, memory, this, this); // reteContainer.getLibrary().registerSpecializedProjectionIndexer(this, memoryIdentityIndexer); // } } @Override public void update(Direction direction, Tuple updateElement) { boolean change; if (direction == Direction.INSERT) { change = memory.add(updateElement); } else { // REVOKE try { change = memory.remove(updateElement); } catch (java.lang.NullPointerException ex) { // TODO UGLY, but will it find our problems? change = false; reteContainer .getNetwork() .getContext() .logError( "[INTERNAL ERROR] Duplicate deletion of " + updateElement + " was detected in UniquenessEnforcer " + this, ex); } } if (change) { propagateUpdate(direction, updateElement); // trivial projectionIndexers if (memoryIdentityIndexer != null) memoryIdentityIndexer.propagate(direction, updateElement); if (memoryNullIndexer != null) memoryNullIndexer.propagate(direction, updateElement); } } @Override public ProjectionIndexer constructIndex(TupleMask mask) { if (Options.employTrivialIndexers) { if (nullMask.equals(mask)) return getNullIndexer(); if (identityMask.equals(mask)) return getIdentityIndexer(); } return super.constructIndex(mask); } @Override public void pullInto(Collection<Tuple> collector) { collector.addAll(memory); } public MemoryNullIndexer getNullIndexer() { if (memoryNullIndexer == null) memoryNullIndexer = new MemoryNullIndexer(reteContainer, tupleWidth, memory, this, this); return memoryNullIndexer; } public MemoryIdentityIndexer getIdentityIndexer() { if (memoryIdentityIndexer == null) memoryIdentityIndexer = new MemoryIdentityIndexer(reteContainer, tupleWidth, memory, this, this); return memoryIdentityIndexer; } @Override public void appendParent(Supplier supplier) { parents.add(supplier); } @Override public void removeParent(Supplier supplier) { parents.remove(supplier); } @Override public Collection<Supplier> getParents() { return parents; } // // public void tearOff() { // for (Supplier parent : new LinkedList<Supplier>(parents) ) // { // network.disconnectAndDesynchronize(parent, this); // } // } // // /** // * @return the dirty // */ // public boolean isDirty() { // return dirty; // } // // /** // * @param dirty the dirty to set // */ // public void setDirty(boolean dirty) { // this.dirty = dirty; // } }