001: /*
002: $Header: /cvsroot/xorm/xorm/src/org/xorm/CollectionProxy.java,v 1.7 2003/03/22 01:21:19 wbiggs Exp $
003:
004: This file is part of XORM.
005:
006: XORM is free software; you can redistribute it and/or modify
007: it under the terms of the GNU General Public License as published by
008: the Free Software Foundation; either version 2 of the License, or
009: (at your option) any later version.
010:
011: XORM 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
014: GNU General Public License for more details.
015:
016: You should have received a copy of the GNU General Public License
017: along with XORM; if not, write to the Free Software
018: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: */
020: package org.xorm;
021:
022: import java.util.AbstractCollection;
023: import java.util.ArrayList;
024: import java.util.Collection;
025: import java.util.Collections;
026: import java.util.HashMap;
027: import java.util.Iterator;
028: import java.util.List;
029: import java.util.NoSuchElementException;
030: import java.util.logging.Logger;
031: import javax.jdo.PersistenceManager;
032:
033: import org.xorm.datastore.Column;
034: import org.xorm.datastore.DataFetchGroup;
035: import org.xorm.datastore.Row;
036: import org.xorm.query.Selector;
037:
038: /**
039: * Represents a one-to-many or many-to-many relationship. An instance
040: * of CollectionProxy is constructed by
041: * InterfaceInvocationHandler.invokeCollectionGet() and by the JDO Query
042: * mechanism.
043: */
044: public class CollectionProxy extends AbstractCollection implements I15d {
045: protected static Logger logger = Logger
046: .getLogger("org.xorm.CollectionProxy");
047:
048: protected Collection rows;
049: protected HashMap rowToProxy = new HashMap();
050: protected ClassMapping classMapping;
051: protected InterfaceManager mgr;
052: protected Selector selector;
053: protected int sizeHint = -1;
054: protected ProxyIterator iterator;
055: protected boolean closed;
056:
057: protected CollectionProxy(InterfaceManager mgr,
058: ClassMapping classMapping) {
059: this .mgr = mgr;
060: this .classMapping = classMapping;
061: }
062:
063: public CollectionProxy(PersistenceManager mgr,
064: ClassMapping classMapping, Selector selector) {
065: this ((InterfaceManager) mgr, classMapping);
066: this .selector = selector;
067: }
068:
069: /** Returns the InterfaceManager associated with this proxy. */
070: public InterfaceManager getInterfaceManager() {
071: return mgr;
072: }
073:
074: public Class getElementType() {
075: return classMapping.getMappedClass();
076: }
077:
078: /**
079: * Returns the column on the rows held by this object that contains
080: * the primary keys of the element type.
081: */
082: protected Column getKeyColumn() {
083: return classMapping.getTable().getPrimaryKey();
084: }
085:
086: /** Lazy resolve on rows. */
087: public synchronized Collection getRows() {
088: if (rows == null) {
089: if (selector != null) {
090: rows = mgr.selectRows(selector);
091: } else {
092: // Empty
093: rows = new ArrayList();
094: }
095: }
096: return rows;
097: }
098:
099: public boolean add(Object o) {
100: throw new UnsupportedOperationException(I18N
101: .msg("E_read_only_collection"));
102: }
103:
104: public boolean remove(Object o) {
105: throw new UnsupportedOperationException(I18N
106: .msg("E_read_only_collection"));
107: }
108:
109: public void close() {
110: if (iterator != null) {
111: iterator.close();
112: }
113: closed = true;
114: }
115:
116: /** Returns the size of the collection. */
117: public int size() {
118: if (rows == null) {
119: if (sizeHint == -1) {
120: sizeHint = (mgr == null) ? 0 : mgr
121: .executeSizeQuery(selector);
122: }
123: return sizeHint;
124: } else {
125: return rows.size();
126: }
127: }
128:
129: protected class ProxyIterator implements Iterator {
130: protected Iterator inner = getRows().iterator();
131: protected Row lastRow;
132: protected boolean valid = true;
133:
134: public boolean hasNext() {
135: return valid && inner.hasNext();
136: }
137:
138: public Object next() {
139: if (!valid) {
140: throw new NoSuchElementException();
141: }
142: lastRow = (Row) inner.next();
143: Object last;
144: if (rowToProxy.containsKey(lastRow)) {
145: last = rowToProxy.get(lastRow);
146: } else {
147: Object key = lastRow.getValue(getKeyColumn());
148: last = mgr.lookup(getElementType(), key);
149: rowToProxy.put(lastRow, last);
150: }
151: return last;
152: }
153:
154: public void remove() {
155: throw new UnsupportedOperationException(I18N
156: .msg("E_read_only_collection"));
157: }
158:
159: public void close() {
160: valid = false;
161: }
162: }
163:
164: public Iterator iterator() {
165: if (closed)
166: return Collections.EMPTY_LIST.iterator();
167: return iterator = new ProxyIterator();
168: }
169: }
|