Source code: nl/aidministrator/rdf/ral/rdbms/RecursiveSQLResourceIterator.java
1 /* Sesame - Storage and Querying architecture for RDF and RDF Schema
2 * Copyright (C) 2002 Aidministrator Nederland b.v.
3 *
4 * Contact:
5 * Aidministrator Nederland b.v.
6 * Julianaplein 14b
7 * 3817 CS Amersfoort
8 * The Netherlands
9 * tel. +31(0)33 4659987
10 * fax. +31(0)33 4659987
11 * sesame@aidministrator.nl
12 *
13 * http://www.aidministrator.nl/
14 *
15 * This library is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU Lesser General Public
17 * License as published by the Free Software Foundation; either
18 * version 2.1 of the License, or (at your option) any later version.
19 *
20 * This library is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * Lesser General Public License for more details.
24 *
25 * You should have received a copy of the GNU Lesser General Public
26 * License along with this library; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 */
29
30 package nl.aidministrator.rdf.ral.rdbms;
31
32 import nl.aidministrator.rdf.ral.ResourceIterator;
33 import nl.aidministrator.rdf.sail.model.*;
34 import java.util.*;
35 import java.sql.*;
36
37 /**
38 * A ResourceIterator that executes SQL queries recursively by re-inserting
39 * part of the query's results into the query. The query should contain EXACTLY
40 * ONE IN-parameter (i.e. there is one '?' in the query) and the ResultSet
41 * should contain the following columns: id (int), namespace (String) and
42 * localname (String). The first value (the id) will be re-inserted into the
43 * query.
44 *
45 * @author Peter van 't Hof
46 * @version 1.4, 01/02/02
47 */
48 public class RecursiveSQLResourceIterator implements ResourceIterator {
49
50 /*-----------+
51 | Variables |
52 +-----------*/
53
54 /**
55 * Connection to the database. */
56 protected Connection _databaseCon;
57 /**
58 * The query in the form of a PreparedStatement. */
59 protected PreparedStatement _statement;
60 /**
61 * Queue containing the results. */
62 protected Vector _resultsQueue;
63
64 /**
65 * Stores Resources that have already been iterated. This prevents looping
66 * of the iterator and therefore supports multiple inheritance and loops
67 * in the class or property hierarchy.
68 */
69 protected Set _iterated;
70
71 /*-------------+
72 | Constructors |
73 +-------------*/
74
75 /**
76 * Constructor.
77 *
78 * @param databaseCon connection to the repository
79 * @param query query to execute
80 * @param initialResource initial resource who is returned first. Its id is
81 * then inserted in the query.
82 */
83 public RecursiveSQLResourceIterator(Connection databaseCon, String query, IdResource initialResource)
84 throws SQLException {
85 _databaseCon = databaseCon;
86 _statement = _databaseCon.prepareStatement(query);
87 _resultsQueue = new Vector();
88 _iterated = new HashSet();
89 _add(initialResource);
90 }
91
92 /*--------+
93 | Methods |
94 +--------*/
95
96 private void _add(Resource resource) {
97 _resultsQueue.add(resource);
98 _iterated.add(resource);
99 }
100
101 private void _fillQueue(int value) {
102 try {
103 _statement.setInt(1, value);
104 ResultSet rs = _statement.executeQuery();
105
106 while (rs.next()) {
107 IdResource resource = new IdResource(rs.getInt(1), rs.getString(2), rs.getString(3));
108
109 if (!_iterated.contains(resource)) {
110 _add(resource);
111 }
112 }
113 rs.close();
114 }
115 catch (SQLException e) {
116 // FIXME: should throw a RalException
117
118 System.err.println("SQLException in _fillQueue(int)...");
119 }
120 }
121
122 public boolean hasNext() {
123 return !_resultsQueue.isEmpty();
124 }
125
126 /**
127 * Gets the next result.
128 *
129 * @exception NoSuchElementException If there are no more results
130 * available.
131 */
132 public Value next() {
133 if (hasNext()) {
134 IdResource result = (IdResource)_resultsQueue.remove(0);
135
136 _fillQueue(result.getId());
137
138 if (!hasNext()) { // Close connection if there aren 't any results left.
139 close();
140 }
141 return result;
142 }
143 else {
144 throw new NoSuchElementException("No more resources...");
145 }
146 }
147
148 public void close() {
149 _resultsQueue.clear();
150
151 try {
152 if (_statement != null) {
153 _statement.close();
154 }
155 _databaseCon.close();
156 }
157 catch (SQLException e) {
158 // FIXME: should throw a RalException
159
160 System.err.println("SQLException in close()...");
161 }
162 }
163
164 /**
165 * Called by the garbage collector on SQLValueIterator when garbage
166 * collection determines that there are no more references to the
167 * SQLValueIterator.
168 */
169 protected void finalize() {
170 close();
171 }
172 }