001: /**
002: * Speedo: an implementation of JDO compliant personality on top of JORM generic
003: * I/O sub-system.
004: * Copyright (C) 2001-2004 France Telecom R&D
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: *
021: *
022: * Contact: speedo@objectweb.org
023: *
024: * Authors: S. Chassande-Barrioz
025: *
026: */package org.objectweb.speedo.query.jdo;
027:
028: import java.util.ArrayList;
029: import java.util.Collection;
030: import java.util.Collections;
031: import java.util.Iterator;
032: import java.util.List;
033: import java.util.ListIterator;
034: import java.util.NoSuchElementException;
035:
036: import javax.jdo.JDOUnsupportedOptionException;
037: import javax.jdo.JDOUserException;
038: import javax.jdo.PersistenceManager;
039:
040: import org.objectweb.medor.api.MedorException;
041: import org.objectweb.medor.tuple.api.TupleCollection;
042: import org.objectweb.speedo.api.SpeedoException;
043: import org.objectweb.util.monolog.api.BasicLevel;
044: import org.objectweb.util.monolog.api.Logger;
045:
046: /**
047: * is the result of a JDO query. The result is exported as a java.util.List.
048: * This implementation supports user class or persistent class as query result.
049: * This implementation does not supports simultaneous iterations.
050: *
051: * @author S.Chassande-Barrioz
052: */
053: public class JDOQueryResultList extends JDOQueryResultCommon implements
054: List {
055:
056: /**
057: * if all values are loaded, this field represents the result of the query.
058: */
059: private List values = null;
060:
061: /**
062: * Is the current iteraor over the query result.
063: */
064: private QueryIterator iterator;
065:
066: /**
067: * Builds a QueryResultList.
068: * @param _tc the tuple collection representing the query result
069: * @param _pm is the peristence manager linked to the query
070: * @param _conns is the connection to the underlying support to close in
071: * same time than the query.
072: * @param _resultClazz is the class encapsulated the result
073: */
074: public JDOQueryResultList(TupleCollection _tc,
075: PersistenceManager _pm, Object[] _conns,
076: Class _resultClazz, Class[] _selectedFieldTypes,
077: boolean staticFirstElementIndex,
078: boolean returnIdentifierOnly, Logger _logger)
079: throws MedorException, SpeedoException {
080: super (_tc, _pm, _conns, _resultClazz, _selectedFieldTypes,
081: staticFirstElementIndex, returnIdentifierOnly, _logger);
082: }
083:
084: /**
085: *
086: * @return true if the calculation of the next element can be done,
087: * otherwise false.
088: */
089: protected boolean assertNotClosed() {
090: return pm != null;
091: }
092:
093: /**
094: * @return true if the query has not been closed
095: */
096: protected boolean assertBeforeNext() {
097: return pm != null && !pm.isClosed();
098: }
099:
100: /**
101: * Computes the query result.
102: */
103: protected List getList() {
104: if (!assertNotClosed()) {
105: throw new JDOUserException(
106: "Impossible to use a closed query result");
107: }
108: if (!assertBeforeNext()) {
109: throw new JDOUserException(
110: "Impossible to use a query result without opened persistence manager");
111: }
112: if (values != null)
113: return values;
114:
115: values = new ArrayList();
116: try {
117: if (!tc.isEmpty()) {
118: tc.first();
119: do {
120: Object o = getValue(tc.getTuple());
121: if (o != null) {
122: values.add(o);
123: }
124: } while (tc.next());
125: }
126: } catch (MedorException me) {
127: values = null;
128: throw new JDOUnsupportedOptionException(
129: "Persistence manager problem to get result",
130: new Exception[] { me });
131: }
132: return values;
133: }
134:
135: private class QueryIterator implements Iterator {
136:
137: private Object next;
138: private int idx = 0;
139:
140: public QueryIterator() {
141: try {
142: tc.first();
143: if (assertBeforeNext()) {
144: calculateNext(true);
145: } else {
146: next = null;
147: }
148: } catch (MedorException e) {
149: next = null;
150: }
151: }
152:
153: public void desactivate() {
154: next = null;
155: }
156:
157: public boolean hasNext() {
158: return next != null;
159: }
160:
161: public Object next() {
162: if (next == null) {
163: throw new NoSuchElementException("No such element");
164: }
165: Object res = next;
166: calculateNext(false);
167: return res;
168: }
169:
170: private void calculateNext(boolean isfirst) {
171: boolean first = isfirst;
172: next = null;
173: try {
174: while (next == null && (first || tc.next())) {
175: first = false;
176: next = getValue(tc.getTuple());
177: }
178: } catch (MedorException e) {
179: logger.log(BasicLevel.ERROR,
180: "Impossible to fetch the pname", e);
181: throw new NoSuchElementException(e.getMessage());
182: }
183: }
184:
185: public void remove() {
186: throw new UnsupportedOperationException(
187: "This method is not supported in this implementation");
188: }
189: }
190:
191: // IMPLEMENTATION OF THE Collection INTERFACE //
192: //--------------------------------------------//
193:
194: /**
195: * Ensures that this collection contains the specified element
196: * (optional operation).
197: */
198: public boolean add(Object o) {
199: throw new JDOUnsupportedOptionException(
200: "This method is not supported in this implementation");
201: }
202:
203: /**
204: * Adds all of the elements in the specified collection to this collection
205: * (optional operation).
206: */
207: public boolean addAll(Collection c) {
208: throw new JDOUnsupportedOptionException(
209: "This method is not supported in this implementation");
210: }
211:
212: /**
213: * Removes all of the elements from this collection
214: * (optional operation).
215: */
216: public void clear() {
217: throw new JDOUnsupportedOptionException(
218: "This method is not supported in this implementation");
219: }
220:
221: /**
222: * Returns true if this collection contains the specified element.
223: */
224: public boolean contains(Object o) {
225: return indexOf(o) != -1;
226: }
227:
228: /**
229: * Returns true if this collection contains all of the elements in the
230: * specified collection.
231: */
232: public boolean containsAll(Collection c) {
233: if (values != null) {
234: return values.containsAll(c);
235: }
236: ArrayList tofind = new ArrayList(c);
237: for (Iterator it = iterator(); it.hasNext()
238: && !tofind.isEmpty();) {
239: Object current = it.next();
240: boolean found = false;
241: for (Iterator iter = tofind.iterator(); iter.hasNext()
242: && !found;) {
243: Object o = iter.next();
244: if ((o == null && current == null)
245: || (o != null && o.equals(current))) {
246: found = true;
247: iter.remove();
248: }
249: }
250: if (!found) {
251: return false;
252: }
253: }
254: return true;
255: }
256:
257: /**
258: * Compares the specified object with this collection for equality.
259: */
260: public boolean equals(Object o) {
261: throw new JDOUnsupportedOptionException(
262: "This method is not supported in this implementation");
263: }
264:
265: /**
266: * Returns the hash code value for this collection.
267: */
268: public int hashCode() {
269: return getList().hashCode();
270: }
271:
272: /**
273: * Returns true if this collection contains no elements.
274: */
275: public boolean isEmpty() {
276: try {
277: return tc == null || tc.isEmpty();
278: } catch (MedorException me) {
279: throw new JDOUnsupportedOptionException(
280: "a MedorException has been catched",
281: new Exception[] { me });
282: }
283: }
284:
285: /**
286: * Returns an iterator over the elements in this collection.
287: */
288: public Iterator iterator() {
289: if (iterator != null) {
290: iterator.desactivate();
291: }
292: iterator = new QueryIterator();
293: return iterator;
294: }
295:
296: /**
297: * Removes a single instance of the specified element from this collection,
298: * if it is present (optional operation).
299: */
300: public boolean remove(Object o) {
301: throw new JDOUnsupportedOptionException(
302: "This method is not supported in this implementation");
303: }
304:
305: /**
306: * Removes all this collection's elements that are also contained in the
307: * specified collection (optional operation).
308: */
309: public boolean removeAll(Collection c) {
310: throw new JDOUnsupportedOptionException(
311: "This method is not supported in this implementation");
312: }
313:
314: /**
315: * Retains only the elements in this collection that are contained in the
316: * specified collection (optional operation).
317: */
318: public boolean retainAll(Collection c) {
319: throw new JDOUnsupportedOptionException(
320: "This method is not supported in this implementation");
321: }
322:
323: /**
324: * Returns the number of elements in this collection.
325: */
326: public int size() {
327: return getList().size();
328: }
329:
330: /**
331: * Returns an array containing all of the elements in this collection.
332: */
333: public Object[] toArray() {
334: return getList().toArray();
335: }
336:
337: /**
338: * Returns an array containing all of the elements in this collection whose
339: * runtime type is that of the specified array.
340: */
341: public Object[] toArray(Object[] a) {
342: return getList().toArray(a);
343: }
344:
345: public void add(int index, Object element) {
346: throw new JDOUnsupportedOptionException(
347: "This method is not supported in this implementation");
348: }
349:
350: public boolean addAll(int index, Collection c) {
351: throw new JDOUnsupportedOptionException(
352: "This method is not supported in this implementation");
353: }
354:
355: public Object get(int index) {
356: if (values != null) {
357: return values.get(index);
358: } else {
359: int i = -1;
360: Object current = null;
361: for (Iterator it = iterator(); it.hasNext() && i < index; i++) {
362: current = it.next();
363: }
364: if (i == index) {
365: return current;
366: } else {
367: return null;
368: }
369: }
370: }
371:
372: public int indexOf(Object o) {
373: if (values != null) {
374: return values.indexOf(o);
375: }
376: int i = 0;
377: for (Iterator it = iterator(); it.hasNext(); i++) {
378: Object current = it.next();
379: if ((o == null && current == null)
380: || (o != null && o.equals(current))) {
381: return i;
382: }
383: }
384: return -1;
385: }
386:
387: public int lastIndexOf(Object o) {
388: return getList().lastIndexOf(o);
389: }
390:
391: public ListIterator listIterator() {
392: return listIterator(0);
393: }
394:
395: public ListIterator listIterator(int index) {
396: if (values != null) {
397: return values.listIterator();
398: } else if (index == 0) {
399: return getList().listIterator();
400: } else {
401: //TODO: implement listIterator(int) efficiency
402: return getList().listIterator(index);
403: }
404: }
405:
406: public Object remove(int index) {
407: throw new JDOUnsupportedOptionException(
408: "This method is not supported in this implementation");
409: }
410:
411: public Object set(int index, Object element) {
412: throw new JDOUnsupportedOptionException(
413: "This method is not supported in this implementation");
414: }
415:
416: public List subList(int fromIndex, int toIndex) {
417: if (toIndex < fromIndex) {
418: throw new IllegalArgumentException("toIndex(" + toIndex
419: + ") < fromIndex(" + fromIndex + ")");
420: } else if (toIndex == fromIndex) {
421: return Collections.EMPTY_LIST;
422: } else if (values != null) {
423: return values.subList(fromIndex, toIndex);
424: } else {
425: ArrayList result = new ArrayList();
426: int i = -1;
427: for (Iterator it = iterator(); it.hasNext() && i < toIndex; i++) {
428: Object current = it.next();
429: }
430: return null;
431: }
432: }
433: }
|