001: /*
002: * (c) Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
003: * All rights reserved.
004: *
005: *
006: */
007:
008: //=======================================================================
009: // Package
010: package com.hp.hpl.jena.db.impl;
011:
012: //=======================================================================
013: // Imports
014: import java.sql.*;
015:
016: import com.hp.hpl.jena.db.RDFRDBException;
017: import com.hp.hpl.jena.graph.*;
018: import com.hp.hpl.jena.shared.JenaException;
019: import com.hp.hpl.jena.vocabulary.RDF;
020:
021: import org.apache.commons.logging.Log;
022: import org.apache.commons.logging.LogFactory;
023:
024: //=======================================================================
025: /**
026: * Version of ResultSetIterator that extracts database rows as Triples from a reified statement table.
027: *
028: * @author hkuno. Based on ResultSetResource Iterator, by Dave Reynolds, HPLabs, Bristol <a href="mailto:der@hplb.hpl.hp.com">Dave Reynolds</a>
029: * @version $Revision: 1.13 $ on $Date: 2008/01/02 12:08:23 $
030: */
031: public class ResultSetReifIterator extends ResultSetIterator {
032:
033: /** The rdf model in which to instantiate any resources */
034: protected IDBID m_graphID;
035:
036: /** The database driver, used to access namespace and resource caches */
037: protected IPSet m_pset;
038:
039: /** Holds subject, predicate and object of current row */
040: protected Node m_subjNode;
041: protected Node m_predNode;
042: protected Node m_objNode;
043:
044: /** Statement URI of current row */
045: protected Node m_stmtURI;
046:
047: /** HasType flag is true if reified statement has type rdf:Statement */
048: protected boolean m_hasType;
049:
050: /** getTriples is true if this iterator should return all triples for the reified statement
051: * otherwise, reified statements are returned. */
052: protected boolean m_getTriples;
053:
054: /** a triple match over a reified table might return one property.
055: * m_propCol identifies the column number of the property to return.
056: * it ranges 1-4.
057: */
058: protected int m_propCol;
059:
060: /** a triple match over a reified table might specify an object value
061: * to match but no property. so, return all columns (properties)
062: * that match the specified object value.
063: */
064: protected Node m_matchObj;
065:
066: /** total number of fragments to generate for this row (ranges 1-4) */
067: protected int m_fragCount;
068:
069: /** number of remaining fragments to generate for this row (ranges 1-4) */
070: protected int m_fragRem;
071:
072: /** number of next fragment to generate (0-3 for subj, pred, obj, type). */
073: protected int m_nextFrag;
074:
075: static protected Log logger = LogFactory
076: .getLog(ResultSetReifIterator.class);
077:
078: // Constructor
079: public ResultSetReifIterator(IPSet p, boolean getTriples,
080: IDBID graphID) {
081: m_pset = p;
082: setGraphID(graphID);
083: m_getTriples = getTriples;
084: m_matchObj = null;
085: m_propCol = 0;
086: }
087:
088: public ResultSetReifIterator(IPSet p, char getProp, IDBID graphID) {
089: m_pset = p;
090: setGraphID(graphID);
091: m_getTriples = true;
092: m_matchObj = null;
093: if (getProp == 'S')
094: m_propCol = 1;
095: else if (getProp == 'P')
096: m_propCol = 2;
097: else if (getProp == 'O')
098: m_propCol = 3;
099: else if (getProp == 'T')
100: m_propCol = 4;
101: }
102:
103: public ResultSetReifIterator(IPSet p, Node getObj, IDBID graphID) {
104: m_pset = p;
105: setGraphID(graphID);
106: m_getTriples = true;
107: m_matchObj = getObj;
108: m_propCol = 0;
109: }
110:
111: /**
112: * Set m_graphID.
113: * @param gid is the id of the graph associated with this iterator.
114: */
115: public void setGraphID(IDBID gid) {
116: m_graphID = gid;
117: }
118:
119: /**
120: * Reset an existing iterator to scan a new result set.
121: * @param resultSet the result set being iterated over
122: * @param sourceStatement The source Statement to be cleaned up when the iterator finishes - return it to cache or close it if no cache
123: * @param cache The originating SQLcache to return the statement to, can be null
124: * @param opname The name of the original operation that lead to this statement, can be null if SQLCache is null
125: */
126: public void reset(ResultSet resultSet,
127: PreparedStatement sourceStatement, SQLCache cache,
128: String opname) {
129: super .reset(resultSet, sourceStatement, cache, opname);
130: }
131:
132: /**
133: * Extract the current row into a triple.
134: * Requires the row to be of the form:
135: * subject URI (String)
136: * predicate URI (String)
137: * object URI (String)
138: * object value (String)
139: * Object literal id (Object)
140: *
141: * The object of the triple can be either a URI, a simple literal (in
142: * which case it will just have an object value, or a complex literal
143: * (in which case both the object value and the object literal id
144: * columns may be populated.
145: */
146: protected void extractRow() throws SQLException {
147: int rx = 1;
148: ResultSet rs = m_resultSet;
149: String subj = rs.getString(1);
150: String pred = rs.getString(2);
151: String obj = rs.getString(3);
152:
153: m_stmtURI = m_pset.driver().RDBStringToNode(rs.getString(4));
154: m_hasType = rs.getString(5).equals("T");
155:
156: m_fragRem = 0;
157: if (m_hasType)
158: if ((m_matchObj == null)
159: || m_matchObj.equals(RDF.Nodes.Statement))
160: m_fragRem++;
161:
162: if (subj == null) {
163: m_subjNode = Node.NULL;
164: } else {
165: m_subjNode = m_pset.driver().RDBStringToNode(subj);
166: if ((m_matchObj == null) || m_matchObj.equals(m_subjNode))
167: m_fragRem++;
168: }
169: if (pred == null) {
170: m_predNode = Node.NULL;
171: } else {
172: m_predNode = m_pset.driver().RDBStringToNode(pred);
173: if ((m_matchObj == null) || m_matchObj.equals(m_predNode))
174: m_fragRem++;
175: }
176: if (obj == null) {
177: m_objNode = Node.NULL;
178: } else {
179: m_objNode = m_pset.driver().RDBStringToNode(obj);
180: if ((m_matchObj == null) || m_matchObj.equals(m_objNode))
181: m_fragRem++;
182: }
183: if (m_propCol > 0) {
184: m_nextFrag = m_propCol - 1;
185: m_fragCount = m_fragRem = 1;
186: } else {
187: m_nextFrag = 0;
188: m_fragCount = m_fragRem;
189: }
190: }
191:
192: /**
193: * Return triples for the current row, which should have already been extracted.
194: */
195: protected Object getRow() {
196: Triple t = null;
197:
198: if (m_getTriples == true) {
199: if (m_nextFrag == 0) {
200: if (!m_subjNode.equals(Node.NULL)
201: && ((m_matchObj == null) || m_matchObj
202: .equals(m_subjNode))) {
203: t = Triple.create(m_stmtURI, RDF.Nodes.subject,
204: m_subjNode);
205: m_fragRem--;
206: } else
207: m_nextFrag++;
208: }
209: if (m_nextFrag == 1) {
210: if (!m_predNode.equals(Node.NULL)
211: && ((m_matchObj == null) || m_matchObj
212: .equals(m_predNode))) {
213: t = Triple.create(m_stmtURI, RDF.Nodes.predicate,
214: m_predNode);
215: m_fragRem--;
216: } else
217: m_nextFrag++;
218: }
219: if (m_nextFrag == 2) {
220: if (!m_objNode.equals(Node.NULL)
221: && ((m_matchObj == null) || m_matchObj
222: .equals(m_objNode))) {
223: t = Triple.create(m_stmtURI, RDF.Nodes.object,
224: m_objNode);
225: m_fragRem--;
226: } else
227: m_nextFrag++;
228: }
229: if (m_nextFrag >= 3) {
230: if (m_hasType
231: && ((m_matchObj == null) || m_matchObj
232: .equals(RDF.Nodes.Statement))) {
233: t = Triple.create(m_stmtURI, RDF.Nodes.type,
234: RDF.Nodes.Statement);
235: m_fragRem--;
236: } else
237: throw new JenaException("Reified triple not found");
238: }
239: m_nextFrag++;
240: if (m_fragRem > 0)
241: m_prefetched = true;
242:
243: } else {
244: t = Triple.create(m_subjNode, m_predNode, m_objNode);
245: }
246:
247: return t;
248: }
249:
250: /**
251: * Return the true if the current row has a non-null subject.
252: */
253: protected boolean hasSubj() {
254: return m_subjNode != Node.NULL;
255: }
256:
257: /**
258: * Return the true if the current row has a non-null predicate.
259: */
260: protected boolean hasPred() {
261: return m_predNode != Node.NULL;
262: }
263:
264: /**
265: * Return the true if the current row has a non-null object.
266: */
267: protected boolean hasObj() {
268: return m_objNode != Node.NULL;
269: }
270:
271: /**
272: * Return the true if the current row has T (true) for hasType.
273: */
274: protected boolean hasType() {
275: return m_hasType;
276: }
277:
278: /**
279: * Return the number of (reification statement) fragments for the current row.
280: */
281: protected int getFragCount() {
282: return m_fragCount;
283: }
284:
285: /**
286: * Return the reifying URI for current row, which should have already been extracted.
287: */
288: protected Node getStmtURI() {
289: return m_stmtURI;
290: }
291:
292: /**
293: * Return the hasType value of current row, which should have already been extracted.
294: */
295: protected boolean getHasType() {
296: return m_hasType;
297: }
298:
299: /**
300: * Delete the current row, which should have already been extracted.
301: * Should only be used (carefully and) internally by db layer.
302: */
303: protected void deleteRow() {
304: try {
305: m_resultSet.deleteRow();
306: } catch (SQLException e) {
307: throw new RDFRDBException("Internal sql error", e);
308: }
309: }
310:
311: } // End class
312:
313: /*
314: * (c) Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008 Hewlett-Packard Development Company, LP
315: * All rights reserved.
316: *
317: * Redistribution and use in source and binary forms, with or without
318: * modification, are permitted provided that the following conditions
319: * are met:
320: * 1. Redistributions of source code must retain the above copyright
321: * notice, this list of conditions and the following disclaimer.
322: * 2. Redistributions in binary form must reproduce the above copyright
323: * notice, this list of conditions and the following disclaimer in the
324: * documentation and/or other materials provided with the distribution.
325: * 3. The name of the author may not be used to endorse or promote products
326: * derived from this software without specific prior written permission.
327:
328: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
329: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
330: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
331: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
332: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
333: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
334: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
335: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
336: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
337: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
338: */
|