Source Code Cross Referenced for StateManagerImpl.java in  » Database-ORM » TJDO » com » triactive » jdo » state » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database ORM » TJDO » com.triactive.jdo.state 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 2004 (C) TJDO.
0003:         * All rights reserved.
0004:         *
0005:         * This software is distributed under the terms of the TJDO License version 1.0.
0006:         * See the terms of the TJDO License in the documentation provided with this software.
0007:         *
0008:         * $Id: StateManagerImpl.java,v 1.19 2004/01/25 22:31:16 jackknifebarber Exp $
0009:         */
0010:
0011:        package com.triactive.jdo.state;
0012:
0013:        import com.triactive.jdo.AbstractFieldManager;
0014:        import com.triactive.jdo.FieldManager;
0015:        import com.triactive.jdo.GenericFieldManager;
0016:        import com.triactive.jdo.PersistenceManager;
0017:        import com.triactive.jdo.SCO;
0018:        import com.triactive.jdo.model.ClassMetaData;
0019:        import com.triactive.jdo.model.FieldMetaData;
0020:        import com.triactive.jdo.sco.SCOProcessor;
0021:        import com.triactive.jdo.store.StoreManager;
0022:        import java.io.PrintWriter;
0023:        import java.lang.reflect.Method;
0024:        import java.util.Arrays;
0025:        import java.util.Collection;
0026:        import java.util.Map;
0027:        import javax.jdo.InstanceCallbacks;
0028:        import javax.jdo.JDOFatalInternalException;
0029:        import javax.jdo.JDOFatalUserException;
0030:        import javax.jdo.JDOUnsupportedOptionException;
0031:        import javax.jdo.JDOUserException;
0032:        import javax.jdo.Transaction;
0033:        import javax.jdo.spi.JDOImplHelper;
0034:        import javax.jdo.spi.PersistenceCapable;
0035:        import javax.jdo.spi.StateManager;
0036:        import org.apache.log4j.Category;
0037:
0038:        /**
0039:         * This class implements the StateManager.
0040:         *
0041:         * @author <a href="mailto:mmartin5@austin.rr.com">Mike Martin</a>
0042:         * @version $Revision: 1.19 $
0043:         */
0044:
0045:        public class StateManagerImpl implements  com.triactive.jdo.StateManager {
0046:            private static final Category LOG = Category
0047:                    .getInstance(StateManagerImpl.class);
0048:            private static final JDOImplHelper helper;
0049:            private static final StateFieldManager hollowFieldManager = new StateFieldManager();
0050:
0051:            private PersistenceManager myPM;
0052:            private PersistenceCapable myPC;
0053:            private Transaction myTX;
0054:            private Object myID;
0055:            private LifeCycleState myLC;
0056:            private byte jdoFlags;
0057:            private PersistenceCapable savedImage = null;
0058:            private byte savedFlags;
0059:            private boolean[] savedLoadedFields = null;
0060:
0061:            private ClassMetaData cmd;
0062:            private StoreManager srm;
0063:            private int fieldCount;
0064:
0065:            private boolean inserting = false;
0066:            private boolean dirty = false;
0067:            private boolean deleting = false;
0068:            private boolean flushing = false;
0069:            private boolean changingState = false;
0070:            private boolean postLoadPending = false;
0071:            private boolean disconnecting = false;
0072:            private boolean[] dirtyFields;
0073:            private boolean[] loadedFields;
0074:            private boolean[] defaultFetchGroupFields;
0075:            private boolean[] secondClassMutableFields;
0076:            private int[] allFieldNumbers;
0077:            private int[] persistentFieldNumbers;
0078:            private int[] defaultFetchGroupFieldNumbers;
0079:            private int[] secondClassMutableFieldNumbers;
0080:
0081:            private FieldManager currFM = null;
0082:
0083:            static {
0084:                try {
0085:                    helper = JDOImplHelper.getInstance();
0086:                } catch (SecurityException e) {
0087:                    throw new JDOFatalUserException(
0088:                            "Insufficient access granted to com.triactive.jdo.*",
0089:                            e);
0090:                }
0091:            }
0092:
0093:            /**
0094:             * Constructs a state manager to manage an existing persistence-capable
0095:             * instance that is not persistent.
0096:             * All mutable SCO fields are wrapped in suitable wrapper objects and the
0097:             * PC instance transitions to a TransientClean state.
0098:             *
0099:             * @param pm
0100:             *      The persistence manager controlling this state manager.
0101:             * @param pc
0102:             *      The instance to be managed.
0103:             */
0104:
0105:            public StateManagerImpl(PersistenceManager pm, PersistenceCapable pc) {
0106:                myPM = pm;
0107:                myTX = pm.currentTransaction();
0108:                srm = myPM.getStoreManager();
0109:                myPC = pc;
0110:                myID = null;
0111:                myLC = LifeCycleState.getLifeCycleState(LifeCycleState.T_CLEAN);
0112:                jdoFlags = PersistenceCapable.READ_OK;
0113:                cmd = ClassMetaData.forClass(pc.getClass());
0114:
0115:                initialize();
0116:
0117:                for (int i = 0; i < fieldCount; ++i)
0118:                    loadedFields[i] = true;
0119:
0120:                myPC.jdoReplaceStateManager(this );
0121:                myPC.jdoReplaceFlags();
0122:
0123:                replaceSCOFields();
0124:            }
0125:
0126:            /**
0127:             * Constructs a state manager to manage a new, hollow instance having the
0128:             * given object ID.
0129:             * This constructor is used for creating new instances of existing
0130:             * persistent objects (i.e. via pm.getObjectById()).
0131:             *
0132:             * @param pm
0133:             *      The persistence manager controlling this state manager.
0134:             * @param pcClass
0135:             *      The class of the new instance to be created.
0136:             * @param id
0137:             *      The JDO identity of the object.
0138:             */
0139:
0140:            public StateManagerImpl(PersistenceManager pm, Class pcClass,
0141:                    Object id) {
0142:                myPM = pm;
0143:                myTX = pm.currentTransaction();
0144:                srm = myPM.getStoreManager();
0145:                myID = id;
0146:                myLC = LifeCycleState.getLifeCycleState(LifeCycleState.HOLLOW);
0147:                jdoFlags = PersistenceCapable.LOAD_REQUIRED;
0148:                cmd = ClassMetaData.forClass(pcClass);
0149:
0150:                initialize();
0151:
0152:                myPC = helper.newInstance(pcClass, this );
0153:            }
0154:
0155:            private void initialize() {
0156:                fieldCount = cmd.getInheritedFieldCount() + cmd.getFieldCount();
0157:
0158:                dirtyFields = new boolean[fieldCount];
0159:                loadedFields = (boolean[]) cmd.getTransactionalFieldFlags()
0160:                        .clone();
0161:                defaultFetchGroupFields = cmd.getDefaultFetchGroupFieldFlags();
0162:                secondClassMutableFields = cmd
0163:                        .getSecondClassMutableFieldFlags();
0164:
0165:                allFieldNumbers = cmd.getAllFieldNumbers();
0166:                persistentFieldNumbers = cmd.getPersistentFieldNumbers();
0167:                defaultFetchGroupFieldNumbers = cmd
0168:                        .getDefaultFetchGroupFieldNumbers();
0169:                secondClassMutableFieldNumbers = cmd
0170:                        .getSecondClassMutableFieldNumbers();
0171:            }
0172:
0173:            /**
0174:             * Passes all SCO field values through replaceFields(), which will wrap any
0175:             * unwrapped values with an appropriate SCO wrapper.
0176:             */
0177:            void replaceSCOFields() {
0178:                StateFieldManager scoFieldValues = new StateFieldManager();
0179:
0180:                provideFields(secondClassMutableFieldNumbers, scoFieldValues);
0181:                replaceFields(secondClassMutableFieldNumbers, scoFieldValues);
0182:            }
0183:
0184:            Object wrapSCOInstance(int field, Object value) {
0185:                if (value == null
0186:                        || (value instanceof  SCO && ((SCO) value).getOwner() == myPC))
0187:                    return value;
0188:                else {
0189:                    FieldMetaData fmd = cmd.getFieldAbsolute(field);
0190:                    Class fieldType = fmd.getType();
0191:
0192:                    SCOProcessor scoProc = SCOProcessor.forFieldType(fieldType);
0193:
0194:                    if (scoProc == null)
0195:                        throw new JDOUserException(
0196:                                "Class not supported as a second-class object: "
0197:                                        + fieldType.getName());
0198:
0199:                    return scoProc.newSCOInstance(myPC, fmd.getName(), value);
0200:                }
0201:            }
0202:
0203:            /**
0204:             * Calls unsetOwner() on all SCO fields.
0205:             */
0206:            private void disownSCOFields() {
0207:                provideFields(secondClassMutableFieldNumbers,
0208:                        new AbstractFieldManager() {
0209:                            public void storeObjectField(int fieldNumber,
0210:                                    Object value) {
0211:                                if (value instanceof  SCO)
0212:                                    ((SCO) value).unsetOwner();
0213:                            }
0214:                        });
0215:            }
0216:
0217:            private boolean isDFGLoaded() {
0218:                for (int i = 0; i < defaultFetchGroupFieldNumbers.length; ++i) {
0219:                    if (!loadedFields[defaultFetchGroupFieldNumbers[i]])
0220:                        return false;
0221:                }
0222:
0223:                return true;
0224:            }
0225:
0226:            void enlistInTransaction() {
0227:                myPM.enlistInTransaction(this );
0228:
0229:                if (jdoFlags == PersistenceCapable.LOAD_REQUIRED
0230:                        && isDFGLoaded()) {
0231:                    /*
0232:                     * A transactional object whose DFG fields are loaded does not need
0233:                     * to contact us in order to read those fields.
0234:                     */
0235:                    jdoFlags = PersistenceCapable.READ_OK;
0236:                    myPC.jdoReplaceFlags();
0237:                }
0238:            }
0239:
0240:            void evictFromTransaction() {
0241:                myPM.evictFromTransaction(this );
0242:
0243:                if (jdoFlags == PersistenceCapable.READ_OK
0244:                        && myLC.isPersistent()) {
0245:                    /*
0246:                     * A non-transactional object needs to contact us on any field read no
0247:                     * matter what fields are loaded.
0248:                     */
0249:                    jdoFlags = PersistenceCapable.LOAD_REQUIRED;
0250:                    myPC.jdoReplaceFlags();
0251:                }
0252:            }
0253:
0254:            void saveFields() {
0255:                savedFlags = jdoFlags;
0256:                savedLoadedFields = (boolean[]) loadedFields.clone();
0257:                savedImage = myPC.jdoNewInstance(this );
0258:                savedImage.jdoCopyFields(myPC, allFieldNumbers);
0259:
0260:                for (int i = 0; i < secondClassMutableFieldNumbers.length; ++i) {
0261:                    int field = secondClassMutableFieldNumbers[i];
0262:
0263:                    /*
0264:                     * Note: SCO fields in the saved image are clones and therefore
0265:                     * unowned.  If/when they are later restored the individual life-
0266:                     * cycle states decide whether or not they must be rewrapped to get
0267:                     * reowned (if going Transient they don't, otherwise they do).
0268:                     */
0269:                    Object value = provideField(savedImage, field);
0270:
0271:                    if (value != null) {
0272:                        if (value instanceof  SCO)
0273:                            value = ((SCO) value).clone();
0274:                        else {
0275:                            Class c = value.getClass();
0276:
0277:                            try {
0278:                                Method m = c.getMethod("clone", null);
0279:
0280:                                if (m != null)
0281:                                    value = m.invoke(value, null);
0282:                            } catch (Exception e) {
0283:                                throw new JDOFatalInternalException(
0284:                                        "SCO class not cloneable: "
0285:                                                + c.getName());
0286:                            }
0287:                        }
0288:
0289:                        replaceField(savedImage, field, value);
0290:                    }
0291:                }
0292:            }
0293:
0294:            void restoreFields() {
0295:                if (savedImage != null) {
0296:                    loadedFields = savedLoadedFields;
0297:                    jdoFlags = savedFlags;
0298:                    myPC.jdoReplaceFlags();
0299:                    myPC.jdoCopyFields(savedImage, allFieldNumbers);
0300:
0301:                    clearDirtyFlags();
0302:                    discardSavedFields();
0303:                }
0304:            }
0305:
0306:            void discardSavedFields() {
0307:                savedFlags = 0;
0308:                savedLoadedFields = null;
0309:                savedImage = null;
0310:            }
0311:
0312:            void clearPersistentFields() {
0313:                try {
0314:                    if (myPC instanceof  InstanceCallbacks)
0315:                        ((InstanceCallbacks) myPC).jdoPreClear();
0316:                } finally {
0317:                    replaceFieldsInternal(persistentFieldNumbers,
0318:                            hollowFieldManager);
0319:                    clearLoadedFlags();
0320:                    clearDirtyFlags();
0321:                }
0322:            }
0323:
0324:            private void clearLoadedFlags() {
0325:                jdoFlags = PersistenceCapable.LOAD_REQUIRED;
0326:                myPC.jdoReplaceFlags();
0327:                System.arraycopy(cmd.getTransactionalFieldFlags(), 0,
0328:                        loadedFields, 0, loadedFields.length);
0329:            }
0330:
0331:            private void clearDirtyFlags() {
0332:                dirty = false;
0333:                clearFlags(dirtyFields);
0334:            }
0335:
0336:            /**
0337:             * Returns an array of integers containing the indices of all elements in
0338:             * <tt>flags</tt> that are set to <tt>state</tt>.
0339:             */
0340:
0341:            private static int[] getFlagsSetTo(boolean[] flags, boolean state) {
0342:                int[] temp = new int[flags.length];
0343:                int j = 0;
0344:
0345:                for (int i = 0; i < flags.length; i++) {
0346:                    if (flags[i] == state)
0347:                        temp[j++] = i;
0348:                }
0349:
0350:                if (j != 0) {
0351:                    int[] fieldNumbers = new int[j];
0352:                    System.arraycopy(temp, 0, fieldNumbers, 0, j);
0353:
0354:                    return fieldNumbers;
0355:                } else
0356:                    return null;
0357:            }
0358:
0359:            /**
0360:             * Returns an array of integers containing the indices of all elements in
0361:             * <tt>flags</tt> whose index occurs in <tt>indices</tt> and whose value is
0362:             * <tt>state</tt>.
0363:             */
0364:
0365:            private static int[] getFlagsSetTo(boolean[] flags, int[] indices,
0366:                    boolean state) {
0367:                int[] temp = new int[indices.length];
0368:                int j = 0;
0369:
0370:                for (int i = 0; i < indices.length; i++) {
0371:                    if (flags[indices[i]] == state)
0372:                        temp[j++] = indices[i];
0373:                }
0374:
0375:                if (j != 0) {
0376:                    int[] fieldNumbers = new int[j];
0377:                    System.arraycopy(temp, 0, fieldNumbers, 0, j);
0378:
0379:                    return fieldNumbers;
0380:                } else
0381:                    return null;
0382:            }
0383:
0384:            private static void clearFlags(boolean[] flags) {
0385:                for (int i = 0; i < flags.length; i++)
0386:                    flags[i] = false;
0387:            }
0388:
0389:            private boolean disconnectClone(PersistenceCapable pc) {
0390:                if (pc != myPC) {
0391:                    if (LOG.isDebugEnabled())
0392:                        LOG.debug("Disconnecting clone " + toJVMIDString(pc)
0393:                                + " from " + this );
0394:
0395:                    /*
0396:                     * Reset jdoFlags in the clone to PersistenceCapable.READ_WRITE_OK 
0397:                     * and clear its state manager.
0398:                     */
0399:                    byte myJdoFlags = jdoFlags;
0400:                    jdoFlags = PersistenceCapable.READ_WRITE_OK;
0401:
0402:                    try {
0403:                        pc.jdoReplaceFlags();
0404:                    } finally {
0405:                        jdoFlags = myJdoFlags;
0406:                    }
0407:
0408:                    pc.jdoReplaceStateManager(null);
0409:                    return true;
0410:                } else
0411:                    return false;
0412:            }
0413:
0414:            /**
0415:             * The StateManager uses this method to supply the value of jdoFlags to the
0416:             * associated PersistenceCapable instance.
0417:             *
0418:             * @param pc
0419:             *   the calling PersistenceCapable instance
0420:             * @return
0421:             *   the value of jdoFlags to be stored in the PersistenceCapable instance
0422:             */
0423:
0424:            public byte replacingFlags(PersistenceCapable pc) {
0425:                // If this is a clone, return READ_WRITE_OK.
0426:                if (pc != myPC)
0427:                    return PersistenceCapable.READ_WRITE_OK;
0428:                else
0429:                    return jdoFlags;
0430:            }
0431:
0432:            /**
0433:             * Return the PersistenceManager that owns this instance.
0434:             *
0435:             * @param pc
0436:             *   the calling PersistenceCapable instance
0437:             * @return
0438:             *   the PersistenceManager that owns this instance
0439:             */
0440:
0441:            public javax.jdo.PersistenceManager getPersistenceManager(
0442:                    PersistenceCapable pc) {
0443:                if (disconnectClone(pc))
0444:                    return null;
0445:                else {
0446:                    this .myPM.hereIsStateManager(this , myPC);
0447:                    return myPM;
0448:                }
0449:            }
0450:
0451:            private void postWriteField(int field) {
0452:                /*
0453:                 * If we've written a field in the middle of inserting or flushing it
0454:                 * must be due to jdoPreStore().  If inserting, we haven't actually done
0455:                 * the INSERT yet so we don't want to mark anything as dirty, which
0456:                 * would make us want to do an UPDATE later.
0457:                 */
0458:                if (myLC.isPersistent() && !inserting) {
0459:                    dirty = true;
0460:                    dirtyFields[field] = true;
0461:                    loadedFields[field] = true;
0462:
0463:                    /*
0464:                     * If flushing, to avoid an infinite recursion we don't notify the
0465:                     * PM or call flush().
0466:                     */
0467:                    if (!flushing) {
0468:                        if (myTX.isActive())
0469:                            myPM.markDirty(this );
0470:                        else
0471:                            flush();
0472:                    }
0473:                }
0474:            }
0475:
0476:            /**
0477:             * Marks the given field dirty.
0478:             */
0479:
0480:            public void makeDirty(int field) {
0481:                transitionWriteField();
0482:                postWriteField(field);
0483:            }
0484:
0485:            /**
0486:             * Mark the associated PersistenceCapable field dirty.
0487:             *
0488:             * @param pc the calling PersistenceCapable instance
0489:             * @param fieldName the name of the field
0490:             */
0491:
0492:            public void makeDirty(PersistenceCapable pc, String fieldName) {
0493:                if (!disconnectClone(pc)) {
0494:                    int fieldNumber = cmd.getAbsoluteFieldNumber(fieldName);
0495:
0496:                    if (fieldNumber == -1)
0497:                        throw new JDOUserException("No such field '"
0498:                                + fieldName + "' in class "
0499:                                + cmd.getPCClass().getName());
0500:
0501:                    makeDirty(fieldNumber);
0502:                }
0503:            }
0504:
0505:            public Object getObjectId() {
0506:                return myID;
0507:            }
0508:
0509:            public StoreManager getStoreManager() {
0510:                return srm;
0511:            }
0512:
0513:            public PersistenceManager getPersistenceManager() {
0514:                return myPM;
0515:            }
0516:
0517:            /**
0518:             * Return the object representing the JDO identity of the calling instance.
0519:             *
0520:             * According to the JDO specification, if the JDO identity is being changed
0521:             * in the current transaction, this method returns the JDO identify as of the
0522:             * beginning of the transaction.
0523:             *
0524:             * @param pc the calling PersistenceCapable instance
0525:             * @return the object representing the JDO identity of the calling instance
0526:             */
0527:
0528:            public Object getObjectId(PersistenceCapable pc) {
0529:                if (disconnectClone(pc))
0530:                    return null;
0531:                else
0532:                    return myID;
0533:            }
0534:
0535:            /**
0536:             * Replace the current value of jdoStateManager.
0537:             *
0538:             * <P>This method is called by the PersistenceCapable whenever
0539:             * jdoReplaceStateManager is called and there is already
0540:             * an owning StateManager.  This is a security precaution
0541:             * to ensure that the owning StateManager is the only
0542:             * source of any change to its reference in the PersistenceCapable.</p>
0543:             *
0544:             * @return the new value for the jdoStateManager
0545:             * @param pc the calling PersistenceCapable instance
0546:             * @param sm the proposed new value for the jdoStateManager
0547:             */
0548:
0549:            public StateManager replacingStateManager(PersistenceCapable pc,
0550:                    StateManager sm) {
0551:                if (myLC == null)
0552:                    throw new JDOFatalInternalException("Null LifeCycleState");
0553:
0554:                if (pc == myPC) {
0555:                    if (sm != null)
0556:                        throw new JDOFatalInternalException(
0557:                                "Attempted to replace with a different state manager");
0558:                    if (!disconnecting)
0559:                        throw new JDOFatalInternalException(
0560:                                "Attempted to clear state manager from other than disconnect()");
0561:
0562:                    if (LOG.isDebugEnabled())
0563:                        LOG.debug("Clearing state manager for "
0564:                                + toJVMIDString(pc));
0565:
0566:                    return null;
0567:                } else if (pc == savedImage)
0568:                    return null;
0569:                else
0570:                    return sm;
0571:            }
0572:
0573:            /**
0574:             * Return the object representing the JDO identity
0575:             * of the calling instance.  If the JDO identity is being changed in
0576:             * the current transaction, this method returns the current identity as
0577:             * changed in the transaction.
0578:             *
0579:             * @param pc the calling PersistenceCapable instance
0580:             * @return the object representing the JDO identity of the calling instance
0581:             */
0582:
0583:            public Object getTransactionalObjectId(PersistenceCapable pc) {
0584:                return getObjectId(pc);
0585:            }
0586:
0587:            /**
0588:             * Tests whether this object is dirty.
0589:             *
0590:             * Instances that have been modified, deleted, or newly
0591:             * made persistent in the current transaction return true.
0592:             *
0593:             * <P>Transient nontransactional instances return false (JDO spec), but the
0594:             * TriActive implementation does not currently support the transient
0595:             * transactional state.
0596:             *
0597:             * @see PersistenceCapable#jdoMakeDirty(String fieldName)
0598:             * @param pc the calling PersistenceCapable instance
0599:             * @return true if this instance has been modified in the current transaction.
0600:             */
0601:
0602:            public boolean isDirty(PersistenceCapable pc) {
0603:                if (disconnectClone(pc))
0604:                    return false;
0605:                else
0606:                    return myLC.isDirty();
0607:            }
0608:
0609:            /**
0610:             * Tests whether this object is transactional.
0611:             *
0612:             * Instances that respect transaction boundaries return true.  These instances
0613:             * include transient instances made transactional as a result of being the
0614:             * target of a makeTransactional method call; newly made persistent or deleted
0615:             * persistent instances; persistent instances read in data store
0616:             * transactions; and persistent instances modified in optimistic transactions.
0617:             *
0618:             * <P>Transient nontransactional instances return false.
0619:             *
0620:             * @param pc the calling PersistenceCapable instance
0621:             * @return true if this instance is transactional.
0622:             */
0623:
0624:            public boolean isTransactional(PersistenceCapable pc) {
0625:                if (disconnectClone(pc))
0626:                    return false;
0627:                else
0628:                    return myLC.isTransactional();
0629:            }
0630:
0631:            /**
0632:             * Tests whether this object is persistent.
0633:             *
0634:             * Instances whose state is stored in the data store return true.
0635:             *
0636:             * <P>Transient instances return false.
0637:             *
0638:             * @see PersistenceManager#makePersistent(Object pc)
0639:             * @param pc the calling PersistenceCapable instance
0640:             * @return true if this instance is persistent.
0641:             */
0642:
0643:            public boolean isPersistent(PersistenceCapable pc) {
0644:                if (disconnectClone(pc))
0645:                    return false;
0646:                else
0647:                    return myLC.isPersistent();
0648:            }
0649:
0650:            /**
0651:             * Tests whether this object has been newly made persistent.
0652:             *
0653:             * Instances that have been made persistent in the current transaction
0654:             * return true.
0655:             *
0656:             * <P>Transient instances return false.
0657:             *
0658:             * @see PersistenceManager#makePersistent(Object pc)
0659:             * @param pc the calling PersistenceCapable instance
0660:             * @return true if this instance was made persistent
0661:             * in the current transaction.
0662:             */
0663:
0664:            public boolean isNew(PersistenceCapable pc) {
0665:                if (disconnectClone(pc))
0666:                    return false;
0667:                else
0668:                    return myLC.isNew();
0669:            }
0670:
0671:            /**
0672:             * Tests whether this object has been deleted.
0673:             *
0674:             * Instances that have been deleted in the current transaction return true.
0675:             *
0676:             * <P>Transient instances return false.
0677:             *
0678:             * @see PersistenceManager#deletePersistent(Object pc)
0679:             * @param pc the calling PersistenceCapable instance
0680:             * @return true if this instance was deleted
0681:             * in the current transaction.
0682:             */
0683:
0684:            public boolean isDeleted(PersistenceCapable pc) {
0685:                if (disconnectClone(pc))
0686:                    return false;
0687:                else
0688:                    return myLC.isDeleted();
0689:            }
0690:
0691:            /**
0692:             * Called whenever the default fetch group fields have all been loaded.
0693:             * Updates jdoFlags and calls jdoPostLoad() as appropriate.
0694:             * <p>
0695:             * If it's called in the midst of a life-cycle transition both actions will
0696:             * be deferred until the transition is complete.
0697:             * <em>This deferral is important</em>.
0698:             * Without it, we could enter user code (jdoPostLoad()) while still making
0699:             * a state transition, and that way lies madness.
0700:             * <p>
0701:             * As an example, consider a jdoPostLoad() that calls other enhanced methods
0702:             * that read fields (jdoPostLoad() itself is not enhanced).  A P_NONTRANS
0703:             * object accessed within a transaction would produce the following infinite
0704:             * loop:
0705:             * <p>
0706:             * <blockquote><pre>
0707:             * isLoaded()
0708:             * transitionReadField()
0709:             * refreshLoadedFields()
0710:             * jdoPostLoad()
0711:             * isLoaded()
0712:             * ...
0713:             * </pre></blockquote>
0714:             * <p>
0715:             * because the transition from P_NONTRANS to P_CLEAN can never be completed.
0716:             */
0717:
0718:            private void postLoad() {
0719:                if (changingState)
0720:                    postLoadPending = true;
0721:                else {
0722:                    /*
0723:                     * A transactional object whose DFG fields are loaded does not need
0724:                     * to contact us in order to read those fields, so we can safely set
0725:                     * READ_OK.
0726:                     *
0727:                     * A non-transactional object needs to notify us on all field reads
0728:                     * so that we can decide whether or not any transition should occur,
0729:                     * so we leave the flags at LOAD_REQUIRED.
0730:                     */
0731:                    if (jdoFlags == PersistenceCapable.LOAD_REQUIRED
0732:                            && myLC.isTransactional()) {
0733:                        jdoFlags = PersistenceCapable.READ_OK;
0734:                        myPC.jdoReplaceFlags();
0735:                    }
0736:
0737:                    if (myPC instanceof  InstanceCallbacks)
0738:                        ((InstanceCallbacks) myPC).jdoPostLoad();
0739:                }
0740:            }
0741:
0742:            /**
0743:             * Validates that the instance exists in the data store.
0744:             * Called by pm.getObjectById() when validate == true.
0745:             */
0746:
0747:            public void validate() {
0748:                if (!myLC.isTransactional()) {
0749:                    /*
0750:                     * We're either Hollow or PNonTrans.  If a TX is active and there
0751:                     * are any DFG fields then a retrieve() does what we want, i.e. it
0752:                     * validates existence and makes us PClean.  Otherwise we do the
0753:                     * minimum lookup operation and leave our state as it is.
0754:                     */
0755:                    if (myTX.isActive()
0756:                            && defaultFetchGroupFieldNumbers.length != 0)
0757:                        retrieve(true);
0758:                    else
0759:                        srm.lookup(this );
0760:                }
0761:            }
0762:
0763:            /**
0764:             * Offers the specified pre-fetched fields to the state manager.
0765:             * If the instance is in a state that can benefit from newly available field
0766:             * values, the fields are replaced in the instance and a state change occurs
0767:             * as though the instance itself had read a field.
0768:             * Called by pm.getObjectById() when given prefetched fields.
0769:             */
0770:
0771:            public void offerPrefetchedFields(int[] fieldNumbers,
0772:                    FieldManager fieldManager) {
0773:                if (!myLC.isTransactional()) {
0774:                    /* We're either Hollow or PNonTrans.  Accept the fields. */
0775:                    transitionReadField();
0776:
0777:                    boolean dfgWasAlreadyLoaded = isDFGLoaded();
0778:
0779:                    replaceFields(fieldNumbers, fieldManager);
0780:
0781:                    if (!dfgWasAlreadyLoaded && isDFGLoaded())
0782:                        postLoad();
0783:                }
0784:            }
0785:
0786:            /**
0787:             * Fetchs from the database all fields in the default fetch group not
0788:             * already loaded.
0789:             * Called by, or immediately after, life-cycle transitions.
0790:             */
0791:
0792:            void loadDFGFields() {
0793:                int[] fieldNumbers = getFlagsSetTo(loadedFields,
0794:                        defaultFetchGroupFieldNumbers, false);
0795:
0796:                if (fieldNumbers != null) {
0797:                    srm.fetch(this , fieldNumbers);
0798:                    postLoad();
0799:                }
0800:            }
0801:
0802:            /**
0803:             * Fetch a given field from the database.  Do NOT call with a default fetch
0804:             * group field.
0805:             *
0806:             * @param fieldNumber   the field number of the field to fetch.
0807:             */
0808:
0809:            private void loadNonDFGField(int fieldNumber) {
0810:                srm.fetch(this , new int[] { fieldNumber });
0811:            }
0812:
0813:            /**
0814:             * Fetchs from the database all fields not currently loaded.
0815:             * Called by life-cycle transitions.
0816:             */
0817:
0818:            void loadUnloadedFields() {
0819:                int[] fieldNumbers = getFlagsSetTo(loadedFields, false);
0820:
0821:                if (fieldNumbers != null) {
0822:                    boolean dfgWasAlreadyLoaded = isDFGLoaded();
0823:
0824:                    srm.fetch(this , fieldNumbers);
0825:
0826:                    /* If the DFG was not already loaded, it is now. */
0827:                    if (!dfgWasAlreadyLoaded)
0828:                        postLoad();
0829:                }
0830:            }
0831:
0832:            /**
0833:             * Refreshes from the database all fields currently loaded.
0834:             * Called by life-cycle transitions.
0835:             */
0836:
0837:            void refreshLoadedFields() {
0838:                int[] fieldNumbers = getFlagsSetTo(loadedFields, true);
0839:
0840:                if (fieldNumbers != null) {
0841:                    clearDirtyFlags();
0842:                    clearLoadedFlags();
0843:
0844:                    srm.fetch(this , fieldNumbers);
0845:
0846:                    if (isDFGLoaded())
0847:                        postLoad();
0848:                }
0849:            }
0850:
0851:            /**
0852:             * Guarantee that the serializable transactional and persistent fields
0853:             * are loaded into the instance.  This method is called by the generated
0854:             * jdoPreSerialize method prior to serialization of the instance.
0855:             *
0856:             * @param pc the calling PersistenceCapable instance
0857:             */
0858:
0859:            public void preSerialize(PersistenceCapable pc) {
0860:                if (disconnectClone(pc))
0861:                    return;
0862:
0863:                retrieve(false);
0864:            }
0865:
0866:            /**
0867:             * Return true if the field is cached in the calling instance.
0868:             * <P>In the TriActive implementation of this method, isLoaded() will always
0869:             * return true. If the field is not loaded, it will be loaded as a side effect
0870:             * of the call to this method. If it is in the default fetch group, the default
0871:             * fetch group, including this field, will be loaded.
0872:             *
0873:             * @param pc the calling PersistenceCapable instance
0874:             * @param field the absolute field number
0875:             * @return always returns true (this implementation)
0876:             */
0877:
0878:            public boolean isLoaded(PersistenceCapable pc, int field) {
0879:                if (disconnectClone(pc))
0880:                    return true;
0881:                else {
0882:                    transitionReadField();
0883:
0884:                    if (!loadedFields[field]) {
0885:                        if (defaultFetchGroupFields[field])
0886:                            loadDFGFields();
0887:                        else
0888:                            loadNonDFGField(field);
0889:                    }
0890:
0891:                    return true;
0892:                }
0893:            }
0894:
0895:            /**
0896:             * Reads the current value of the specified field.
0897:             * This has the same effect on the state of the instance as if user code
0898:             * attempted to read the field.
0899:             *
0900:             * @param field
0901:             *      The field number to read.
0902:             * @return
0903:             *      The value of the field.  Primitives are boxed in appropriate
0904:             *      java.lang wrapper classes.
0905:             */
0906:
0907:            public Object getField(int field) {
0908:                isLoaded(myPC, field);
0909:                return provideField(myPC, field);
0910:            }
0911:
0912:            /**
0913:             * Updates the current value of the specified field.
0914:             * This has the same effect on the state of the instance as if user code
0915:             * attempted to write the field.
0916:             *
0917:             * @param field
0918:             *      The field number to write.
0919:             * @param currentValue
0920:             *      The current value of the field.  Used to determine whether or not
0921:             *      the write is redundant.  If necessary, the value can be obtained
0922:             *      using {@link #getField}.
0923:             * @param newValue
0924:             *      The new value of the field.  Primitives must be boxed in appropriate
0925:             *      java.lang wrapper classes.
0926:             */
0927:
0928:            public void setField(int field, Object currentValue, Object newValue) {
0929:                if (!loadedFields[field] || currentValue != newValue)
0930:                    writeObjectField(field, currentValue, newValue);
0931:            }
0932:
0933:            /**
0934:             * This method is called by the associated PersistenceCapable if the
0935:             * value for the specified field is not cached (i.e., StateManager.isLoaded()
0936:             * fails). In this implementation of the StateManager, isLoaded() has a
0937:             * side effect of loading unloaded information and will always return true.
0938:             * As such, this method should never be called.
0939:             */
0940:
0941:            public boolean getBooleanField(PersistenceCapable pc, int field,
0942:                    boolean currentValue) {
0943:                throw new JDOUnsupportedOptionException("Method not supported");
0944:            }
0945:
0946:            /**
0947:             * This method is called by the associated PersistenceCapable if the
0948:             * value for the specified field is not cached (i.e., StateManager.isLoaded()
0949:             * fails). In this implementation of the StateManager, isLoaded() has a
0950:             * side effect of loading unloaded information and will always return true.
0951:             * As such, this method should never be called.
0952:             */
0953:
0954:            public byte getByteField(PersistenceCapable pc, int field,
0955:                    byte currentValue) {
0956:                throw new JDOUnsupportedOptionException("Method not supported");
0957:            }
0958:
0959:            /**
0960:             * This method is called by the associated PersistenceCapable if the
0961:             * value for the specified field is not cached (i.e., StateManager.isLoaded()
0962:             * fails). In this implementation of the StateManager, isLoaded() has a
0963:             * side effect of loading unloaded information and will always return true.
0964:             * As such, this method should never be called.
0965:             */
0966:
0967:            public char getCharField(PersistenceCapable pc, int field,
0968:                    char currentValue) {
0969:                throw new JDOUnsupportedOptionException("Method not supported");
0970:            }
0971:
0972:            /**
0973:             * This method is called by the associated PersistenceCapable if the
0974:             * value for the specified field is not cached (i.e., StateManager.isLoaded()
0975:             * fails). In this implementation of the StateManager, isLoaded() has a
0976:             * side effect of loading unloaded information and will always return true.
0977:             * As such, this method should never be called.
0978:             */
0979:
0980:            public double getDoubleField(PersistenceCapable pc, int field,
0981:                    double currentValue) {
0982:                throw new JDOUnsupportedOptionException("Method not supported");
0983:            }
0984:
0985:            /**
0986:             * This method is called by the associated PersistenceCapable if the
0987:             * value for the specified field is not cached (i.e., StateManager.isLoaded()
0988:             * fails). In this implementation of the StateManager, isLoaded() has a
0989:             * side effect of loading unloaded information and will always return true.
0990:             * As such, this method should never be called.
0991:             */
0992:
0993:            public float getFloatField(PersistenceCapable pc, int field,
0994:                    float currentValue) {
0995:                throw new JDOUnsupportedOptionException("Method not supported");
0996:            }
0997:
0998:            /**
0999:             * This method is called by the associated PersistenceCapable if the
1000:             * value for the specified field is not cached (i.e., StateManager.isLoaded()
1001:             * fails). In this implementation of the StateManager, isLoaded() has a
1002:             * side effect of loading unloaded information and will always return true.
1003:             * As such, this method should never be called.
1004:             */
1005:
1006:            public int getIntField(PersistenceCapable pc, int field,
1007:                    int currentValue) {
1008:                throw new JDOUnsupportedOptionException("Method not supported");
1009:            }
1010:
1011:            /**
1012:             * This method is called by the associated PersistenceCapable if the
1013:             * value for the specified field is not cached (i.e., StateManager.isLoaded()
1014:             * fails). In this implementation of the StateManager, isLoaded() has a
1015:             * side effect of loading unloaded information and will always return true.
1016:             * As such, this method should never be called.
1017:             */
1018:
1019:            public long getLongField(PersistenceCapable pc, int field,
1020:                    long currentValue) {
1021:                throw new JDOUnsupportedOptionException("Method not supported");
1022:            }
1023:
1024:            /**
1025:             * This method is called by the associated PersistenceCapable if the
1026:             * value for the specified field is not cached (i.e., StateManager.isLoaded()
1027:             * fails). In this implementation of the StateManager, isLoaded() has a
1028:             * side effect of loading unloaded information and will always return true.
1029:             * As such, this method should never be called.
1030:             */
1031:
1032:            public short getShortField(PersistenceCapable pc, int field,
1033:                    short currentValue) {
1034:                throw new JDOUnsupportedOptionException("Method not supported");
1035:            }
1036:
1037:            /**
1038:             * This method is called by the associated PersistenceCapable if the
1039:             * value for the specified field is not cached (i.e., StateManager.isLoaded()
1040:             * fails). In this implementation of the StateManager, isLoaded() has a
1041:             * side effect of loading unloaded information and will always return true.
1042:             * As such, this method should never be called.
1043:             */
1044:
1045:            public String getStringField(PersistenceCapable pc, int field,
1046:                    String currentValue) {
1047:                throw new JDOUnsupportedOptionException("Method not supported");
1048:            }
1049:
1050:            /**
1051:             * This method is called by the associated PersistenceCapable if the
1052:             * value for the specified field is not cached (i.e., StateManager.isLoaded()
1053:             * fails). In this implementation of the StateManager, isLoaded() has a
1054:             * side effect of loading unloaded information and will always return true.
1055:             * As such, this method should never be called.
1056:             */
1057:
1058:            public Object getObjectField(PersistenceCapable pc, int field,
1059:                    Object currentValue) {
1060:                throw new JDOUnsupportedOptionException("Method not supported");
1061:            }
1062:
1063:            /**
1064:             * Called by the various setXXXField() methods once it's established that
1065:             * the field really deserves to be written.
1066:             * Makes the state transition and replaces the field value in the PC
1067:             * instance.
1068:             */
1069:
1070:            private void writeField(int field, Object newValue) {
1071:                transitionWriteField();
1072:                replaceField(myPC, field, newValue);
1073:                postWriteField(field);
1074:            }
1075:
1076:            /**
1077:             * Called by setObjectField() once it's established that the field really
1078:             * deserves to be written.
1079:             * Makes the state transition and replaces the field value in the PC
1080:             * instance.
1081:             * Wraps SCO fields if needed.
1082:             */
1083:
1084:            private void writeObjectField(int field, Object currentValue,
1085:                    Object newValue) {
1086:                transitionWriteField();
1087:
1088:                if (secondClassMutableFields[field]) {
1089:                    if (currentValue instanceof  SCO)
1090:                        ((SCO) currentValue).unsetOwner();
1091:
1092:                    newValue = wrapSCOInstance(field, newValue);
1093:                }
1094:
1095:                replaceField(myPC, field, newValue);
1096:                postWriteField(field);
1097:            }
1098:
1099:            /**
1100:             * This method is called by the associated PersistenceCapable when the
1101:             * corresponding mutator method (setXXX()) is called on the PersistenceCapable.
1102:             *
1103:             * @param pc the calling PersistenceCapable instance
1104:             * @param field the field number
1105:             * @param currentValue the current value of the field
1106:             * @param newValue the new value for the field
1107:             */
1108:
1109:            public void setBooleanField(PersistenceCapable pc, int field,
1110:                    boolean currentValue, boolean newValue) {
1111:                if (pc != myPC) {
1112:                    replaceField(pc, field, newValue ? Boolean.TRUE
1113:                            : Boolean.FALSE);
1114:                    disconnectClone(pc);
1115:                } else {
1116:                    if (!loadedFields[field] || currentValue != newValue)
1117:                        writeField(field, newValue ? Boolean.TRUE
1118:                                : Boolean.FALSE);
1119:                }
1120:            }
1121:
1122:            /**
1123:             * This method is called by the associated PersistenceCapable when the
1124:             * corresponding mutator method (setXXX()) is called on the PersistenceCapable.
1125:             *
1126:             * @param pc the calling PersistenceCapable instance
1127:             * @param field the field number
1128:             * @param currentValue the current value of the field
1129:             * @param newValue the new value for the field
1130:             */
1131:
1132:            public void setByteField(PersistenceCapable pc, int field,
1133:                    byte currentValue, byte newValue) {
1134:                if (pc != myPC) {
1135:                    replaceField(pc, field, new Byte(newValue));
1136:                    disconnectClone(pc);
1137:                } else {
1138:                    if (!loadedFields[field] || currentValue != newValue)
1139:                        writeField(field, new Byte(newValue));
1140:                }
1141:            }
1142:
1143:            /**
1144:             * This method is called by the associated PersistenceCapable when the
1145:             * corresponding mutator method (setXXX()) is called on the PersistenceCapable.
1146:             *
1147:             * @param pc the calling PersistenceCapable instance
1148:             * @param field the field number
1149:             * @param currentValue the current value of the field
1150:             * @param newValue the new value for the field
1151:             */
1152:
1153:            public void setCharField(PersistenceCapable pc, int field,
1154:                    char currentValue, char newValue) {
1155:                if (pc != myPC) {
1156:                    replaceField(pc, field, new Character(newValue));
1157:                    disconnectClone(pc);
1158:                } else {
1159:                    if (!loadedFields[field] || currentValue != newValue)
1160:                        writeField(field, new Character(newValue));
1161:                }
1162:            }
1163:
1164:            /**
1165:             * This method is called by the associated PersistenceCapable when the
1166:             * corresponding mutator method (setXXX()) is called on the PersistenceCapable.
1167:             *
1168:             * @param pc the calling PersistenceCapable instance
1169:             * @param field the field number
1170:             * @param currentValue the current value of the field
1171:             * @param newValue the new value for the field
1172:             */
1173:
1174:            public void setDoubleField(PersistenceCapable pc, int field,
1175:                    double currentValue, double newValue) {
1176:                if (pc != myPC) {
1177:                    replaceField(pc, field, new Double(newValue));
1178:                    disconnectClone(pc);
1179:                } else {
1180:                    if (!loadedFields[field] || currentValue != newValue)
1181:                        writeField(field, new Double(newValue));
1182:                }
1183:            }
1184:
1185:            /**
1186:             * This method is called by the associated PersistenceCapable when the
1187:             * corresponding mutator method (setXXX()) is called on the PersistenceCapable.
1188:             *
1189:             * @param pc the calling PersistenceCapable instance
1190:             * @param field the field number
1191:             * @param currentValue the current value of the field
1192:             * @param newValue the new value for the field
1193:             */
1194:
1195:            public void setFloatField(PersistenceCapable pc, int field,
1196:                    float currentValue, float newValue) {
1197:                if (pc != myPC) {
1198:                    replaceField(pc, field, new Float(newValue));
1199:                    disconnectClone(pc);
1200:                } else {
1201:                    if (!loadedFields[field] || currentValue != newValue)
1202:                        writeField(field, new Float(newValue));
1203:                }
1204:            }
1205:
1206:            /**
1207:             * This method is called by the associated PersistenceCapable when the
1208:             * corresponding mutator method (setXXX()) is called on the PersistenceCapable.
1209:             *
1210:             * @param pc the calling PersistenceCapable instance
1211:             * @param field the field number
1212:             * @param currentValue the current value of the field
1213:             * @param newValue the new value for the field
1214:             */
1215:
1216:            public void setIntField(PersistenceCapable pc, int field,
1217:                    int currentValue, int newValue) {
1218:                if (pc != myPC) {
1219:                    replaceField(pc, field, new Integer(newValue));
1220:                    disconnectClone(pc);
1221:                } else {
1222:                    if (!loadedFields[field] || currentValue != newValue)
1223:                        writeField(field, new Integer(newValue));
1224:                }
1225:            }
1226:
1227:            /**
1228:             * This method is called by the associated PersistenceCapable when the
1229:             * corresponding mutator method (setXXX()) is called on the PersistenceCapable.
1230:             *
1231:             * @param pc the calling PersistenceCapable instance
1232:             * @param field the field number
1233:             * @param currentValue the current value of the field
1234:             * @param newValue the new value for the field
1235:             */
1236:
1237:            public void setLongField(PersistenceCapable pc, int field,
1238:                    long currentValue, long newValue) {
1239:                if (pc != myPC) {
1240:                    replaceField(pc, field, new Long(newValue));
1241:                    disconnectClone(pc);
1242:                } else {
1243:                    if (!loadedFields[field] || currentValue != newValue)
1244:                        writeField(field, new Long(newValue));
1245:                }
1246:            }
1247:
1248:            /**
1249:             * This method is called by the associated PersistenceCapable when the
1250:             * corresponding mutator method (setXXX()) is called on the PersistenceCapable.
1251:             *
1252:             * @param pc the calling PersistenceCapable instance
1253:             * @param field the field number
1254:             * @param currentValue the current value of the field
1255:             * @param newValue the new value for the field
1256:             */
1257:
1258:            public void setShortField(PersistenceCapable pc, int field,
1259:                    short currentValue, short newValue) {
1260:                if (pc != myPC) {
1261:                    replaceField(pc, field, new Short(newValue));
1262:                    disconnectClone(pc);
1263:                } else {
1264:                    if (!loadedFields[field] || currentValue != newValue)
1265:                        writeField(field, new Short(newValue));
1266:                }
1267:            }
1268:
1269:            /**
1270:             * This method is called by the associated PersistenceCapable when the
1271:             * corresponding mutator method (setXXX()) is called on the PersistenceCapable.
1272:             *
1273:             * @param pc the calling PersistenceCapable instance
1274:             * @param field the field number
1275:             * @param currentValue the current value of the field
1276:             * @param newValue the new value for the field
1277:             */
1278:
1279:            public void setStringField(PersistenceCapable pc, int field,
1280:                    String currentValue, String newValue) {
1281:                if (pc != myPC) {
1282:                    replaceField(pc, field, newValue);
1283:                    disconnectClone(pc);
1284:                } else {
1285:                    if (!loadedFields[field] || !equals(currentValue, newValue))
1286:                        writeField(field, newValue);
1287:                }
1288:            }
1289:
1290:            /**
1291:             * This method is called by the associated PersistenceCapable when the
1292:             * corresponding mutator method (setXXX()) is called on the PersistenceCapable.
1293:             *
1294:             * @param pc the calling PersistenceCapable instance
1295:             * @param field the field number
1296:             * @param currentValue the current value of the field
1297:             * @param newValue the new value for the field
1298:             */
1299:
1300:            public void setObjectField(PersistenceCapable pc, int field,
1301:                    Object currentValue, Object newValue) {
1302:                if (pc != myPC) {
1303:                    replaceField(pc, field, newValue);
1304:                    disconnectClone(pc);
1305:                } else {
1306:                    if (!loadedFields[field] || currentValue != newValue)
1307:                        writeObjectField(field, currentValue, newValue);
1308:                }
1309:            }
1310:
1311:            /**
1312:             * Compares two objects for equality, where one or both of the object
1313:             * references may be null.
1314:             *
1315:             * @return  <code>true</code> if the objects are both <code>null</code> or
1316:             *          compare equal according to their equals() method,
1317:             *          <code>false</code> otherwise.
1318:             */
1319:
1320:            private static boolean equals(Object o1, Object o2) {
1321:                return o1 == null ? (o2 == null) : o1.equals(o2);
1322:            }
1323:
1324:            /**
1325:             * This method is called from the associated PersistenceCapable when its
1326:             * PersistenceCapable.jdoProvideFields() method is invoked. Its purpose is
1327:             * to provide the value of the specified field to the StateManager.
1328:             *
1329:             * @param pc   the calling PersistenceCapable instance
1330:             * @param field   the field number
1331:             * @param currentValue   the current value of the field
1332:             */
1333:
1334:            public void providedBooleanField(PersistenceCapable pc, int field,
1335:                    boolean currentValue) {
1336:                currFM.storeBooleanField(field, currentValue);
1337:            }
1338:
1339:            /**
1340:             * This method is called from the associated PersistenceCapable when its
1341:             * PersistenceCapable.jdoProvideFields() method is invoked. Its purpose is
1342:             * to provide the value of the specified field to the StateManager.
1343:             *
1344:             * @param pc   the calling PersistenceCapable instance
1345:             * @param field   the field number
1346:             * @param currentValue   the current value of the field
1347:             */
1348:
1349:            public void providedByteField(PersistenceCapable pc, int field,
1350:                    byte currentValue) {
1351:                currFM.storeByteField(field, currentValue);
1352:            }
1353:
1354:            /**
1355:             * This method is called from the associated PersistenceCapable when its
1356:             * PersistenceCapable.jdoProvideFields() method is invoked. Its purpose is
1357:             * to provide the value of the specified field to the StateManager.
1358:             *
1359:             * @param pc   the calling PersistenceCapable instance
1360:             * @param field   the field number
1361:             * @param currentValue   the current value of the field
1362:             */
1363:
1364:            public void providedCharField(PersistenceCapable pc, int field,
1365:                    char currentValue) {
1366:                currFM.storeCharField(field, currentValue);
1367:            }
1368:
1369:            /**
1370:             * This method is called from the associated PersistenceCapable when its
1371:             * PersistenceCapable.jdoProvideFields() method is invoked. Its purpose is
1372:             * to provide the value of the specified field to the StateManager.
1373:             *
1374:             * @param pc   the calling PersistenceCapable instance
1375:             * @param field   the field number
1376:             * @param currentValue   the current value of the field
1377:             */
1378:
1379:            public void providedDoubleField(PersistenceCapable pc, int field,
1380:                    double currentValue) {
1381:                currFM.storeDoubleField(field, currentValue);
1382:            }
1383:
1384:            /**
1385:             * This method is called from the associated PersistenceCapable when its
1386:             * PersistenceCapable.jdoProvideFields() method is invoked. Its purpose is
1387:             * to provide the value of the specified field to the StateManager.
1388:             *
1389:             * @param pc   the calling PersistenceCapable instance
1390:             * @param field   the field number
1391:             * @param currentValue   the current value of the field
1392:             */
1393:
1394:            public void providedFloatField(PersistenceCapable pc, int field,
1395:                    float currentValue) {
1396:                currFM.storeFloatField(field, currentValue);
1397:            }
1398:
1399:            /**
1400:             * This method is called from the associated PersistenceCapable when its
1401:             * PersistenceCapable.jdoProvideFields() method is invoked. Its purpose is
1402:             * to provide the value of the specified field to the StateManager.
1403:             *
1404:             * @param pc   the calling PersistenceCapable instance
1405:             * @param field   the field number
1406:             * @param currentValue   the current value of the field
1407:             */
1408:
1409:            public void providedIntField(PersistenceCapable pc, int field,
1410:                    int currentValue) {
1411:                currFM.storeIntField(field, currentValue);
1412:            }
1413:
1414:            /**
1415:             * This method is called from the associated PersistenceCapable when its
1416:             * PersistenceCapable.jdoProvideFields() method is invoked. Its purpose is
1417:             * to provide the value of the specified field to the StateManager.
1418:             *
1419:             * @param pc   the calling PersistenceCapable instance
1420:             * @param field   the field number
1421:             * @param currentValue   the current value of the field
1422:             */
1423:
1424:            public void providedLongField(PersistenceCapable pc, int field,
1425:                    long currentValue) {
1426:                currFM.storeLongField(field, currentValue);
1427:            }
1428:
1429:            /**
1430:             * This method is called from the associated PersistenceCapable when its
1431:             * PersistenceCapable.jdoProvideFields() method is invoked. Its purpose is
1432:             * to provide the value of the specified field to the StateManager.
1433:             *
1434:             * @param pc   the calling PersistenceCapable instance
1435:             * @param field   the field number
1436:             * @param currentValue   the current value of the field
1437:             */
1438:
1439:            public void providedShortField(PersistenceCapable pc, int field,
1440:                    short currentValue) {
1441:                currFM.storeShortField(field, currentValue);
1442:            }
1443:
1444:            /**
1445:             * This method is called from the associated PersistenceCapable when its
1446:             * PersistenceCapable.jdoProvideFields() method is invoked. Its purpose is
1447:             * to provide the value of the specified field to the StateManager.
1448:             *
1449:             * @param pc   the calling PersistenceCapable instance
1450:             * @param field   the field number
1451:             * @param currentValue   the current value of the field
1452:             */
1453:
1454:            public void providedStringField(PersistenceCapable pc, int field,
1455:                    String currentValue) {
1456:                currFM.storeStringField(field, currentValue);
1457:            }
1458:
1459:            /**
1460:             * This method is called from the associated PersistenceCapable when its
1461:             * PersistenceCapable.jdoProvideFields() method is invoked. Its purpose is
1462:             * to provide the value of the specified field to the StateManager.
1463:             *
1464:             * @param pc   the calling PersistenceCapable instance
1465:             * @param field   the field number
1466:             * @param currentValue   the current value of the field
1467:             */
1468:
1469:            public void providedObjectField(PersistenceCapable pc, int field,
1470:                    Object currentValue) {
1471:                currFM.storeObjectField(field, currentValue);
1472:            }
1473:
1474:            /**
1475:             * This method is invoked by the PersistenceCapable object's
1476:             * jdoReplaceField() method to refresh the value of a boolean field.
1477:             *
1478:             * @param pc the calling PersistenceCapable instance
1479:             * @param field the field number
1480:             * @return the new value for the field
1481:             */
1482:
1483:            public boolean replacingBooleanField(PersistenceCapable pc,
1484:                    int field) {
1485:                boolean value = currFM.fetchBooleanField(field);
1486:                loadedFields[field] = true;
1487:
1488:                return value;
1489:            }
1490:
1491:            /**
1492:             * This method is invoked by the PersistenceCapable object's
1493:             * jdoReplaceField() method to refresh the value of a byte field.
1494:             *
1495:             * @param obj the calling PersistenceCapable instance
1496:             * @param field the field number
1497:             * @return the new value for the field
1498:             */
1499:
1500:            public byte replacingByteField(PersistenceCapable obj, int field) {
1501:                byte value = currFM.fetchByteField(field);
1502:                loadedFields[field] = true;
1503:
1504:                return value;
1505:            }
1506:
1507:            /**
1508:             * This method is invoked by the PersistenceCapable object's
1509:             * jdoReplaceField() method to refresh the value of a char field.
1510:             *
1511:             * @param obj the calling PersistenceCapable instance
1512:             * @param field the field number
1513:             * @return the new value for the field
1514:             */
1515:
1516:            public char replacingCharField(PersistenceCapable obj, int field) {
1517:                char value = currFM.fetchCharField(field);
1518:                loadedFields[field] = true;
1519:
1520:                return value;
1521:            }
1522:
1523:            /**
1524:             * This method is invoked by the PersistenceCapable object's
1525:             * jdoReplaceField() method to refresh the value of a double field.
1526:             *
1527:             * @param obj the calling PersistenceCapable instance
1528:             * @param field the field number
1529:             * @return the new value for the field
1530:             */
1531:
1532:            public double replacingDoubleField(PersistenceCapable obj, int field) {
1533:                double value = currFM.fetchDoubleField(field);
1534:                loadedFields[field] = true;
1535:
1536:                return value;
1537:            }
1538:
1539:            /**
1540:             * This method is invoked by the PersistenceCapable object's
1541:             * jdoReplaceField() method to refresh the value of a float field.
1542:             *
1543:             * @param obj the calling PersistenceCapable instance
1544:             * @param field the field number
1545:             * @return the new value for the field
1546:             */
1547:
1548:            public float replacingFloatField(PersistenceCapable obj, int field) {
1549:                float value = currFM.fetchFloatField(field);
1550:                loadedFields[field] = true;
1551:
1552:                return value;
1553:            }
1554:
1555:            /**
1556:             * This method is invoked by the PersistenceCapable object's
1557:             * jdoReplaceField() method to refresh the value of a int field.
1558:             *
1559:             * @param obj the calling PersistenceCapable instance
1560:             * @param field the field number
1561:             * @return the new value for the field
1562:             */
1563:
1564:            public int replacingIntField(PersistenceCapable obj, int field) {
1565:                int value = currFM.fetchIntField(field);
1566:                loadedFields[field] = true;
1567:
1568:                return value;
1569:            }
1570:
1571:            /**
1572:             * This method is invoked by the PersistenceCapable object's
1573:             * jdoReplaceField() method to refresh the value of a long field.
1574:             *
1575:             * @param obj the calling PersistenceCapable instance
1576:             * @param field the field number
1577:             * @return the new value for the field
1578:             */
1579:
1580:            public long replacingLongField(PersistenceCapable obj, int field) {
1581:                long value = currFM.fetchLongField(field);
1582:                loadedFields[field] = true;
1583:
1584:                return value;
1585:            }
1586:
1587:            /**
1588:             * This method is invoked by the PersistenceCapable object's
1589:             * jdoReplaceField() method to refresh the value of a short field.
1590:             *
1591:             * @param obj the calling PersistenceCapable instance
1592:             * @param field the field number
1593:             * @return the new value for the field
1594:             */
1595:
1596:            public short replacingShortField(PersistenceCapable obj, int field) {
1597:                short value = currFM.fetchShortField(field);
1598:                loadedFields[field] = true;
1599:
1600:                return value;
1601:            }
1602:
1603:            /**
1604:             * This method is invoked by the PersistenceCapable object's
1605:             * jdoReplaceField() method to refresh the value of a String field.
1606:             *
1607:             * @param obj the calling PersistenceCapable instance
1608:             * @param field the field number
1609:             * @return the new value for the field
1610:             */
1611:
1612:            public String replacingStringField(PersistenceCapable obj, int field) {
1613:                String value = currFM.fetchStringField(field);
1614:                loadedFields[field] = true;
1615:
1616:                return value;
1617:            }
1618:
1619:            /**
1620:             * This method is invoked by the PersistenceCapable object's
1621:             * jdoReplaceField() method to refresh the value of an Object field.
1622:             *
1623:             * @param obj the calling PersistenceCapable instance
1624:             * @param field the field number
1625:             * @return the new value for the field
1626:             */
1627:
1628:            public Object replacingObjectField(PersistenceCapable obj, int field) {
1629:                Object value = currFM.fetchObjectField(field);
1630:                loadedFields[field] = true;
1631:
1632:                return value;
1633:            }
1634:
1635:            public PersistenceCapable getObject() {
1636:                return myPC;
1637:            }
1638:
1639:            private synchronized Object provideField(PersistenceCapable pc,
1640:                    int fieldNumber) {
1641:                Object obj;
1642:
1643:                FieldManager prevFM = currFM;
1644:                currFM = new StateFieldManager();
1645:
1646:                try {
1647:                    pc.jdoProvideField(fieldNumber);
1648:                    return currFM.fetchObjectField(fieldNumber);
1649:                } finally {
1650:                    currFM = prevFM;
1651:                }
1652:            }
1653:
1654:            private synchronized void replaceField(PersistenceCapable pc,
1655:                    int fieldNumber, final Object value) {
1656:                FieldManager prevFM = currFM;
1657:                currFM = new GenericFieldManager() {
1658:                    public Object fetchObjectField(int field) {
1659:                        return value;
1660:                    }
1661:
1662:                    public void storeObjectField(int field, Object value) {
1663:                    } // not possible
1664:                };
1665:
1666:                try {
1667:                    pc.jdoReplaceField(fieldNumber);
1668:                } finally {
1669:                    currFM = prevFM;
1670:                }
1671:            }
1672:
1673:            /**
1674:             * Called from the StoreManager after StoreManager.update() is called to obtain
1675:             * updated values from the PersistenceCapable associated with this StateManager.
1676:             *
1677:             * @param fieldNumbers
1678:             *   An array of field numbers to be updated by the Store
1679:             * @param fm
1680:             *   The updated values are stored in this object. This object is only valid
1681:             *   for the duration of this call.
1682:             */
1683:
1684:            public synchronized void provideFields(int fieldNumbers[],
1685:                    FieldManager fm) {
1686:                FieldManager prevFM = currFM;
1687:                currFM = fm;
1688:
1689:                try {
1690:                    myPC.jdoProvideFields(fieldNumbers);
1691:                } finally {
1692:                    currFM = prevFM;
1693:                }
1694:            }
1695:
1696:            /**
1697:             * Called to refresh data in the PersistenceCapable object associated with
1698:             * this StateManager.
1699:             * <p>
1700:             * Unwrapped values for SCO fields are wrapped with an appropriate SCO
1701:             * wrapper object.
1702:             *
1703:             * @param fieldNumbers
1704:             *      An array of field numbers to be refreshed.
1705:             * @param fm
1706:             *      Provides the updated values. This object is only used for the
1707:             *      duration of the call.
1708:             */
1709:
1710:            public synchronized void replaceFields(int fieldNumbers[],
1711:                    FieldManager fm) {
1712:                replaceFieldsInternal(fieldNumbers, new SCOWrapper(fm, this ,
1713:                        secondClassMutableFields));
1714:            }
1715:
1716:            private synchronized void replaceFieldsInternal(int fieldNumbers[],
1717:                    FieldManager fm) {
1718:                FieldManager prevFM = currFM;
1719:                currFM = fm;
1720:
1721:                try {
1722:                    myPC.jdoReplaceFields(fieldNumbers);
1723:                } finally {
1724:                    currFM = prevFM;
1725:                }
1726:            }
1727:
1728:            private void preStateChange() {
1729:                changingState = true;
1730:            }
1731:
1732:            private void postStateChange() {
1733:                changingState = false;
1734:
1735:                if (postLoadPending) {
1736:                    postLoadPending = false;
1737:                    postLoad();
1738:                }
1739:            }
1740:
1741:            /**
1742:             * Makes the instance persistent.
1743:             * If the object is already persistent, this method does nothing.
1744:             * Otherwise, a new object ID for the instance is obtained from the store
1745:             * manager and the object is inserted in the data store.
1746:             * <p>
1747:             * Any failure will leave the instance in its previous life-cycle state.
1748:             *
1749:             * @return
1750:             *      <code>true</code> if the object was successfully made persistent,
1751:             *      <code>false</code> if the object was already persistent.
1752:             */
1753:
1754:            public boolean makePersistent() {
1755:                if (myLC.isPersistent())
1756:                    return false;
1757:
1758:                LifeCycleState oldLC = myLC;
1759:                preStateChange();
1760:                try {
1761:                    myLC = myLC.transitionMakePersistent(this , myTX);
1762:                } finally {
1763:                    postStateChange();
1764:                }
1765:
1766:                boolean succeeded = false;
1767:
1768:                try {
1769:                    myID = srm.newObjectID(myPC.getClass());
1770:
1771:                    if (inserting)
1772:                        throw new JDOFatalInternalException(
1773:                                "makePersistent() called recursively");
1774:
1775:                    inserting = true;
1776:
1777:                    try {
1778:                        if (myPC instanceof  InstanceCallbacks)
1779:                            ((InstanceCallbacks) myPC).jdoPreStore();
1780:
1781:                        srm.insert(this );
1782:                    } finally {
1783:                        inserting = false;
1784:                    }
1785:
1786:                    succeeded = true;
1787:                } finally {
1788:                    if (!succeeded) {
1789:                        preStateChange();
1790:                        try {
1791:                            myLC = myLC.transitionRollbackState(this , oldLC);
1792:                        } finally {
1793:                            postStateChange();
1794:                        }
1795:
1796:                        myID = null;
1797:                    }
1798:                }
1799:
1800:                myPM.dataStoreModified();
1801:
1802:                return true;
1803:            }
1804:
1805:            private void transitionReadField() {
1806:                preStateChange();
1807:                try {
1808:                    myLC = myLC.transitionReadField(this , myTX);
1809:                } finally {
1810:                    postStateChange();
1811:                }
1812:            }
1813:
1814:            private void transitionWriteField() {
1815:                preStateChange();
1816:                try {
1817:                    myLC = myLC.transitionWriteField(this , myTX);
1818:                } finally {
1819:                    postStateChange();
1820:                }
1821:            }
1822:
1823:            public void makeTransactional() {
1824:                preStateChange();
1825:                try {
1826:                    myLC = myLC.transitionMakeTransactional(this , myTX);
1827:                } finally {
1828:                    postStateChange();
1829:                }
1830:            }
1831:
1832:            public void makeNontransactional() {
1833:                preStateChange();
1834:                try {
1835:                    myLC = myLC.transitionMakeNontransactional(this );
1836:                } finally {
1837:                    postStateChange();
1838:                }
1839:            }
1840:
1841:            public void makeTransient() {
1842:                preStateChange();
1843:                try {
1844:                    myLC = myLC.transitionMakeTransient(this );
1845:                } finally {
1846:                    postStateChange();
1847:                }
1848:            }
1849:
1850:            public void evict() {
1851:                preStateChange();
1852:                try {
1853:                    myLC = myLC.transitionEvict(this );
1854:                } finally {
1855:                    postStateChange();
1856:                }
1857:            }
1858:
1859:            public void refresh() {
1860:                preStateChange();
1861:                try {
1862:                    myLC = myLC.transitionRefresh(this , myTX);
1863:                } finally {
1864:                    postStateChange();
1865:                }
1866:            }
1867:
1868:            public void retrieve(boolean DFGOnly) {
1869:                preStateChange();
1870:                try {
1871:                    myLC = myLC.transitionRetrieve(this , myTX, DFGOnly);
1872:                } finally {
1873:                    postStateChange();
1874:                }
1875:            }
1876:
1877:            /**
1878:             * This method is invoked when a commit is performed in a Transaction
1879:             * involving the PersistenceCapable managed by this StateManager
1880:             */
1881:
1882:            public void postCommit() {
1883:                preStateChange();
1884:                try {
1885:                    myLC = myLC.transitionCommit(this , myTX);
1886:                } finally {
1887:                    postStateChange();
1888:                }
1889:            }
1890:
1891:            /**
1892:             * This method is invoked when a rollback is performed in a Transaction
1893:             * involving the PersistenceCapable managed by this StateManager.
1894:             */
1895:
1896:            public void preRollback() {
1897:                preStateChange();
1898:                try {
1899:                    myLC = myLC.transitionRollback(this , myTX);
1900:                } finally {
1901:                    postStateChange();
1902:                }
1903:            }
1904:
1905:            void preDelete() {
1906:                if (myPC instanceof  InstanceCallbacks)
1907:                    ((InstanceCallbacks) myPC).jdoPreDelete();
1908:            }
1909:
1910:            /**
1911:             * Deletes the instance.
1912:             * If the object is already deleted, this method does nothing.
1913:             * Otherwise, the object is removed from the data store.
1914:             * <p>
1915:             * Any failure will leave the instance in its previous life-cycle state.
1916:             */
1917:
1918:            public void deletePersistent() {
1919:                if (myLC.isDeleted())
1920:                    return;
1921:
1922:                if (deleting)
1923:                    throw new JDOFatalInternalException(
1924:                            "deletePersistent() called recursively");
1925:
1926:                deleting = true;
1927:
1928:                try {
1929:                    LifeCycleState oldLC = myLC;
1930:                    preStateChange();
1931:                    try {
1932:                        myLC = myLC.transitionDeletePersistent(this , myTX);
1933:                    } finally {
1934:                        postStateChange();
1935:                    }
1936:
1937:                    boolean succeeded = false;
1938:
1939:                    try {
1940:                        srm.delete(this );
1941:                        clearLoadedFlags();
1942:
1943:                        succeeded = true;
1944:                    } finally {
1945:                        if (!succeeded) {
1946:                            preStateChange();
1947:                            try {
1948:                                myLC = myLC
1949:                                        .transitionRollbackState(this , oldLC);
1950:                            } finally {
1951:                                postStateChange();
1952:                            }
1953:                        }
1954:                    }
1955:                } finally {
1956:                    deleting = false;
1957:                }
1958:
1959:                myPM.dataStoreModified();
1960:            }
1961:
1962:            /**
1963:             * Flushes any dirty fields to the data store.
1964:             *
1965:             * <p>Note that "dirty" in this case is not equated to being in the P_DIRTY
1966:             * state.  The P_DIRTY state means that at least one field in the object has
1967:             * been written by the user during the current transaction, whereas for the
1968:             * purposes of this method, a field is "dirty" if it's been written by the
1969:             * user but not yet updated in the data store.  The difference is, it's
1970:             * possible for an object's state to be P_DIRTY, yet have no "dirty" fields
1971:             * because flush() has been called at least once during the transaction.
1972:             */
1973:
1974:            public void flush() {
1975:                if (dirty) {
1976:                    if (flushing)
1977:                        throw new JDOFatalInternalException(
1978:                                "flush() re-entered");
1979:
1980:                    flushing = true;
1981:
1982:                    try {
1983:                        if (myPC instanceof  InstanceCallbacks && !deleting)
1984:                            ((InstanceCallbacks) myPC).jdoPreStore();
1985:
1986:                        int[] dirtyFieldNumbers = getFlagsSetTo(dirtyFields,
1987:                                true);
1988:
1989:                        if (dirtyFieldNumbers == null)
1990:                            throw new JDOFatalInternalException(
1991:                                    "dirty == true but no fields are marked dirty");
1992:
1993:                        srm.update(this , dirtyFieldNumbers);
1994:
1995:                        clearDirtyFlags();
1996:                    } finally {
1997:                        flushing = false;
1998:                    }
1999:
2000:                    myPM.dataStoreModified();
2001:                }
2002:            }
2003:
2004:            void disconnect() {
2005:                if (LOG.isDebugEnabled())
2006:                    LOG.debug("Disconnecting " + toJVMIDString(myPC) + " from "
2007:                            + this );
2008:
2009:                disownSCOFields();
2010:                myPM.removeStateManager(this );
2011:                jdoFlags = PersistenceCapable.READ_WRITE_OK;
2012:                myPC.jdoReplaceFlags();
2013:
2014:                disconnecting = true;
2015:
2016:                try {
2017:                    myPC.jdoReplaceStateManager(null);
2018:                } finally {
2019:                    disconnecting = false;
2020:                }
2021:
2022:                discardSavedFields();
2023:                myPM = null;
2024:                myPC = null;
2025:                myID = null;
2026:                myLC = null;
2027:                cmd = null;
2028:                srm = null;
2029:            }
2030:
2031:            public String toString() {
2032:                if (myPC == null)
2033:                    return "StateManager@" + System.identityHashCode(this )
2034:                            + "(disconnected)";
2035:                else {
2036:                    String pcClassName = myPC.getClass().getName();
2037:
2038:                    return "StateManager:"
2039:                            + pcClassName.substring(pcClassName
2040:                                    .lastIndexOf('.') + 1) + '@'
2041:                            + System.identityHashCode(myPC) + '(' + myID + ')';
2042:                }
2043:            }
2044:
2045:            /* ------------------------ debugging helper methods -------------------- */
2046:
2047:            private static String toJVMIDString(Object obj) {
2048:                if (obj == null)
2049:                    return "null";
2050:                else
2051:                    return obj.getClass().getName() + '@'
2052:                            + System.identityHashCode(obj);
2053:            }
2054:
2055:            private static String booleanArrayToString(boolean[] ba) {
2056:                if (ba == null)
2057:                    return "null";
2058:
2059:                StringBuffer sb = new StringBuffer("[");
2060:
2061:                for (int i = 0; i < ba.length; ++i)
2062:                    sb.append(ba[i] ? 'Y' : 'N');
2063:
2064:                sb.append(']');
2065:
2066:                return sb.toString();
2067:            }
2068:
2069:            private static String intArrayToString(int[] ia) {
2070:                if (ia == null)
2071:                    return "null";
2072:
2073:                StringBuffer sb = new StringBuffer("[");
2074:
2075:                for (int i = 0; i < ia.length; ++i) {
2076:                    if (i > 0)
2077:                        sb.append(',');
2078:
2079:                    sb.append(ia[i]);
2080:                }
2081:
2082:                sb.append(']');
2083:
2084:                return sb.toString();
2085:            }
2086:
2087:            private static String jdoFlagsToString(byte flags) {
2088:                switch (flags) {
2089:                case PersistenceCapable.LOAD_REQUIRED:
2090:                    return "LOAD_REQUIRED";
2091:                case PersistenceCapable.READ_OK:
2092:                    return "READ_OK";
2093:                case PersistenceCapable.READ_WRITE_OK:
2094:                    return "READ_WRITE_OK";
2095:                default:
2096:                    return "???";
2097:                }
2098:            }
2099:
2100:            private static void dumpPC(PersistenceCapable pc, PrintWriter out) {
2101:                out.println(toJVMIDString(pc));
2102:
2103:                if (pc == null)
2104:                    return;
2105:
2106:                out.print("jdoStateManager = ");
2107:                out.println(peekField(pc, "jdoStateManager"));
2108:                out.print("jdoFlags = ");
2109:                Object flagsObj = peekField(pc, "jdoFlags");
2110:
2111:                if (flagsObj instanceof  Byte)
2112:                    out
2113:                            .println(jdoFlagsToString(((Byte) flagsObj)
2114:                                    .byteValue()));
2115:                else
2116:                    out.println(flagsObj);
2117:
2118:                Class c = pc.getClass();
2119:
2120:                do {
2121:                    String[] fieldNames = helper.getFieldNames(c);
2122:
2123:                    for (int i = 0; i < fieldNames.length; ++i) {
2124:                        out.print(fieldNames[i]);
2125:                        out.print(" = ");
2126:                        out.println(peekField(pc, fieldNames[i]));
2127:                    }
2128:
2129:                    c = c.getSuperclass();
2130:                } while (c != null
2131:                        && PersistenceCapable.class.isAssignableFrom(c));
2132:            }
2133:
2134:            private static Object peekField(Object obj, String fieldName) {
2135:                try {
2136:                    /*
2137:                     * This doesn't work due to security problems but you get the idea.
2138:                     * I'm trying to get field values directly without going through
2139:                     * the provideField machinery.
2140:                     */
2141:                    Object value = obj.getClass().getDeclaredField(fieldName)
2142:                            .get(obj);
2143:
2144:                    if (value instanceof  PersistenceCapable)
2145:                        return toJVMIDString(value);
2146:                    else
2147:                        return value;
2148:                } catch (Exception e) {
2149:                    return e.toString();
2150:                }
2151:            }
2152:
2153:            public void dump(PrintWriter out) {
2154:                out.print("myPM = ");
2155:                out.println(myPM);
2156:                out.print("myTX = ");
2157:                out.println(myTX);
2158:                out.print("myID = ");
2159:                out.println(myID);
2160:                out.print("myLC = ");
2161:                out.println(myLC);
2162:                out.print("cmd = ");
2163:                out.println(cmd);
2164:                out.print("srm = ");
2165:                out.println(srm);
2166:                out.print("fieldCount = ");
2167:                out.println(fieldCount);
2168:                out.print("dirty = ");
2169:                out.println(dirty);
2170:                out.print("flushing = ");
2171:                out.println(flushing);
2172:                out.print("changingState = ");
2173:                out.println(changingState);
2174:                out.print("postLoadPending = ");
2175:                out.println(postLoadPending);
2176:                out.print("disconnecting = ");
2177:                out.println(disconnecting);
2178:                out.print("dirtyFields = ");
2179:                out.println(booleanArrayToString(dirtyFields));
2180:                out.print("defaultFetchGroupFields = ");
2181:                out.println(booleanArrayToString(defaultFetchGroupFields));
2182:                out.print("secondClassMutableFields = ");
2183:                out.println(booleanArrayToString(secondClassMutableFields));
2184:                out.print("allFieldNumbers = ");
2185:                out.println(intArrayToString(allFieldNumbers));
2186:                out.print("persistentFieldNumbers = ");
2187:                out.println(intArrayToString(persistentFieldNumbers));
2188:                out.print("defaultFetchGroupFieldNumbers = ");
2189:                out.println(intArrayToString(defaultFetchGroupFieldNumbers));
2190:                out.print("secondClassMutableFieldNumbers = ");
2191:                out.println(intArrayToString(secondClassMutableFieldNumbers));
2192:
2193:                out.println();
2194:                out.print("jdoFlags = ");
2195:                out.println(jdoFlagsToString(jdoFlags));
2196:                out.print("loadedFields = ");
2197:                out.println(booleanArrayToString(loadedFields));
2198:                out.print("myPC = ");
2199:                dumpPC(myPC, out);
2200:
2201:                out.println();
2202:                out.print("savedFlags = ");
2203:                out.println(jdoFlagsToString(savedFlags));
2204:                out.print("savedLoadedFields = ");
2205:                out.println(booleanArrayToString(savedLoadedFields));
2206:                out.print("savedImage = ");
2207:                dumpPC(savedImage, out);
2208:            }
2209:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.