001: /******************************************************************
002: * File: LPTopGoalIterator.java
003: * Created by: Dave Reynolds
004: * Created on: 21-Jul-2003
005: *
006: * (c) Copyright 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
007: * [See end of file]
008: * $Id: LPTopGoalIterator.java,v 1.13 2008/01/02 12:06:16 andy_seaborne Exp $
009: *****************************************************************/package com.hp.hpl.jena.reasoner.rulesys.impl;
010:
011: import java.util.NoSuchElementException;
012:
013: import com.hp.hpl.jena.reasoner.rulesys.BackwardRuleInfGraphI;
014: import com.hp.hpl.jena.util.iterator.ClosableIterator;
015:
016: import java.util.*;
017:
018: /**
019: * Wraps up the results an LP rule engine instance into a conventional
020: * iterator. Ensures that the engine is closed and detached from the
021: * inference graph if the iterator hits the end of the result set.
022: *
023: * @author <a href="mailto:der@hplb.hpl.hp.com">Dave Reynolds</a>
024: * @version $Revision: 1.13 $ on $Date: 2008/01/02 12:06:16 $
025: */
026: public class LPTopGoalIterator implements ClosableIterator,
027: LPInterpreterContext {
028: /** The next result to be returned, or null if we have finished */
029: Object lookAhead;
030:
031: /** The parent backward chaining engine - nulled on close */
032: LPInterpreter interpreter;
033:
034: /** The parent InfGraph -- retained on close to allow CME detection */
035: BackwardRuleInfGraphI infgraph;
036:
037: /** The set of choice points that the top level interpter is waiting for */
038: protected Set choicePoints = new HashSet();
039:
040: /** The choice point most recently notified as ready to run. */
041: protected ConsumerChoicePointFrame nextToRun;
042:
043: /** set to true if we should be able to usefully run */
044: protected boolean isReady = true;
045:
046: /** set to true if at least one branch has block so an active readiness check is required */
047: protected boolean checkReadyNeeded = false;
048:
049: /** True if the iteration has started */
050: boolean started = false;
051:
052: /** Version stamp of the graph when we start */
053: protected int initialVersion;
054:
055: /**
056: * Constructor. Wraps a top level goal state as an iterator
057: */
058: public LPTopGoalIterator(LPInterpreter engine) {
059: this .interpreter = engine;
060: infgraph = engine.getEngine().getInfGraph();
061: initialVersion = infgraph.getVersion();
062: // engine.setState(this);
063: engine.setTopInterpreter(this );
064: }
065:
066: /**
067: * Find the next result in the goal state and put it in the
068: * lookahead buffer.
069: */
070: private synchronized void moveForward() {
071: checkClosed();
072: LPBRuleEngine lpEngine = interpreter.getEngine();
073: synchronized (lpEngine) {
074: // LogFactory.getLog( getClass() ).debug( "Entering moveForward sync block on " + interpreter.getEngine() );
075:
076: started = true;
077: // LogFactory.getLog( getClass() ).debug( "interpreter = " + interpreter );
078:
079: lookAhead = interpreter.next();
080: if (lookAhead == StateFlag.FAIL) {
081: if (choicePoints.isEmpty()) {
082: // Nothing left to try
083: close();
084: } else {
085: // Some options open, continue pumping
086: nextToRun = null;
087: lpEngine.pump(this );
088: if (nextToRun == null) {
089: // Reached final closure
090: close();
091: } else {
092: interpreter.setState(nextToRun);
093: moveForward();
094: }
095: }
096: }
097: // LogFactory.getLog( getClass() ).debug( "Leaving moveForward sync block " );
098:
099: }
100: }
101:
102: /** Notify this context that a brach was suspended awaiting futher
103: * results from the given generator. */
104: public void notifyBlockedOn(ConsumerChoicePointFrame ccp) {
105: choicePoints.add(ccp);
106: checkReadyNeeded = true;
107: }
108:
109: /**
110: * Notify this context that the given choice point has terminated
111: * and can be remove from the wait list.
112: */
113: public void notifyFinished(ConsumerChoicePointFrame ccp) {
114: choicePoints.remove(ccp);
115: checkReadyNeeded = true;
116: }
117:
118: /**
119: * Directly set that this generator is ready (because the generating
120: * for one of its generatingCPs has produced new results).
121: */
122: public void setReady(ConsumerChoicePointFrame ccp) {
123: nextToRun = ccp;
124: isReady = true;
125: checkReadyNeeded = false;
126: }
127:
128: /**
129: * Return true if the iterator is ready to be scheduled (i.e. it is not
130: * known to be complete and not known to be waiting for a dependent generator).
131: */
132: public boolean isReady() {
133: if (checkReadyNeeded) {
134: isReady = false;
135: for (Iterator i = choicePoints.iterator(); i.hasNext();) {
136: ConsumerChoicePointFrame ccp = (ConsumerChoicePointFrame) i
137: .next();
138: if (ccp.isReady()) {
139: if (nextToRun == null) {
140: nextToRun = ccp;
141: }
142: isReady = true;
143: break;
144: }
145: }
146: checkReadyNeeded = false;
147: return isReady;
148: } else {
149: return isReady;
150: }
151: }
152:
153: /**
154: * @see com.hp.hpl.jena.util.iterator.ClosableIterator#close()
155: */
156: public synchronized void close() {
157: if (interpreter != null) {
158: synchronized (interpreter.getEngine()) {
159: // LogFactory.getLog( getClass() ).debug( "Entering close sync block on " + interpreter.getEngine() );
160:
161: // Check for any dangling generators which are complete
162: interpreter.getEngine().checkForCompletions();
163: // Close this top goal
164: lookAhead = null;
165: //LogFactory.getLog( getClass() ).debug( "Nulling and closing LPTopGoalIterator " + interpreter );
166: interpreter.close();
167: // was TEMP experiment: interpreter.getEngine().detach(interpreter);
168: interpreter = null;
169: isReady = false;
170: checkReadyNeeded = false;
171: nextToRun = null;
172: // choicePoints = null; // disabled to prevent async close causing problems
173: //LogFactory.getLog( getClass() ).debug( "Leaving close sync block " );
174: }
175: }
176: }
177:
178: /**
179: * @see java.util.Iterator#hasNext()
180: */
181: public boolean hasNext() {
182: checkCME();
183: if (!started)
184: moveForward();
185: return (lookAhead != null);
186: }
187:
188: /**
189: * @see java.util.Iterator#next()
190: */
191: public Object next() {
192: checkCME();
193: if (!started)
194: moveForward();
195: if (lookAhead == null) {
196: throw new NoSuchElementException(
197: "Overran end of LP result set");
198: }
199: Object result = lookAhead;
200: moveForward();
201: return result;
202: }
203:
204: /**
205: * Check that the iterator has either cleanly closed or
206: * the version stamp is still valid
207: */
208: private void checkCME() {
209: if (initialVersion != infgraph.getVersion()) {
210: throw new ConcurrentModificationException();
211: }
212: }
213:
214: /**
215: * Check if the iterator has been closed and so we can't move forward safely
216: */
217: private void checkClosed() {
218: if (interpreter == null || interpreter.getEngine() == null) {
219: throw new ConcurrentModificationException(
220: "Due to closed iterator");
221: }
222: }
223:
224: /**
225: * @see java.util.Iterator#remove()
226: */
227: public void remove() {
228: throw new UnsupportedOperationException();
229: }
230:
231: }
232:
233: /*
234: (c) Copyright 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
235: All rights reserved.
236:
237: Redistribution and use in source and binary forms, with or without
238: modification, are permitted provided that the following conditions
239: are met:
240:
241: 1. Redistributions of source code must retain the above copyright
242: notice, this list of conditions and the following disclaimer.
243:
244: 2. Redistributions in binary form must reproduce the above copyright
245: notice, this list of conditions and the following disclaimer in the
246: documentation and/or other materials provided with the distribution.
247:
248: 3. The name of the author may not be used to endorse or promote products
249: derived from this software without specific prior written permission.
250:
251: THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
252: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
253: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
254: IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
255: INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
256: NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
257: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
258: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
259: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
260: THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
261: */
|