001: /******************************************************************
002: * File: ConsumerChoicePoint.java
003: * Created by: Dave Reynolds
004: * Created on: 07-Aug-2003
005: *
006: * (c) Copyright 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
007: * [See end of file]
008: * $Id: ConsumerChoicePointFrame.java,v 1.12 2008/01/02 12:06:16 andy_seaborne Exp $
009: *****************************************************************/package com.hp.hpl.jena.reasoner.rulesys.impl;
010:
011: import com.hp.hpl.jena.graph.*;
012: import com.hp.hpl.jena.reasoner.rulesys.Node_RuleVariable;
013:
014: import java.util.*;
015:
016: /**
017: * Frame in the LPInterpreter's control stack used to represent matching
018: * to the results of a tabled predicate. Conventionally the system state which
019: * finds and tables the goal results is called the generator and states which
020: * require those results are called consumers.
021: * <p>
022: * This is used in the inner loop of the interpreter and so is a pure data structure
023: * not an abstract data type and assumes privileged access to the interpreter state.
024: * </p>
025: *
026: * @author <a href="mailto:der@hplb.hpl.hp.com">Dave Reynolds</a>
027: * @version $Revision: 1.12 $ on $Date: 2008/01/02 12:06:16 $
028: */
029: public class ConsumerChoicePointFrame extends GenericTripleMatchFrame
030: implements LPAgendaEntry, LPInterpreterState {
031:
032: /** The generator whose tabled results we are selecting over */
033: protected Generator generator;
034:
035: /** The index in the generator's result set that we have reached so far. */
036: protected int resultIndex;
037:
038: /** The preserved permanent registers for the pickled interpreter */
039: protected Node[] pVars;
040:
041: /** The preserved trail variables for the picked interpreter */
042: protected Node_RuleVariable[] trailVars;
043:
044: /** The preserved trail bound values for the picked interpreter */
045: protected Node[] trailValues;
046:
047: /** The length of the preserved trail */
048: protected int trailLength;
049:
050: /** The generator or top iterator we are producting results for */
051: protected LPInterpreterContext context;
052:
053: /**
054: * Constructor.
055: * @param interpreter the parent interpreter whose state is to be preserved here, its arg stack
056: * defines the parameters for the target goal
057: */
058: public ConsumerChoicePointFrame(LPInterpreter interpreter) {
059: init(interpreter);
060: }
061:
062: /**
063: * Initialize the choice point state.
064: * @param interpreter the parent interpreter whose state is to be preserved here, its arg stack
065: * defines the parameters for the target goal
066: */
067: public void init(LPInterpreter interpreter) {
068: super .init(interpreter);
069: context = interpreter.getContext();
070: generator = interpreter.getEngine().generatorFor(goal);
071: generator.addConsumer(this );
072: resultIndex = 0;
073: }
074:
075: /**
076: * Preserve the state of an interpreter into this frame.
077: */
078: public void preserveState(List trail) {
079: // Save the trail state
080: int trailLen = trail.size();
081: if (trailLen > trailLength) {
082: trailValues = new Node[trailLen];
083: trailVars = new Node_RuleVariable[trailLen];
084: }
085: trailLength = trailLen;
086: for (int i = 0; i < trailLen; i++) {
087: Node_RuleVariable var = (Node_RuleVariable) trail.get(i);
088: trailVars[i] = var;
089: trailValues[i] = var.getRawBoundValue();
090: }
091: // Save the permanent variables
092: Node[] currentPVars = envFrame.pVars;
093: if (currentPVars != null) {
094: if (pVars == null || pVars.length < currentPVars.length) {
095: pVars = new Node[currentPVars.length];
096: }
097: System.arraycopy(currentPVars, 0, pVars, 0,
098: currentPVars.length);
099: }
100: }
101:
102: /**
103: * Restore the state of an interpreter from this frame
104: */
105: public void restoreState(LPInterpreter interp) {
106: interp.unwindTrail(0);
107: for (int i = 0; i < trailLength; i++) {
108: interp.bind(trailVars[i], trailValues[i]);
109: }
110: if (pVars != null) {
111: System.arraycopy(pVars, 0, envFrame.pVars, 0, pVars.length);
112: }
113: }
114:
115: /**
116: * Find the next result triple and bind the result vars appropriately.
117: * @param interpreter the calling interpreter whose trail should be used
118: * @return FAIL if there are no more matches and the generator is closed, SUSPEND if
119: * there are no more matches but the generator could generate more, SATISFIED if
120: * a match has been found.
121: */
122: public synchronized StateFlag nextMatch(LPInterpreter interpreter) {
123: while (resultIndex < generator.results.size()) {
124: Triple result = (Triple) generator.results
125: .get(resultIndex++);
126: // Check if we have finished with this generator
127: if (resultIndex >= generator.results.size()
128: && generator.isComplete()) {
129: generator.removeConsumer(this );
130: }
131: if (bindResult(result, interpreter)) {
132: return StateFlag.SATISFIED;
133: }
134: }
135: if (generator.isComplete()) {
136: setFinished();
137: generator.removeConsumer(this );
138: return StateFlag.FAIL;
139: } else {
140: return StateFlag.SUSPEND;
141: }
142: }
143:
144: /**
145: * Return true if this choice point could usefully be restarted.
146: */
147: public boolean isReady() {
148: return generator.numResults() > resultIndex;
149: }
150:
151: /**
152: * Called by generator when there are more results available.
153: */
154: public void setReady() {
155: context.setReady(this );
156: }
157:
158: /**
159: * Notify that this consumer choice point has finished consuming all
160: * the results of a closed generator.
161: */
162: public void setFinished() {
163: context.notifyFinished(this );
164: }
165:
166: /**
167: * Reactivate this choice point to return new results.
168: */
169: public void pump() {
170: if (context instanceof Generator) {
171: ((Generator) context).pump(this );
172: } else {
173: // The top level iterator is in charge and will restore and run this choice point itself
174: }
175: }
176:
177: /**
178: * Return the generator associated with this entry (might be the entry itself)
179: */
180: public Generator getGenerator() {
181: return generator;
182: }
183:
184: /**
185: * Return the interpeter context which is reading the results of this consumer.
186: */
187: public LPInterpreterContext getConsumingContext() {
188: return context;
189: }
190:
191: }
192:
193: /*
194: (c) Copyright 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
195: All rights reserved.
196:
197: Redistribution and use in source and binary forms, with or without
198: modification, are permitted provided that the following conditions
199: are met:
200:
201: 1. Redistributions of source code must retain the above copyright
202: notice, this list of conditions and the following disclaimer.
203:
204: 2. Redistributions in binary form must reproduce the above copyright
205: notice, this list of conditions and the following disclaimer in the
206: documentation and/or other materials provided with the distribution.
207:
208: 3. The name of the author may not be used to endorse or promote products
209: derived from this software without specific prior written permission.
210:
211: THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
212: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
213: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
214: IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
215: INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
216: NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
217: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
218: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
219: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
220: THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
221: */
|