/******************************************************************************* * 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.construction; import org.eclipse.incquery.runtime.rete.boundary.AbstractEvaluator; import org.eclipse.incquery.runtime.rete.boundary.PredicateEvaluatorNode; import org.eclipse.incquery.runtime.rete.boundary.ReteBoundary; import org.eclipse.incquery.runtime.rete.index.DualInputNode; import org.eclipse.incquery.runtime.rete.index.Indexer; import org.eclipse.incquery.runtime.rete.index.IterableIndexer; import org.eclipse.incquery.runtime.rete.matcher.ReteEngine; import org.eclipse.incquery.runtime.rete.network.Library; import org.eclipse.incquery.runtime.rete.network.Network; import org.eclipse.incquery.runtime.rete.network.Receiver; import org.eclipse.incquery.runtime.rete.network.ReteContainer; import org.eclipse.incquery.runtime.rete.network.Supplier; import org.eclipse.incquery.runtime.rete.remote.Address; import org.eclipse.incquery.runtime.rete.single.EqualityFilterNode; import org.eclipse.incquery.runtime.rete.single.InequalityFilterNode; import org.eclipse.incquery.runtime.rete.single.TransitiveClosureNode; import org.eclipse.incquery.runtime.rete.single.TrimmerNode; import org.eclipse.incquery.runtime.rete.tuple.FlatTuple; import org.eclipse.incquery.runtime.rete.tuple.LeftInheritanceTuple; import org.eclipse.incquery.runtime.rete.tuple.Tuple; import org.eclipse.incquery.runtime.rete.tuple.TupleMask; import org.eclipse.incquery.runtime.rete.util.Options; /** * The buildable interface of a rete container. * * @author Bergmann Gábor * */ public class ReteContainerBuildable<PatternDescription> implements Buildable<PatternDescription, Address<? extends Supplier>, Address<? extends Receiver>> { protected Library library; protected ReteContainer targetContainer; protected Network reteNet; protected ReteBoundary<PatternDescription> boundary; protected ReteEngine<PatternDescription> engine; protected boolean headAttached = false; /** * Constructs the builder attached to a specified container. Prerequisite: engine has its network and boundary * fields initialized. * * @param targetContainer */ public ReteContainerBuildable(ReteEngine<PatternDescription> engine, ReteContainer targetContainer) { super(); this.engine = engine; this.reteNet = engine.getReteNet(); this.boundary = engine.getBoundary(); this.targetContainer = targetContainer; this.library = targetContainer.getLibrary(); this.headAttached = false; } /** * Constructs the builder attached to the head container. Prerequisite: engine has its network and boundary fields * initialized */ public ReteContainerBuildable(ReteEngine<PatternDescription> engine) { super(); this.engine = engine; this.reteNet = engine.getReteNet(); this.boundary = engine.getBoundary(); this.targetContainer = reteNet.getHeadContainer(); this.library = targetContainer.getLibrary(); this.headAttached = true; } public void reinitialize() { this.reteNet = engine.getReteNet(); this.boundary = engine.getBoundary(); this.targetContainer = headAttached ? reteNet.getHeadContainer() : reteNet.getNextContainer(); this.library = targetContainer.getLibrary(); } public Stub<Address<? extends Supplier>> buildTrimmer(Stub<Address<? extends Supplier>> stub, TupleMask trimMask) { Address<TrimmerNode> bodyTerminator = library.accessTrimmerNode(stub.getHandle(), trimMask); return new Stub<Address<? extends Supplier>>(stub, trimMask.transform(stub.getVariablesTuple()), bodyTerminator); } public void buildConnection(Stub<Address<? extends Supplier>> stub, Address<? extends Receiver> collector) { reteNet.connectRemoteNodes(stub.getHandle(), collector, true); boundary.registerParentStubForReceiver(collector, stub); } public Stub<Address<? extends Supplier>> buildStartStub(Object[] constantValues, Object[] constantNames) { return new Stub<Address<? extends Supplier>>(new FlatTuple(constantNames), library.accessConstantNode(boundary .wrapTuple(new FlatTuple(constantValues)))); } public Stub<Address<? extends Supplier>> buildEqualityChecker(Stub<Address<? extends Supplier>> stub, int[] indices) { Address<EqualityFilterNode> checker = library.accessEqualityFilterNode(stub.getHandle(), indices); return new Stub<Address<? extends Supplier>>(stub, checker); } public Stub<Address<? extends Supplier>> buildInjectivityChecker(Stub<Address<? extends Supplier>> stub, int subject, int[] inequalIndices) { Address<InequalityFilterNode> checker = library.accessInequalityFilterNode(stub.getHandle(), subject, new TupleMask(inequalIndices, stub.getVariablesTuple().getSize())); return new Stub<Address<? extends Supplier>>(stub, checker); } @Override public Stub<Address<? extends Supplier>> buildTransitiveClosure(Stub<Address<? extends Supplier>> stub) { Address<TransitiveClosureNode> checker = library.accessTransitiveClosureNode(stub.getHandle()); return new Stub<Address<? extends Supplier>>(stub, checker); } public Stub<Address<? extends Supplier>> patternCallStub(Tuple nodes, PatternDescription supplierKey) throws RetePatternBuildException { return new Stub<Address<? extends Supplier>>(nodes, boundary.accessProduction(supplierKey)); } public Stub<Address<? extends Supplier>> instantiationTransitiveStub(Tuple nodes) { return new Stub<Address<? extends Supplier>>(nodes, boundary.accessInstantiationTransitiveRoot()); } public Stub<Address<? extends Supplier>> instantiationDirectStub(Tuple nodes) { return new Stub<Address<? extends Supplier>>(nodes, boundary.accessInstantiationRoot()); } public Stub<Address<? extends Supplier>> generalizationTransitiveStub(Tuple nodes) { return new Stub<Address<? extends Supplier>>(nodes, boundary.accessGeneralizationTransitiveRoot()); } public Stub<Address<? extends Supplier>> generalizationDirectStub(Tuple nodes) { return new Stub<Address<? extends Supplier>>(nodes, boundary.accessGeneralizationRoot()); } public Stub<Address<? extends Supplier>> containmentTransitiveStub(Tuple nodes) { return new Stub<Address<? extends Supplier>>(nodes, boundary.accessContainmentTransitiveRoot()); } public Stub<Address<? extends Supplier>> containmentDirectStub(Tuple nodes) { return new Stub<Address<? extends Supplier>>(nodes, boundary.accessContainmentRoot()); } public Stub<Address<? extends Supplier>> binaryEdgeTypeStub(Tuple nodes, Object supplierKey) { return new Stub<Address<? extends Supplier>>(nodes, boundary.accessBinaryEdgeRoot(supplierKey)); } public Stub<Address<? extends Supplier>> ternaryEdgeTypeStub(Tuple nodes, Object supplierKey) { return new Stub<Address<? extends Supplier>>(nodes, boundary.accessTernaryEdgeRoot(supplierKey)); } public Stub<Address<? extends Supplier>> unaryTypeStub(Tuple nodes, Object supplierKey) { return new Stub<Address<? extends Supplier>>(nodes, boundary.accessUnaryRoot(supplierKey)); } public Stub<Address<? extends Supplier>> buildBetaNode(Stub<Address<? extends Supplier>> primaryStub, Stub<Address<? extends Supplier>> sideStub, TupleMask primaryMask, TupleMask sideMask, TupleMask complementer, boolean negative) { Address<? extends IterableIndexer> primarySlot = library.accessProjectionIndexer(primaryStub.getHandle(), primaryMask); Address<? extends Indexer> sideSlot = library.accessProjectionIndexer(sideStub.getHandle(), sideMask); if (negative) { Address<? extends DualInputNode> checker = library.accessExistenceNode(primarySlot, sideSlot, true); return new Stub<Address<? extends Supplier>>(primaryStub, checker); } else { Address<? extends DualInputNode> checker = library.accessJoinNode(primarySlot, sideSlot, complementer); Tuple newCalibrationPattern = complementer.combine(primaryStub.getVariablesTuple(), sideStub.getVariablesTuple(), Options.enableInheritance, true); return new Stub<Address<? extends Supplier>>(primaryStub, sideStub, newCalibrationPattern, checker); } } public Stub<Address<? extends Supplier>> buildCounterBetaNode(Stub<Address<? extends Supplier>> primaryStub, Stub<Address<? extends Supplier>> sideStub, TupleMask primaryMask, TupleMask originalSideMask, TupleMask complementer, Object aggregateResultCalibrationElement) { Address<? extends IterableIndexer> primarySlot = library.accessProjectionIndexer(primaryStub.getHandle(), primaryMask); Address<? extends Indexer> sideSlot = library.accessCountOuterIndexer(sideStub.getHandle(), originalSideMask); Address<? extends DualInputNode> checker = library.accessJoinNode(primarySlot, sideSlot, TupleMask.selectSingle(originalSideMask.indices.length, originalSideMask.indices.length + 1)); Object[] newCalibrationElement = { aggregateResultCalibrationElement }; Tuple newCalibrationPattern = new LeftInheritanceTuple(primaryStub.getVariablesTuple(), newCalibrationElement); Stub<Address<? extends Supplier>> result = new Stub<Address<? extends Supplier>>(primaryStub, newCalibrationPattern, checker); return result; } public Stub<Address<? extends Supplier>> buildCountCheckBetaNode(Stub<Address<? extends Supplier>> primaryStub, Stub<Address<? extends Supplier>> sideStub, TupleMask primaryMask, TupleMask originalSideMask, int resultPositionInSignature) { Address<? extends IterableIndexer> primarySlot = library.accessProjectionIndexer(primaryStub.getHandle(), primaryMask); Address<? extends Indexer> sideSlot = library.accessCountOuterIdentityIndexer(sideStub.getHandle(), originalSideMask, resultPositionInSignature); Address<? extends DualInputNode> checker = library.accessJoinNode(primarySlot, sideSlot, TupleMask.empty(originalSideMask.indices.length + 1)); Tuple newCalibrationPattern = primaryStub.getVariablesTuple(); Stub<Address<? extends Supplier>> result = new Stub<Address<? extends Supplier>>(primaryStub, newCalibrationPattern, checker); return result; } public Stub<Address<? extends Supplier>> buildPredicateChecker(AbstractEvaluator evaluator, Integer rhsIndex, int[] affectedIndices, Stub<Address<? extends Supplier>> stub) { PredicateEvaluatorNode ten = new PredicateEvaluatorNode(engine, targetContainer, rhsIndex, affectedIndices, stub.getVariablesTuple().getSize(), evaluator); Address<PredicateEvaluatorNode> checker = Address.of(ten); reteNet.connectRemoteNodes(stub.getHandle(), checker, true); Stub<Address<? extends Supplier>> result = new Stub<Address<? extends Supplier>>(stub, checker); return result; } /** * @return a buildable that potentially acts on a separate container */ public ReteContainerBuildable<PatternDescription> getNextContainer() { return new ReteContainerBuildable<PatternDescription>(engine, reteNet.getNextContainer()); } public Stub<Address<? extends Supplier>> buildScopeConstrainer(Stub<Address<? extends Supplier>> stub, boolean transitive, Object unwrappedContainer, int constrainedIndex) { Address<? extends Supplier> root = (transitive) ? boundary.accessContainmentTransitiveRoot() : boundary .accessContainmentRoot(); // bind the container element Address<? extends Supplier> filteredRoot = targetContainer.getLibrary().accessValueBinderFilterNode(root, 0/* container */, boundary.wrapElement(unwrappedContainer)); // build secondary indexer int[] secondaryIndices = { 1 /* contained element */}; Address<? extends Indexer> secondary = targetContainer.getLibrary().accessProjectionIndexer(filteredRoot, new TupleMask(secondaryIndices, 2)); // build primary indexer int[] primaryIndices = { constrainedIndex }; TupleMask primaryMask = new TupleMask(primaryIndices, stub.getVariablesTuple().getSize()); Address<? extends IterableIndexer> primary = targetContainer.getLibrary().accessProjectionIndexer( stub.getHandle(), primaryMask); // build checker stub = new Stub<Address<? extends Supplier>>(stub, targetContainer.getLibrary().accessExistenceNode(primary, secondary, false)); return stub; } public Address<? extends Receiver> patternCollector(PatternDescription pattern) throws RetePatternBuildException { return engine.getBoundary().createProductionInternal(pattern); } /** * No need to distinguish */ public ReteContainerBuildable<PatternDescription> putOnTab(PatternDescription effort) { return this; } }