001: /*
002: $Header: /cvsroot/xorm/xorm/src/org/xorm/StateManagerImpl.java,v 1.8 2003/08/30 21:45:17 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.IdentityHashMap;
023:
024: import javax.jdo.PersistenceManager;
025: import javax.jdo.spi.JDOImplHelper;
026: import javax.jdo.spi.PersistenceCapable;
027: import javax.jdo.spi.StateManager;
028:
029: /**
030: * A single instance of StateManagerImpl tracks the state of a
031: * non-interface JDO PersistenceCapable object.
032: * The StateManager is not needed for instances of InterfaceInvocationHandler,
033: * which don't completely follow the JDO spec at present.
034: */
035: public final class StateManagerImpl extends ObjectState implements
036: StateManager {
037: // The Transaction this pc participates in
038: private TransactionImpl txn;
039:
040: // Tracking info on fields that are loaded
041: private boolean[] loaded;
042:
043: // Tracking info on fields that are dirty
044: private boolean[] dirty;
045:
046: // JDO Flags
047: private byte flags;
048:
049: // Object ID
050: private Object objectId;
051:
052: // ClassMapping
053: ClassMapping mapping;
054:
055: private static IdentityHashMap pcToSM = new IdentityHashMap();
056:
057: static StateManagerImpl forPersistenceCapable(
058: PersistenceCapable pc, PersistenceManager mgr) {
059: StateManagerImpl sm = (StateManagerImpl) pcToSM.get(pc);
060: if (sm == null) {
061: sm = new StateManagerImpl((TransactionImpl) mgr
062: .currentTransaction(), pc, STATUS_TRANSACTIONAL);
063: pc.jdoReplaceStateManager(sm); // pc will call replacingSM
064: sm.flags = PersistenceCapable.LOAD_REQUIRED; // manage all
065: pc.jdoReplaceFlags(); // pc will call replacingFlags
066: pcToSM.put(pc, sm);
067: }
068: return sm;
069: }
070:
071: StateManagerImpl(TransactionImpl txn, PersistenceCapable pc,
072: byte status) {
073: super (pc);
074: this .txn = txn;
075: this .status = status;
076: mapping = txn.getInterfaceManager()
077: .getInterfaceManagerFactory().getModelMapping()
078: .getClassMapping(pc.getClass());
079: }
080:
081: private void dirty(int field) {
082: if (!txn.isActive())
083: return;
084: if (dirty == null) {
085: dirty = new boolean[JDOImplHelper.getInstance()
086: .getFieldNames(getProxy().getClass()).length];
087: }
088: dirty[field] = true;
089: setDirty(true);
090: }
091:
092: /** Returns true if a clone was detected. */
093: private boolean checkForClone(PersistenceCapable pc) {
094: if (this .proxy != pc) {
095: // Clone detected -- disconnect
096: flags = PersistenceCapable.READ_WRITE_OK;
097: pc.jdoReplaceFlags(); // pc will call replacingFlags
098: pc.jdoReplaceStateManager(null); // pc will call replacingSM
099: return true;
100: }
101: return false;
102: }
103:
104: // PC calls this to get the flags value to use during jdoReplaceFlags()
105: public byte replacingFlags(PersistenceCapable pc) {
106: return flags;
107: }
108:
109: // Called from PC.jdoReplaceStateManager in response to a PC being
110: // asked to switch to a different StateManager.
111: // Current policy is to always allow the change, but the implications
112: // are not really dealt with yet. Basically we would need to
113: // clean up now that we know we're no longer managing the instance.
114: public StateManager replacingStateManager(PersistenceCapable pc,
115: StateManager sm) {
116: return sm;
117: }
118:
119: public boolean isDirty(PersistenceCapable pc) {
120: if (checkForClone(pc))
121: return false;
122: return isDirty();
123: }
124:
125: public boolean isTransactional(PersistenceCapable pc) {
126: if (checkForClone(pc))
127: return false;
128: return isTransactional();
129: }
130:
131: public boolean isPersistent(PersistenceCapable pc) {
132: if (checkForClone(pc))
133: return false;
134: return isPersistent();
135: }
136:
137: public boolean isNew(PersistenceCapable pc) {
138: if (checkForClone(pc))
139: return false;
140: return isNew();
141: }
142:
143: public boolean isDeleted(PersistenceCapable pc) {
144: if (checkForClone(pc))
145: return false;
146: return isDeleted();
147: }
148:
149: public PersistenceManager getPersistenceManager(
150: PersistenceCapable pc) {
151: if (checkForClone(pc))
152: return null;
153: return txn.getPersistenceManager();
154: }
155:
156: public void makeDirty(PersistenceCapable pc, String fieldName) {
157: if (checkForClone(pc))
158: return;
159:
160: String[] fields = JDOImplHelper.getInstance().getFieldNames(
161: pc.getClass());
162: for (int i = 0; i < fields.length; i++) {
163: if (fields[i].equals(fieldName)) {
164: dirty[i] = true;
165: break;
166: }
167: }
168: }
169:
170: public Object getObjectId(PersistenceCapable pc) {
171: if (checkForClone(pc))
172: return null;
173:
174: return objectId;
175: }
176:
177: public Object getTransactionalObjectId(PersistenceCapable pc) {
178: if (checkForClone(pc))
179: return null;
180:
181: // TODO: support transactionalObjectId
182: return objectId;
183: }
184:
185: public boolean isLoaded(PersistenceCapable pc, int field) {
186: if (checkForClone(pc))
187: return false;
188:
189: //return loaded[field];
190: return false;
191: }
192:
193: /** Ensures all fields are loaded from the datastore. */
194: public void preSerialize(PersistenceCapable pc) {
195: if (checkForClone(pc))
196: return;
197:
198: // TODO
199: }
200:
201: private Object load(int field) {
202: // TODO: Load field from Datastore
203: loaded[field] = true;
204: return null;
205: }
206:
207: // Get methods are called on reference-enhanced accessors (i.e. reads
208: // of PC fields).
209:
210: public boolean getBooleanField(PersistenceCapable pc, int field,
211: boolean currentValue) {
212: if (loaded[field])
213: return currentValue;
214: return ((Boolean) load(field)).booleanValue();
215: }
216:
217: public char getCharField(PersistenceCapable pc, int field,
218: char currentValue) {
219: if (loaded[field])
220: return currentValue;
221: return ((Character) load(field)).charValue();
222: }
223:
224: public byte getByteField(PersistenceCapable pc, int field,
225: byte currentValue) {
226: if (loaded[field])
227: return currentValue;
228: return ((Byte) load(field)).byteValue();
229: }
230:
231: public short getShortField(PersistenceCapable pc, int field,
232: short currentValue) {
233: if (loaded[field])
234: return currentValue;
235: return ((Short) load(field)).shortValue();
236: }
237:
238: public int getIntField(PersistenceCapable pc, int field,
239: int currentValue) {
240: if (loaded[field])
241: return currentValue;
242: return ((Integer) load(field)).intValue();
243: }
244:
245: public long getLongField(PersistenceCapable pc, int field,
246: long currentValue) {
247: if (loaded[field])
248: return currentValue;
249: return ((Long) load(field)).longValue();
250: }
251:
252: public float getFloatField(PersistenceCapable pc, int field,
253: float currentValue) {
254: if (loaded[field])
255: return currentValue;
256: return ((Float) load(field)).floatValue();
257: }
258:
259: public double getDoubleField(PersistenceCapable pc, int field,
260: double currentValue) {
261: if (loaded[field])
262: return currentValue;
263: return ((Double) load(field)).doubleValue();
264: }
265:
266: public String getStringField(PersistenceCapable pc, int field,
267: String currentValue) {
268: if (loaded[field])
269: return currentValue;
270: return (String) load(field);
271: }
272:
273: public Object getObjectField(PersistenceCapable pc, int field,
274: Object currentValue) {
275: if (loaded[field])
276: return currentValue;
277: return load(field);
278: }
279:
280: public void setBooleanField(PersistenceCapable pc, int field,
281: boolean currentValue, boolean newValue) {
282: dirty(field);
283: }
284:
285: public void setCharField(PersistenceCapable pc, int field,
286: char currentValue, char newValue) {
287: dirty(field);
288: }
289:
290: public void setByteField(PersistenceCapable pc, int field,
291: byte currentValue, byte newValue) {
292: dirty(field);
293: }
294:
295: public void setShortField(PersistenceCapable pc, int field,
296: short currentValue, short newValue) {
297: dirty(field);
298: }
299:
300: public void setIntField(PersistenceCapable pc, int field,
301: int currentValue, int newValue) {
302: dirty(field);
303: }
304:
305: public void setLongField(PersistenceCapable pc, int field,
306: long currentValue, long newValue) {
307: dirty(field);
308: }
309:
310: public void setFloatField(PersistenceCapable pc, int field,
311: float currentValue, float newValue) {
312: dirty(field);
313: }
314:
315: public void setDoubleField(PersistenceCapable pc, int field,
316: double currentValue, double newValue) {
317: dirty(field);
318: }
319:
320: public void setStringField(PersistenceCapable pc, int field,
321: String currentValue, String newValue) {
322: System.out.println("In setStringField");
323: dirty(field);
324: }
325:
326: public void setObjectField(PersistenceCapable pc, int field,
327: Object currentValue, Object newValue) {
328: dirty(field);
329: }
330:
331: public void providedBooleanField(PersistenceCapable pc, int field,
332: boolean currentValue) {
333: throw new UnsupportedOperationException();
334: }
335:
336: public void providedCharField(PersistenceCapable pc, int field,
337: char currentValue) {
338: throw new UnsupportedOperationException();
339: }
340:
341: public void providedByteField(PersistenceCapable pc, int field,
342: byte currentValue) {
343: throw new UnsupportedOperationException();
344: }
345:
346: public void providedShortField(PersistenceCapable pc, int field,
347: short currentValue) {
348: throw new UnsupportedOperationException();
349: }
350:
351: public void providedIntField(PersistenceCapable pc, int field,
352: int currentValue) {
353: throw new UnsupportedOperationException();
354: }
355:
356: public void providedLongField(PersistenceCapable pc, int field,
357: long currentValue) {
358: throw new UnsupportedOperationException();
359: }
360:
361: public void providedFloatField(PersistenceCapable pc, int field,
362: float currentValue) {
363: throw new UnsupportedOperationException();
364: }
365:
366: public void providedDoubleField(PersistenceCapable pc, int field,
367: double currentValue) {
368: throw new UnsupportedOperationException();
369: }
370:
371: public void providedStringField(PersistenceCapable pc, int field,
372: String currentValue) {
373: throw new UnsupportedOperationException();
374: }
375:
376: public void providedObjectField(PersistenceCapable pc, int field,
377: Object currentValue) {
378: throw new UnsupportedOperationException();
379: }
380:
381: public boolean replacingBooleanField(PersistenceCapable pc,
382: int field) {
383: throw new UnsupportedOperationException();
384: }
385:
386: public char replacingCharField(PersistenceCapable pc, int field) {
387: throw new UnsupportedOperationException();
388: }
389:
390: public byte replacingByteField(PersistenceCapable pc, int field) {
391: throw new UnsupportedOperationException();
392: }
393:
394: public short replacingShortField(PersistenceCapable pc, int field) {
395: throw new UnsupportedOperationException();
396: }
397:
398: public int replacingIntField(PersistenceCapable pc, int field) {
399: throw new UnsupportedOperationException();
400: }
401:
402: public long replacingLongField(PersistenceCapable pc, int field) {
403: throw new UnsupportedOperationException();
404: }
405:
406: public float replacingFloatField(PersistenceCapable pc, int field) {
407: throw new UnsupportedOperationException();
408: }
409:
410: public double replacingDoubleField(PersistenceCapable pc, int field) {
411: throw new UnsupportedOperationException();
412: }
413:
414: public String replacingStringField(PersistenceCapable pc, int field) {
415: throw new UnsupportedOperationException();
416: }
417:
418: public Object replacingObjectField(PersistenceCapable pc, int field) {
419: throw new UnsupportedOperationException();
420: }
421: }
|