/******************************************************************************* * 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.index; import java.util.Collection; import org.eclipse.incquery.runtime.rete.network.Direction; import org.eclipse.incquery.runtime.rete.network.ReteContainer; import org.eclipse.incquery.runtime.rete.tuple.Tuple; /** * Propagates all substitutions arriving at the PRIMARY slot if and only if (a matching substitution on the SECONDARY is * present) xor (NEGATIVE). * * The negative parameter specifies whether this node checks for existence or non-existence. * * @author Gabor Bergmann */ public class ExistenceNode extends DualInputNode { protected boolean negative; /** * @param reteContainer * @param primarySlot * @param secondarySlot * @param negative * if false, act as axistence checker, otherwise a nonexistence-checker */ public ExistenceNode(ReteContainer reteContainer, IterableIndexer primarySlot, Indexer secondarySlot, boolean negative) { super(reteContainer, primarySlot, secondarySlot, null); this.negative = negative; } @Override public Tuple calibrate(Tuple primary, Tuple secondary) { return primary; } @Override public void notifyUpdate(Side side, Direction direction, Tuple updateElement, Tuple signature, boolean change) { switch (side) { case PRIMARY: if ((retrieveOpposites(side, signature) != null) ^ negative) propagateUpdate(direction, updateElement); break; case SECONDARY: if (change) { Collection<Tuple> opposites = retrieveOpposites(side, signature); if (opposites != null) for (Tuple opposite : opposites) { propagateUpdate((negative ? direction.opposite() : direction), opposite); } } break; case BOTH: // in case the slots coincide, // negative --> always empty // !positive --> identity if (!negative) { propagateUpdate(direction, updateElement); } break; } } @Override public void pullInto(Collection<Tuple> collector) { reteContainer.flushUpdates(); for (Tuple signature : primarySlot.getSignatures()) { Collection<Tuple> primaries = primarySlot.get(signature); // not null due to the contract of // IterableIndex.getSignatures() Collection<Tuple> opposites = secondarySlot.get(signature); if ((opposites != null) ^ negative) collector.addAll(primaries); } } }