001: /*
002: *
003: * JMoney - A Personal Finance Manager
004: * Copyright (c) 2004 Nigel Westbury <westbury@users.sourceforge.net>
005: *
006: *
007: * This program is free software; you can redistribute it and/or modify
008: * it under the terms of the GNU General Public License as published by
009: * the Free Software Foundation; either version 2 of the License, or
010: * (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
020: *
021: */
022:
023: package net.sf.jmoney.jdbcdatastore;
024:
025: import java.sql.ResultSet;
026: import java.sql.SQLException;
027: import java.util.Collection;
028: import java.util.Iterator;
029:
030: import net.sf.jmoney.jdbcdatastore.SessionManager.DatabaseListKey;
031: import net.sf.jmoney.model2.ExtendableObject;
032: import net.sf.jmoney.model2.ExtendablePropertySet;
033: import net.sf.jmoney.model2.IListManager;
034: import net.sf.jmoney.model2.IValues;
035:
036: /**
037: * Every datastore implementation must provide an implementation
038: * of the IListManager interface. This implementation supplies
039: * an implementation that executes each method by submitting
040: * an SQL statement to the database.
041: *
042: * @author Nigel Westbury
043: */
044: public class ListManagerUncached<E extends ExtendableObject> implements
045: IListManager<E> {
046: private SessionManager sessionManager;
047: private DatabaseListKey<E> listKey;
048:
049: public ListManagerUncached(SessionManager sessionManager,
050: DatabaseListKey<E> listKey) {
051: this .sessionManager = sessionManager;
052: this .listKey = listKey;
053: }
054:
055: public <F extends E> F createNewElement(
056: ExtendablePropertySet<F> propertySet) {
057: /*
058: * First build the in-memory object. Even though the object is not
059: * cached in the parent list property, the object must be constructed to
060: * get the default values to be written to the database and the object
061: * must be constructed so it can be returned to the caller.
062: */
063: ObjectKey objectKey = new ObjectKey(sessionManager);
064:
065: /*
066: * Constructing the object means constructing the object key. Both
067: * contain a reference to the other, so they have the same lifetime.
068: */
069: // TODO: remove constructWithCachedList parameter
070: F extendableObject = sessionManager.constructExtendableObject(
071: propertySet, objectKey, sessionManager
072: .constructListKey(listKey));
073: objectKey.setObject(extendableObject);
074:
075: // Insert the new object into the tables.
076:
077: int rowId = sessionManager.insertIntoDatabase(propertySet,
078: extendableObject, listKey);
079: objectKey.setRowId(rowId);
080:
081: return extendableObject;
082: }
083:
084: public <F extends E> F createNewElement(
085: ExtendablePropertySet<F> propertySet, IValues values) {
086: /*
087: * First build the in-memory object. Even though the object is not
088: * cached in the parent list property, the object must be constructed to
089: * get the default values to be written to the database and the object
090: * must be constructed so it can be returned to the caller.
091: */
092: ObjectKey objectKey = new ObjectKey(sessionManager);
093:
094: /*
095: * Constructing the object means constructing the object key. Both
096: * contain a reference to the other, so they have the same lifetime.
097: */
098: F extendableObject = sessionManager.constructExtendableObject(
099: propertySet, objectKey, listKey, values);
100: objectKey.setObject(extendableObject);
101:
102: // Insert the new object into the tables.
103:
104: int rowId = sessionManager.insertIntoDatabase(propertySet,
105: extendableObject, listKey);
106: objectKey.setRowId(rowId);
107:
108: return extendableObject;
109: }
110:
111: public boolean deleteElement(E extendableObject) {
112: // Delete this object from the database.
113: IDatabaseRowKey key = (IDatabaseRowKey) extendableObject
114: .getObjectKey();
115: return sessionManager.deleteFromDatabase(key);
116: }
117:
118: public void moveElement(E extendableObject,
119: IListManager originalListManager) {
120: sessionManager.reparentInDatabase(extendableObject, listKey);
121: }
122:
123: public int size() {
124: try {
125: String tableName = listKey.listPropertyAccessor
126: .getElementPropertySet().getId().replace('.', '_');
127: String columnName = listKey.listPropertyAccessor.getName()
128: .replace('.', '_');
129: String sql = "SELECT COUNT(*) FROM " + tableName
130: + " WHERE \"" + columnName + "\" = "
131: + listKey.parentKey.getRowId();
132: System.out.println(sql);
133: ResultSet resultSet = sessionManager.getReusableStatement()
134: .executeQuery(sql);
135: resultSet.next();
136: int size = resultSet.getInt(1);
137: resultSet.close();
138: return size;
139: } catch (SQLException e) {
140: e.printStackTrace();
141: throw new RuntimeException("internal error");
142: }
143: }
144:
145: public boolean isEmpty() {
146: throw new RuntimeException("method not implemented");
147: }
148:
149: public boolean contains(Object o) {
150: throw new RuntimeException("method not implemented");
151: }
152:
153: public Iterator<E> iterator() {
154: /*
155: * We execute a SQL statement and pass the result set to an
156: * UncachedObjectIterator object which will return the entries in the
157: * result set. However, we must create a new statement because the
158: * iterator is being returned from this method call.
159: *
160: * This class only supports lists where the element type is a final
161: * property set. Therefore we know the exact type of every element in
162: * the list before we execute any query. This saves us from having to
163: * iterate over the final property sets (like the ListManagerCached
164: * object has to).
165: *
166: * The UnchachedObjectIterator is responsible for closing the result set
167: * and the associated statement.
168: */
169: try {
170: ResultSet resultSet = sessionManager.executeListQuery(
171: listKey, listKey.listPropertyAccessor
172: .getElementPropertySet());
173: return new UncachedObjectIterator<E>(resultSet,
174: listKey.listPropertyAccessor
175: .getElementPropertySet(), listKey,
176: sessionManager);
177: } catch (SQLException e) {
178: e.printStackTrace();
179: throw new RuntimeException("internal error");
180: }
181: }
182:
183: public Object[] toArray() {
184: throw new RuntimeException("method not implemented");
185: }
186:
187: public <T> T[] toArray(T[] arg0) {
188: throw new RuntimeException("method not implemented");
189: }
190:
191: public boolean add(E extendableObject) {
192: /*
193: * This list is not cached so there is nothing to do. The object has
194: * already been added to the database so the list will be
195: * correct if it is fetched.
196: */
197: return true;
198: }
199:
200: public boolean remove(Object o) {
201: /*
202: * This list is not cached so there is nothing to do. The object has
203: * already been removed from the database so the list will be
204: * correct if it is fetched.
205: */
206: return true;
207: }
208:
209: public boolean containsAll(Collection<?> arg0) {
210: throw new RuntimeException("method not implemented");
211: }
212:
213: public boolean addAll(Collection<? extends E> arg0) {
214: throw new RuntimeException("method not implemented");
215: }
216:
217: public boolean removeAll(Collection<?> arg0) {
218: throw new RuntimeException("method not implemented");
219: }
220:
221: public boolean retainAll(Collection<?> arg0) {
222: throw new RuntimeException("method not implemented");
223: }
224:
225: public void clear() {
226: throw new RuntimeException("method not implemented");
227: }
228: }
|