/**
* Speedo: an implementation of JDO compliant personality on top of JORM generic
* I/O sub-system.
* Copyright (C) 2001-2004 France Telecom R&D
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*
*
* Contact: speedo@objectweb.org
*
* Authors: S. Chassande-Barrioz
*
*/
package org.objectweb.speedo.query.jdo;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import javax.jdo.JDOUnsupportedOptionException;
import javax.jdo.JDOUserException;
import javax.jdo.PersistenceManager;
import org.objectweb.medor.api.MedorException;
import org.objectweb.medor.tuple.api.TupleCollection;
import org.objectweb.speedo.api.SpeedoException;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;
/**
* is the result of a JDO query. The result is exported as a java.util.List.
* This implementation supports user class or persistent class as query result.
* This implementation does not supports simultaneous iterations.
*
* @author S.Chassande-Barrioz
*/
public class JDOQueryResultList extends JDOQueryResultCommon implements List {
/**
* if all values are loaded, this field represents the result of the query.
*/
private List values = null;
/**
* Is the current iteraor over the query result.
*/
private QueryIterator iterator;
/**
* Builds a QueryResultList.
* @param _tc the tuple collection representing the query result
* @param _pm is the peristence manager linked to the query
* @param _conns is the connection to the underlying support to close in
* same time than the query.
* @param _resultClazz is the class encapsulated the result
*/
public JDOQueryResultList(TupleCollection _tc,
PersistenceManager _pm,
Object[] _conns,
Class _resultClazz,
Class[] _selectedFieldTypes,
boolean staticFirstElementIndex,
boolean returnIdentifierOnly,
Logger _logger)
throws MedorException, SpeedoException {
super(_tc, _pm, _conns, _resultClazz, _selectedFieldTypes,
staticFirstElementIndex, returnIdentifierOnly, _logger);
}
/**
*
* @return true if the calculation of the next element can be done,
* otherwise false.
*/
protected boolean assertNotClosed() {
return pm != null;
}
/**
* @return true if the query has not been closed
*/
protected boolean assertBeforeNext() {
return pm != null && !pm.isClosed();
}
/**
* Computes the query result.
*/
protected List getList() {
if (!assertNotClosed()) {
throw new JDOUserException("Impossible to use a closed query result");
}
if (!assertBeforeNext()) {
throw new JDOUserException(
"Impossible to use a query result without opened persistence manager");
}
if (values != null)
return values;
values = new ArrayList();
try {
if (!tc.isEmpty()) {
tc.first();
do {
Object o = getValue(tc.getTuple());
if (o != null) {
values.add(o);
}
} while (tc.next());
}
} catch (MedorException me) {
values = null;
throw new JDOUnsupportedOptionException(
"Persistence manager problem to get result", new Exception[]{me});
}
return values;
}
private class QueryIterator implements Iterator {
private Object next;
private int idx = 0;
public QueryIterator() {
try {
tc.first();
if (assertBeforeNext()) {
calculateNext(true);
} else {
next = null;
}
} catch (MedorException e) {
next = null;
}
}
public void desactivate() {
next = null;
}
public boolean hasNext() {
return next != null;
}
public Object next() {
if (next == null) {
throw new NoSuchElementException("No such element");
}
Object res = next;
calculateNext(false);
return res;
}
private void calculateNext(boolean isfirst) {
boolean first = isfirst;
next = null;
try {
while(next == null && (first || tc.next())) {
first = false;
next = getValue(tc.getTuple());
}
} catch (MedorException e) {
logger.log(BasicLevel.ERROR, "Impossible to fetch the pname", e);
throw new NoSuchElementException(e.getMessage());
}
}
public void remove() {
throw new UnsupportedOperationException(
"This method is not supported in this implementation");
}
}
// IMPLEMENTATION OF THE Collection INTERFACE //
//--------------------------------------------//
/**
* Ensures that this collection contains the specified element
* (optional operation).
*/
public boolean add(Object o) {
throw new JDOUnsupportedOptionException(
"This method is not supported in this implementation");
}
/**
* Adds all of the elements in the specified collection to this collection
* (optional operation).
*/
public boolean addAll(Collection c) {
throw new JDOUnsupportedOptionException(
"This method is not supported in this implementation");
}
/**
* Removes all of the elements from this collection
* (optional operation).
*/
public void clear() {
throw new JDOUnsupportedOptionException(
"This method is not supported in this implementation");
}
/**
* Returns true if this collection contains the specified element.
*/
public boolean contains(Object o) {
return indexOf(o) != -1;
}
/**
* Returns true if this collection contains all of the elements in the
* specified collection.
*/
public boolean containsAll(Collection c) {
if (values != null) {
return values.containsAll(c);
}
ArrayList tofind = new ArrayList(c);
for(Iterator it = iterator(); it.hasNext() && !tofind.isEmpty();) {
Object current = it.next();
boolean found = false;
for (Iterator iter = tofind.iterator(); iter.hasNext() && !found;) {
Object o = iter.next();
if ((o == null && current == null)
|| (o != null && o.equals(current))){
found = true;
iter.remove();
}
}
if (!found) {
return false;
}
}
return true;
}
/**
* Compares the specified object with this collection for equality.
*/
public boolean equals(Object o) {
throw new JDOUnsupportedOptionException(
"This method is not supported in this implementation");
}
/**
* Returns the hash code value for this collection.
*/
public int hashCode() {
return getList().hashCode();
}
/**
* Returns true if this collection contains no elements.
*/
public boolean isEmpty() {
try {
return tc == null || tc.isEmpty();
} catch (MedorException me) {
throw new JDOUnsupportedOptionException(
"a MedorException has been catched",
new Exception[]{me});
}
}
/**
* Returns an iterator over the elements in this collection.
*/
public Iterator iterator() {
if (iterator != null) {
iterator.desactivate();
}
iterator = new QueryIterator();
return iterator;
}
/**
* Removes a single instance of the specified element from this collection,
* if it is present (optional operation).
*/
public boolean remove(Object o) {
throw new JDOUnsupportedOptionException(
"This method is not supported in this implementation");
}
/**
* Removes all this collection's elements that are also contained in the
* specified collection (optional operation).
*/
public boolean removeAll(Collection c) {
throw new JDOUnsupportedOptionException(
"This method is not supported in this implementation");
}
/**
* Retains only the elements in this collection that are contained in the
* specified collection (optional operation).
*/
public boolean retainAll(Collection c) {
throw new JDOUnsupportedOptionException(
"This method is not supported in this implementation");
}
/**
* Returns the number of elements in this collection.
*/
public int size() {
return getList().size();
}
/**
* Returns an array containing all of the elements in this collection.
*/
public Object[] toArray() {
return getList().toArray();
}
/**
* Returns an array containing all of the elements in this collection whose
* runtime type is that of the specified array.
*/
public Object[] toArray(Object[] a) {
return getList().toArray(a);
}
public void add(int index, Object element) {
throw new JDOUnsupportedOptionException(
"This method is not supported in this implementation");
}
public boolean addAll(int index, Collection c) {
throw new JDOUnsupportedOptionException(
"This method is not supported in this implementation");
}
public Object get(int index) {
if (values != null) {
return values.get(index);
} else {
int i=-1;
Object current = null;
for(Iterator it = iterator(); it.hasNext()&& i<index;i++) {
current = it.next();
}
if (i == index) {
return current;
} else {
return null;
}
}
}
public int indexOf(Object o) {
if (values != null) {
return values.indexOf(o);
}
int i=0;
for(Iterator it = iterator(); it.hasNext();i++) {
Object current = it.next();
if ((o == null && current == null)
|| (o != null && o.equals(current))){
return i;
}
}
return -1;
}
public int lastIndexOf(Object o) {
return getList().lastIndexOf(o);
}
public ListIterator listIterator() {
return listIterator(0);
}
public ListIterator listIterator(int index) {
if (values != null) {
return values.listIterator();
} else if (index == 0) {
return getList().listIterator();
} else {
//TODO: implement listIterator(int) efficiency
return getList().listIterator(index);
}
}
public Object remove(int index) {
throw new JDOUnsupportedOptionException(
"This method is not supported in this implementation");
}
public Object set(int index, Object element) {
throw new JDOUnsupportedOptionException(
"This method is not supported in this implementation");
}
public List subList(int fromIndex, int toIndex) {
if (toIndex < fromIndex) {
throw new IllegalArgumentException("toIndex(" + toIndex
+ ") < fromIndex(" + fromIndex +")");
} else if (toIndex == fromIndex) {
return Collections.EMPTY_LIST;
}else if (values != null) {
return values.subList(fromIndex, toIndex);
} else {
ArrayList result = new ArrayList();
int i=-1;
for(Iterator it = iterator(); it.hasNext() && i<toIndex;i++) {
Object current = it.next();
}
return null;
}
}
}