e2df507fa0a563288a6078950d8ec58dc338db15
[yaz4j-moved-to-github.git] / src / main / java / org / yaz4j / ResultSet.java
1 package org.yaz4j;
2
3 import java.util.ArrayList;
4 import java.util.Iterator;
5 import java.util.List;
6 import java.util.NoSuchElementException;
7 import org.yaz4j.exception.ZoomException;
8 import org.yaz4j.jni.SWIGTYPE_p_ZOOM_record_p;
9 import org.yaz4j.jni.SWIGTYPE_p_ZOOM_resultset_p;
10 import org.yaz4j.jni.SWIGTYPE_p_p_ZOOM_record_p;
11 import org.yaz4j.jni.yaz4jlib;
12
13 /**
14  * This class represents a "buffered handle" to the result set created on the
15  * server and thus retrieving records may invlove a request to the server if
16  * those records are not locally cached. Details on how to configure the retrieval
17  * (present) process are available in the YAZ manual
18  *
19  * @see <a href="http://www.indexdata.com/yaz/doc/zoom.resultsets.html">YAZ ZOOM result sets</a>
20  *
21  * Becacuse of the server misbehaviour or errors during retrieval the
22  * "getRecord" method may either return null or throw exceptions, even when the
23  * index of retrieved records lies within the bounds of the set. Client
24  * code should be prepared for such situations.
25  *
26  * This class implements the iterable interface and as such can be used within
27  * foreach loops, it's important to note however that in this case the errors
28  * during retrieval will be masked with standard NoSuchElementExceptions
29  *
30  * @author jakub
31  */
32 public class ResultSet implements Iterable<Record> {
33   //for GC refcount
34
35   private Connection conn;
36   private SWIGTYPE_p_ZOOM_resultset_p resultSet;
37   private long size = 0;
38   private boolean disposed = false;
39
40   ResultSet(SWIGTYPE_p_ZOOM_resultset_p resultSet, Connection conn) {
41     this.resultSet = resultSet;
42     size = yaz4jlib.ZOOM_resultset_size(this.resultSet);
43     this.conn = conn;
44   }
45
46   @Override
47   public void finalize() {
48     this._dispose();
49   }
50
51   /**
52    * Read option by name.
53    * @param name option name
54    * @return option value
55    */
56   public String option(String name) {
57     return yaz4jlib.ZOOM_resultset_option_get(resultSet, name);
58   }
59
60   /**
61    * Write option with a given name.
62    * @param name option name
63    * @param value option value
64    * @return result set (self) for chainability
65    */
66   public ResultSet option(String name, String value) {
67     yaz4jlib.ZOOM_resultset_option_set(resultSet, name, value);
68     return this;
69   }
70
71   public Record getRecord(long index) throws ZoomException {
72     SWIGTYPE_p_ZOOM_record_p record =
73       yaz4jlib.ZOOM_resultset_record(resultSet, index);
74     //may be out of range or unsupported syntax
75     if (record == null) {
76       return null;
77     }
78     int errorCode = yaz4jlib.ZOOM_record_error(record, null, null, null);
79     if (errorCode != 0) {
80       throw new ZoomException("Record excpetion, code " + errorCode);
81     }
82     return new Record(record, this);
83   }
84   
85   public List<Record> getRecords(long start, int count) throws ZoomException {
86     List<Record> out = new ArrayList<Record>(count);
87     SWIGTYPE_p_p_ZOOM_record_p recs = yaz4jlib.new_zoomRecordArray(count);
88     yaz4jlib.ZOOM_resultset_records(resultSet, recs, start, count);
89     for (int i = 0; i < count; i++) {
90       SWIGTYPE_p_ZOOM_record_p record =
91         yaz4jlib.zoomRecordArray_getitem(recs, i);
92       if (record == null) {
93         continue;
94       }
95       int errorCode = yaz4jlib.ZOOM_record_error(record, null, null, null);
96       if (errorCode != 0) {
97         throw new ZoomException("Record excpetion, code " + errorCode);
98       }
99       out.add(new Record(record, this));
100     }
101     return out;
102   }
103
104   @Override
105   public Iterator<Record> iterator() {
106     return new Iterator<Record>() {
107       private long cur;
108       @Override
109       public boolean hasNext() {
110         return cur < size;
111       }
112
113       @Override
114       public Record next() {
115         try {
116           return getRecord(cur++);
117         } catch (ZoomException ze) {
118           throw new NoSuchElementException(ze.getMessage());
119         }
120       }
121
122       @Override
123       public void remove() {
124         throw new UnsupportedOperationException("remove operation not supported");
125       }
126     };
127   }
128
129   public ResultSet sort(String type, String spec) throws ZoomException {
130     int ret = yaz4jlib.ZOOM_resultset_sort1(resultSet, type, spec);
131     if (ret != 0) throw new ZoomException("Sorting resultset failed");
132     return this;
133   }
134
135   public long getHitCount() {
136     return size;
137   }
138
139   void _dispose() {
140     if (!disposed) {
141       yaz4jlib.ZOOM_resultset_destroy(resultSet);
142       resultSet = null;
143       conn = null;
144       disposed = true;
145     }
146   }
147 }