Added support for getRecords method
[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_p_ZOOM_record_p;
10 import org.yaz4j.jni.SWIGTYPE_p_ZOOM_resultset_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         
88         SWIGTYPE_p_p_ZOOM_record_p recs = yaz4jlib.new_zoomRecordArray(count);
89         yaz4jlib.ZOOM_resultset_records(resultSet, recs, start, count);
90         
91         for (int i = 0; i < count; i++) {
92                 SWIGTYPE_p_ZOOM_record_p record = yaz4jlib.zoomRecordArray_getitem(recs, i);
93                 if (record == null) {
94                         continue;
95                 }
96                 
97                 int errorCode = yaz4jlib.ZOOM_record_error(record, null, null, null);
98             if (errorCode != 0) {
99               throw new ZoomException("Record excpetion, code " + errorCode);
100             }
101             
102             out.add(new Record(record, this));
103         }
104
105     return out;
106   }
107
108   @Override
109   public Iterator<Record> iterator() {
110     return new Iterator<Record>() {
111       private long cur;
112       @Override
113       public boolean hasNext() {
114         return cur < size;
115       }
116
117       @Override
118       public Record next() {
119         try {
120           return getRecord(cur++);
121         } catch (ZoomException ze) {
122           throw new NoSuchElementException(ze.getMessage());
123         }
124       }
125
126       @Override
127       public void remove() {
128         throw new UnsupportedOperationException("remove operation not supported");
129       }
130     };
131   }
132
133   public ResultSet sort(String type, String spec) throws ZoomException {
134     int ret = yaz4jlib.ZOOM_resultset_sort1(resultSet, type, spec);
135     if (ret != 0) throw new ZoomException("Sorting resultset failed");
136     return this;
137   }
138
139   public long getHitCount() {
140     return size;
141   }
142
143   void _dispose() {
144     if (!disposed) {
145       yaz4jlib.ZOOM_resultset_destroy(resultSet);
146       resultSet = null;
147       conn = null;
148       disposed = true;
149     }
150   }
151 }