/*
$Header: /cvsroot/xorm/xorm/src/org/xorm/ListProxy.java,v 1.3 2003/06/27 20:06:07 dcheckoway Exp $
This file is part of XORM.
XORM is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
XORM 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 General Public License for more details.
You should have received a copy of the GNU General Public License
along with XORM; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.xorm;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import org.xorm.datastore.Row;
import org.xorm.query.Selector;
public class ListProxy extends RelationshipProxy implements List {
public ListProxy(InterfaceManager mgr,
RelationshipMapping mapping,
InterfaceInvocationHandler owner,
ClassMapping classMapping,
Object[] args) {
super(mgr, mapping, owner, classMapping, args);
}
protected Selector getSelector() {
Selector selector = super.getSelector();
if (selector == null) { return null; }
// Modify the basic selector by ordering by the index
Selector.Ordering[] ordering = new Selector.Ordering[1];
ordering[0] = new Selector.Ordering(mapping.getIndexColumn(), Selector.Ordering.ASCENDING);
selector.setOrdering(ordering);
// Ensure that the index column gets fetched
selector.getFetchColumns().add(mapping.getIndexColumn());
return selector;
}
/**
* Lazy resolve on rows. Overrides the method in CollectionProxy
* to ensure that rows is always an instance of List. There
* is a slight performance impact to this if the datastore driver
* is not returning a List as the items must be copied.
*/
public Collection getRows() {
if (rows == null) {
Collection c = super.getRows();
rows = (c instanceof List) ? c : new ArrayList(c);
}
return rows;
}
// List operations
public boolean add(Object o) {
add(getRows().size(), o);
return true;
}
public void add(int index, Object o) {
// Sanity checking
if (o == null) throw new NullPointerException();
if (!getElementType().isInstance(o)) {
throw new IllegalArgumentException("Collection only accepts " + getElementType());
}
if (!txnManaged) {
forceTransaction();
}
InterfaceInvocationHandler handler = InterfaceInvocationHandler.getHandler(o);
Row row;
if (mapping.isMToN()) {
row = new Row(mapping.getSource().getColumn().getTable());
row.setValue(mapping.getTarget().getColumn(), handler.getObjectId());
markAsNew(row);
} else {
row = handler.getRow();
}
row.setValue(mapping.getSource().getColumn(), owner.getObjectId());
row.setValue(mapping.getIndexColumn(), new Integer(index));
((List) getRows()).add(index, row);
rowToProxy.put(row, o);
// TODO: alter indices of all elements > index
reindex(index + 1, 1);
}
protected void reindex(int start, int offset) {
ListIterator li = ((List) getRows()).listIterator(start);
while (li.hasNext()) {
Row row = (Row) li.next();
int oldIndex = ((Integer) row.getValue(mapping.getIndexColumn()))
.intValue();
row.setValue(mapping.getIndexColumn(), new Integer(oldIndex + offset));
// Mark the row for an update?
}
}
public boolean addAll(int index, Collection c) {
// Sanity checking
if (c == null) throw new NullPointerException();
if (c.isEmpty()) { return false; }
if (!txnManaged) {
forceTransaction();
}
int current = index;
ArrayList rows = new ArrayList();
Iterator i = c.iterator();
while (i.hasNext()) {
Object o = i.next();
if (!getElementType().isInstance(o)) {
throw new IllegalArgumentException("Collection only accepts " + getElementType());
}
InterfaceInvocationHandler handler = InterfaceInvocationHandler.getHandler(o);
Row row = new Row(mapping.getSource().getColumn().getTable());
row.setValue(mapping.getSource().getColumn(), owner.getObjectId());
row.setValue(mapping.getTarget().getColumn(), handler.getObjectId());
// TODO: set index value to current++
rowToProxy.put(row, o);
if (mapping.isMToN()) {
markAsNew(row);
}
rows.add(row);
}
((List) getRows()).addAll(index, rows);
// TODO: Now update all indices of rows starting at current
return true;
}
public Object get(int index) {
Row row = (Row) ((List) getRows()).get(index);
Object o = null;
if (rowToProxy.containsKey(row)) {
o = rowToProxy.get(row);
} else {
Object key = row.getValue(getKeyColumn());
o = mgr.lookup(getElementType(), key);
rowToProxy.put(row, o);
}
return o;
}
public int indexOf(Object o) {
// It's possible that the Row backing o is the Row in the collection,
// but that's not true for many-to-many
// Tricky because we don't want Row.equals() to use the
// index column.
throw new UnsupportedOperationException();
}
public int lastIndexOf(Object o) {
throw new UnsupportedOperationException();
}
public ListIterator listIterator() {
throw new UnsupportedOperationException();
}
public ListIterator listIterator(int index) {
throw new UnsupportedOperationException();
}
public boolean remove(Object o) {
throw new UnsupportedOperationException();
}
public Object remove(int index) {
throw new UnsupportedOperationException();
}
public Object set(int index, Object o) {
throw new UnsupportedOperationException();
}
public List subList(int fromIndex, int toIndex) {
throw new UnsupportedOperationException();
}
public Object[] toArray() {
Object[] output = new Object [ getRows().size() ];
Iterator it = iterator();
int i = 0;
while (it.hasNext()) {
output[i++] = it.next();
}
return output;
}
public Object[] toArray(Object[] a) {
Object[] output = (Object[]) Array.newInstance(a.getClass().getComponentType(), getRows().size());
Iterator it = iterator();
int i = 0;
while (it.hasNext()) {
Array.set(output, i++, it.next());
}
return output;
}
public boolean equals(Object o) {
// Check if all list elements are equal
throw new UnsupportedOperationException();
}
}