Source Code Cross Referenced for PCStateMan.java in  » Testing » PolePosition-0.20 » com » versant » core » jdo » 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 » Testing » PolePosition 0.20 » com.versant.core.jdo 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright (c) 1998 - 2005 Versant Corporation
0003:         * All rights reserved. This program and the accompanying materials
0004:         * are made available under the terms of the Eclipse Public License v1.0
0005:         * which accompanies this distribution, and is available at
0006:         * http://www.eclipse.org/legal/epl-v10.html
0007:         *
0008:         * Contributors:
0009:         * Versant Corporation - initial API and implementation
0010:         */
0011:        package com.versant.core.jdo;
0012:
0013:        import com.versant.core.common.Debug;
0014:        import com.versant.core.common.Utils;
0015:        import com.versant.core.metadata.*;
0016:        import com.versant.core.common.NewObjectOID;
0017:        import com.versant.core.common.OID;
0018:        import com.versant.core.common.*;
0019:        import com.versant.core.jdo.sco.VersantSimpleSCO;
0020:
0021:        import javax.jdo.InstanceCallbacks;
0022:        import javax.jdo.PersistenceManager;
0023:        import javax.jdo.spi.JDOImplHelper;
0024:        import javax.jdo.spi.PersistenceCapable;
0025:        import javax.jdo.spi.StateManager;
0026:        import java.util.Collection;
0027:        import java.util.Iterator;
0028:        import java.util.Map;
0029:
0030:        import com.versant.core.common.BindingSupportImpl;
0031:
0032:        /**
0033:         * JDO Genie State manager.
0034:         */
0035:        public final class PCStateMan implements  VersantStateManager {
0036:
0037:            private static final int EVENT_ROLLBACK = 0;
0038:            private static final int EVENT_COMMIT = 1;
0039:
0040:            private static final int STATE_TRANSIENT = 0;
0041:            private static final int STATE_T_CLEAN = 8;
0042:            private static final int STATE_T_DIRTY = 12;
0043:            private static final int STATE_HOLLOW = 16;
0044:            private static final int STATE_P_NON_TX = STATE_HOLLOW;
0045:            private static final int STATE_P_CLEAN = 24;
0046:            private static final int STATE_P_DIRTY = 28;
0047:            private static final int STATE_P_DEL = 29;
0048:            private static final int STATE_P_NEW = 30;
0049:            private static final int STATE_P_NEW_DEL = 31;
0050:
0051:            private static final int MASK_DELETE = 1;
0052:            private static final int MASK_NEW = 2;
0053:            private static final int MASK_DIRTY = 4;
0054:            private static final int MASK_TX = 8;
0055:            private static final int MASK_PERSISTENT = 16;
0056:
0057:            private static final int MASK_DELETE_TX_DIRTY = MASK_DELETE
0058:                    + MASK_TX + MASK_DIRTY;
0059:
0060:            private boolean readInTx;
0061:
0062:            private static DeletedState DELETED_STATE = new DeletedState();
0063:            private static InitState INIT_STATE = new InitState();
0064:
0065:            /**
0066:             * The current values.
0067:             */
0068:            public State state;
0069:            /**
0070:             * This state is kept if concurrency checking is done by using changed checking.
0071:             */
0072:            private State origState;
0073:            /**
0074:             * This is used to rollback to.
0075:             */
0076:            private State beforeState;
0077:            /**
0078:             * This is used to carry the fields to store to the server. This must later
0079:             * be replaced by an pool.
0080:             */
0081:            private State toStoreState;
0082:            /**
0083:             * This is used for stores that require that all fake and ref fields are
0084:             * sent to the server for reads on secondary fields stored as SCOs in VDS.
0085:             */
0086:            private State forReadState;
0087:            /**
0088:             * The PersistenceCapable instance that is managed.
0089:             */
0090:            public PersistenceCapable pc;
0091:            /**
0092:             * The OID of the managed instance.
0093:             */
0094:            public OID oid;
0095:            /**
0096:             * The loadedFields of the managed instance.
0097:             */
0098:            private boolean[] loadedFields;
0099:            /**
0100:             * The classmetadata for the managed instance.
0101:             */
0102:            private ClassMetaData classMetaData;
0103:            /**
0104:             * field to replace the flags of the pc instance.
0105:             */
0106:            private byte jdoFlags = PersistenceCapable.LOAD_REQUIRED;
0107:            /**
0108:             * A mask field that specifies the current lifecycle.
0109:             */
0110:            private int stateM;
0111:            /**
0112:             * A flag that is set if this instance is to be evicted at commit.
0113:             */
0114:            public boolean toBeEvictedFlag;
0115:            /**
0116:             * If the pc instance is of type InstanceCallbacks then this will be an already casted
0117:             * ref.
0118:             */
0119:
0120:            private InstanceCallbacks instanceCallbacks;
0121:
0122:            public final QueryStateWrapper queryStateWrapper;
0123:
0124:            private PMProxy pm;
0125:            private ModelMetaData jmd;
0126:
0127:            /**
0128:             * The wrapper for this instance in the managed cache.
0129:             */
0130:            public PMCacheEntry cacheEntry;
0131:
0132:            private LocalPMCache jdoManagedCache;
0133:
0134:            private final JDOImplHelper jdoImplHelper = JDOImplHelper
0135:                    .getInstance();
0136:            /**
0137:             * If this pc instance has been marked for deletion in this tx.
0138:             */
0139:            private boolean addedForDelete;
0140:
0141:            // These are used by JdoGeniePersistenceManagerImp to form linked lists
0142:            public PCStateMan prev;
0143:            public PCStateMan next;
0144:            public boolean inDirtyList;
0145:
0146:            public boolean doChangeChecking;
0147:            private boolean rfgLoaded;
0148:            /**
0149:             * This is to determine if the dfg has been loaded to the pc.
0150:             */
0151:            private boolean dfgLoaded;
0152:            private int[] scoFieldArray;
0153:            /**
0154:             * If this sm has been prepared in the current commit cycle. This field must
0155:             * be cleared after commit/rollback
0156:             */
0157:            private int preparedStatus;
0158:
0159:            /**
0160:             * If this is not null then this is an embedded sm.
0161:             */
0162:            public ClassMetaData owner;
0163:
0164:            private VersantPersistenceManagerImp getPm() {
0165:                return pm.getRealPM();
0166:            }
0167:
0168:            public PMProxy getPmProxy() {
0169:                return pm;
0170:            }
0171:
0172:            public PCStateMan(LocalPMCache jdoManagedCache, ModelMetaData jmd,
0173:                    PMProxy perMan) {
0174:                this .jdoManagedCache = jdoManagedCache;
0175:                this .jmd = jmd;
0176:                this .pm = perMan;
0177:                queryStateWrapper = new QueryStateWrapper(this , perMan);
0178:            }
0179:
0180:            private void init(PersistenceCapable pc, OID oid, ClassMetaData cmd) {
0181:
0182:                if (pc instanceof  InstanceCallbacks) {
0183:                    instanceCallbacks = (InstanceCallbacks) pc;
0184:                }
0185:
0186:                this .classMetaData = cmd;
0187:                scoFieldArray = new int[classMetaData.scoFieldNos.length];
0188:                queryStateWrapper.setCmd(cmd);
0189:                this .pc = pc;
0190:                this .oid = oid;
0191:
0192:                origState = cmd.createState();
0193:                origState.setClassMetaData(cmd);
0194:
0195:                state = cmd.createState();
0196:                state.setClassMetaData(cmd);
0197:                loadedFields = new boolean[cmd.stateFields.length];
0198:                doChangeChecking = classMetaData.changedOptimisticLocking;
0199:            }
0200:
0201:            private State createStateImp() {
0202:                State state = classMetaData.createState();
0203:                state.setClassMetaData(classMetaData);
0204:                return state;
0205:            }
0206:
0207:            private State createToStoreState() {
0208:                if (toStoreState == null) {
0209:                    toStoreState = classMetaData.createState();
0210:                    toStoreState.setClassMetaData(classMetaData);
0211:                } else {
0212:                    toStoreState.clear();
0213:                }
0214:                return toStoreState;
0215:            }
0216:
0217:            /**
0218:             * This initialises the pcStateObject when it is being pushed in from the server
0219:             * as a by product of a query or navigation.
0220:             */
0221:            public void init(OID oid, ClassMetaData cmd, State aState,
0222:                    VersantPersistenceManagerImp rpm) {
0223:                init(jdoImplHelper.newInstance(cmd.cls, rpm
0224:                        .createStateManagerProxy(this )), oid, cmd);
0225:                oid.resolve(aState);
0226:                state.updateNonFilled(aState);
0227:                updated(rpm, false);
0228:                maintainOrigState(aState, rpm);
0229:                setLoadRequired();
0230:                if (cmd.identityType == MDStatics.IDENTITY_TYPE_APPLICATION) {
0231:                    state.copyFields(oid);
0232:                    pc.jdoReplaceFields(classMetaData.pkFieldNos);
0233:                }
0234:            }
0235:
0236:            public EmbeddedStateManager createEmbeddedSM(FieldMetaData fmd) {
0237:                EmbeddedStateManager embeddedSm = new EmbeddedStateManager(
0238:                        this , jmd, jdoImplHelper, fmd);
0239:                embeddedSm.setLoadRequired();
0240:                return embeddedSm;
0241:            }
0242:
0243:            public EmbeddedStateManager createEmbeddedSM(
0244:                    PersistenceCapable embeddedPC, FieldMetaData fmd) {
0245:                EmbeddedStateManager embeddedSm = new EmbeddedStateManager(
0246:                        this , embeddedPC, jmd, fmd);
0247:                embeddedPC.jdoReplaceStateManager(embeddedSm);
0248:                //ask for all the data from the embedded instance
0249:                embeddedPC
0250:                        .jdoProvideFields(embeddedSm.cmd.allManagedFieldNosArray);
0251:                embeddedSm.setLoadRequired();
0252:                return embeddedSm;
0253:            }
0254:
0255:            public void init(VersantDetachable d, OID oid,
0256:                    VersantPersistenceManagerImp rpm) {
0257:                ClassMetaData cmd = oid.getAvailableClassMetaData();
0258:                init(pc, oid, cmd);
0259:                d.jdoReplaceStateManager(this );
0260:                d.jdoProvideFields(cmd.allManagedFieldNosArray);
0261:                d.jdoReplaceStateManager(null);
0262:                pc = jdoImplHelper.newInstance(cmd.cls, rpm
0263:                        .createStateManagerProxy(this ));
0264:                stateM = STATE_P_NEW;
0265:            }
0266:
0267:            public ClassMetaData getClassMetaData() {
0268:                return classMetaData;
0269:            }
0270:
0271:            private final void maintainOrigState(State toCopy,
0272:                    VersantPersistenceManagerImp rpm) {
0273:                if (doChangeChecking) {
0274:                    origState.copyFieldsForOptimisticLocking(toCopy, rpm);
0275:                } else {
0276:                    origState.copyOptimisticLockingField(toCopy);
0277:                }
0278:            }
0279:
0280:            /**
0281:             * This is to create a hollow sm for a getObjectById with validate = false.
0282:             * Must the oid be resolved.
0283:             *
0284:             * @param oid
0285:             */
0286:            public void init(OID oid, VersantPersistenceManagerImp rpm) {
0287:                if (!oid.isResolved()
0288:                        && oid.getAvailableClassMetaData().isInHeirachy()) {
0289:                    throw BindingSupportImpl
0290:                            .getInstance()
0291:                            .internal(
0292:                                    "The oid '"
0293:                                            + oid.toStringImp()
0294:                                            + "' is not resolved to a exact instance type");
0295:                }
0296:                ClassMetaData cmd = oid.getAvailableClassMetaData();
0297:                init(jdoImplHelper.newInstance(cmd.cls, this ), oid, cmd);
0298:                oid.resolve(state);
0299:                jdoManagedCache.createCacheKey(this );
0300:
0301:                setLoadRequired();
0302:                if (cmd.identityType == MDStatics.IDENTITY_TYPE_APPLICATION) {
0303:                    state.copyFields(oid);
0304:                    pc.jdoReplaceFields(classMetaData.pkFieldNos);
0305:                    updated(rpm, false);
0306:                } else {
0307:                    stateM = STATE_HOLLOW;
0308:                }
0309:            }
0310:
0311:            /**
0312:             * This is to init the sm for a new OID. Therefore either an P-New instance
0313:             * or a transient instance.
0314:             * <p/>
0315:             * TODO must test a transient instance that refs other instances. What must happen to them.
0316:             * Must they also propagate to transient.
0317:             */
0318:            public void init(PersistenceCapable pc, OID oid,
0319:                    boolean isTransactional) {
0320:                if (Debug.DEBUG) {
0321:                    if (!oid.isNew()) {
0322:                        throw BindingSupportImpl.getInstance().internal(
0323:                                "The oid must be of type 'new'");
0324:                    }
0325:                }
0326:                init(pc, oid, oid.getClassMetaData());
0327:                try {
0328:                    if (isTransactional) {
0329:                        stateM = STATE_T_CLEAN;
0330:                    } else {
0331:                        stateM = STATE_P_NEW;
0332:                    }
0333:
0334:                    oid.resolve(state);
0335:                    //request all the fields from the pc instance
0336:                    pc.jdoProvideFields(classMetaData.allManagedFieldNosArray);
0337:                    state.addOneToManyInverseFieldsForL2Evict(getPm());
0338:                    //fill the real-oid if possible
0339:                    getRealOIDIfAppId();
0340:                    jdoManagedCache.createCacheKey(this );
0341:
0342:                    //convert all sco fields to be to sco instance and tell pc to reload them
0343:                    replaceSCOFields();
0344:
0345:                    jdoFlags = PersistenceCapable.READ_OK;
0346:                    pc.jdoReplaceFlags();
0347:                    dfgLoaded = true;
0348:                    setAllFieldsToLoaded();
0349:                } catch (Exception e) {
0350:                    /**
0351:                     * Do clean up if exception occured.
0352:                     */
0353:                    try {
0354:                        getPm().removeTxStateObject(this );
0355:                    } catch (Exception e1) {
0356:                        //ignore
0357:                    }
0358:
0359:                    if (Debug.DEBUG) {
0360:                        Debug.ERR.println(e.getMessage());
0361:                        e.printStackTrace(Debug.ERR);
0362:                    }
0363:                    handleException(e);
0364:                }
0365:            }
0366:
0367:            public OID getOID() {
0368:                return oid;
0369:            }
0370:
0371:            public PersistenceCapable getPersistenceCapable() {
0372:                return pc;
0373:            }
0374:
0375:            /**
0376:             * This will return a internal oid created from the state if
0377:             * - app id
0378:             * - keygen == null
0379:             * or state containsvalid pk fields
0380:             *
0381:             * @return
0382:             */
0383:            public OID getRealOIDIfAppId() {
0384:                if (!oid.isNew())
0385:                    return null;
0386:                if (!classMetaData.postInsertKeyGenerator
0387:                        && classMetaData.identityType == MDStatics.IDENTITY_TYPE_APPLICATION
0388:                        && state.containsValidAppIdFields()) {
0389:                    NewObjectOID cNOid = (NewObjectOID) oid;
0390:                    if (cNOid.realOID != null)
0391:                        return cNOid.realOID;
0392:
0393:                    final OID rOid = classMetaData.createOID(true);
0394:                    state.copyKeyFields(rOid);
0395:
0396:                    /**
0397:                     * This is to keap the real oid from being gc'd.
0398:                     */
0399:                    cNOid.realOID = rOid;
0400:                    return rOid;
0401:                }
0402:                return null;
0403:            }
0404:
0405:            /**
0406:             * This will initialise for transient managed use.
0407:             *
0408:             * @param pc
0409:             * @param oid
0410:             */
0411:            public void initTransient(PersistenceCapable pc, OID oid) {
0412:                if (Debug.DEBUG) {
0413:                    if (!oid.isNew()) {
0414:                        throw BindingSupportImpl.getInstance().internal(
0415:                                "The oid must be of type 'new'");
0416:                    }
0417:                }
0418:                init(pc, oid, oid.getClassMetaData());
0419:                stateM = STATE_T_CLEAN;
0420:
0421:            }
0422:
0423:            private void replaceSCOFields() {
0424:                int count = state.replaceSCOFields(pc, getPm(), scoFieldArray);
0425:                for (int i = count - 1; i >= 0; i--) {
0426:                    pc.jdoReplaceField(scoFieldArray[i]);
0427:                }
0428:            }
0429:
0430:            public void dump() {
0431:                if (Debug.DEBUG) {
0432:                    Debug.OUT
0433:                            .println("\n\n<PCStateObject oid = "
0434:                                    + oid.toSString()
0435:                                    + "\nstateM = "
0436:                                    + stateM
0437:                                    + "\nstate = "
0438:                                    + state
0439:                                    //                    + "\nbeforeState = " + beforeState
0440:                                    + "\norigState = "
0441:                                    + origState
0442:                                    + "\nretainValues = "
0443:                                    + getPm().isRetainValues()
0444:                                    + "\nOptimistic = "
0445:                                    + getPm().isOptimistic()
0446:                                    + "\ntxActive = "
0447:                                    + getPm().isActive()
0448:                                    + "###################### end #######################\n\n");
0449:                }
0450:            }
0451:
0452:            public boolean isLoaded(PersistenceCapable pc, FieldMetaData fmd) {
0453:                if (Debug.DEBUG) {
0454:                    checkDfgLoaded();
0455:                    if (!fmd.embeddedFakeField && dfgLoaded
0456:                            && fmd.isJDODefaultFetchGroup()
0457:                            && !pm.getRealPM().isInterceptDfgFieldAccess()) {
0458:
0459:                        throw BindingSupportImpl
0460:                                .getInstance()
0461:                                .internal(
0462:                                        "Default fetch group "
0463:                                                + "fields interception is turned off, but a isLoaded "
0464:                                                + "call was still generated for it");
0465:
0466:                    }
0467:
0468:                    if ((jdoFlags == PersistenceCapable.READ_OK) && !dfgLoaded) {
0469:                        throw BindingSupportImpl.getInstance().internal(
0470:                                "READ_OK is set but the dfg is not loaded.");
0471:                    }
0472:                }
0473:
0474:                checkTxDSReadOnPNonTx();
0475:                return isLoadedImp(fmd.stateFieldNo);
0476:            }
0477:
0478:            public boolean isLoaded(PersistenceCapable pc, int field) {
0479:                return isLoaded(pc, getFMD(field));
0480:
0481:            }
0482:
0483:            public void addToProcessList() {
0484:                addToProcessList(getPm());
0485:            }
0486:
0487:            private void addToProcessList(VersantPersistenceManagerImp rpm) {
0488:                //if no active tx then ignore
0489:                if (!rpm.isActive())
0490:                    return;
0491:                pm.getRealPM().getCache().addForProcessing(this );
0492:                readInTx = true;
0493:            }
0494:
0495:            public boolean isLoadedImp(int field) {
0496:                try {
0497:                    return loadedFields[field];
0498:                } catch (Exception e) {
0499:                    handleException(e);
0500:                }
0501:                return false;
0502:            }
0503:
0504:            private void checkDfgLoaded() {
0505:                if (dfgLoaded
0506:                        && !state.containFields(classMetaData.dfgStateFieldNos)) {
0507:                    throw BindingSupportImpl
0508:                            .getInstance()
0509:                            .internal(
0510:                                    "The default Fetch Group fields"
0511:                                            + " are supposed to be loaded to the pc instance, but the state"
0512:                                            + "does not contain it");
0513:                }
0514:            }
0515:
0516:            /**
0517:             * This is the same as isLoaded but will not trigger any state
0518:             * transitions.
0519:             */
0520:            public boolean isLoadedInternal(PersistenceCapable pc, int field) {
0521:                int stateFieldNo = classMetaData.absToRel[field];
0522:                int cat = classMetaData.stateFields[stateFieldNo].category;
0523:                if (cat == MDStatics.CATEGORY_REF
0524:                        || cat == MDStatics.CATEGORY_POLYREF) {
0525:                    return loadedFields[field];
0526:                } else {
0527:                    return state.containsField(stateFieldNo);
0528:                }
0529:            }
0530:
0531:            /**
0532:             * This is to check if a user is doing a read in an dataStore tx on
0533:             * a p-non-tx instance. Such an instance must be cleared of its state
0534:             * and re-read from the store. It's state must then propagate as normal
0535:             * to P-Clean.
0536:             */
0537:            private final void checkTxDSReadOnPNonTx() {
0538:                if (isPNonTx() && getPm().isActiveDS()) {
0539:                    changeToHollowState(true);
0540:                }
0541:            }
0542:
0543:            final void setLoaded(FieldMetaData fmd) {
0544:                if (Debug.DEBUG) {
0545:                    if (!fmd.embedded && stateM != STATE_TRANSIENT
0546:                            && !state.containsField(fmd.stateFieldNo)
0547:                            && fmd.category != MDStatics.CATEGORY_TRANSACTIONAL) {
0548:                        throw BindingSupportImpl.getInstance().internal(
0549:                                "The field " + fmd.name
0550:                                        + " is not contained in the state");
0551:                    }
0552:                }
0553:                loadedFields[fmd.stateFieldNo] = true;
0554:            }
0555:
0556:            public void evict() {
0557:                switch (stateM) {
0558:                case STATE_P_CLEAN:
0559:                    changeToHollowState();
0560:                    cacheEntry.changeToRefType(jdoManagedCache.queue,
0561:                            VersantPersistenceManager.PM_CACHE_REF_TYPE_WEAK);
0562:                    break;
0563:                case STATE_P_NON_TX:
0564:                    changeToHollowState();
0565:                    cacheEntry.changeToRefType(jdoManagedCache.queue,
0566:                            VersantPersistenceManager.PM_CACHE_REF_TYPE_WEAK);
0567:                    break;
0568:                default:
0569:                    toBeEvictedFlag = true;
0570:                }
0571:            }
0572:
0573:            /**
0574:             * This is an recursive operation. It will retrieve everything that is
0575:             * reachable.
0576:             */
0577:            public void retrieve(VersantPersistenceManagerImp rpm) {
0578:                loadAllPersistentFieldsToPC(rpm);
0579:                state.retrieve(rpm);
0580:            }
0581:
0582:            /**
0583:             * This will load all the managed-persistent fields to the PC instance.
0584:             * Transactional fields are ignored.
0585:             */
0586:            private void loadAllPersistentFieldsToPC(
0587:                    VersantPersistenceManagerImp rpm) {
0588:                // A new instance does not have any lazy fields that need fetching.
0589:                if (isNew())
0590:                    return;
0591:                FetchGroup retrieveFG = classMetaData
0592:                        .getFetchGroup(FetchGroup.RETRIEVE_NAME);
0593:                if (!state.containsFetchGroup(retrieveFG)) {
0594:                    rpm.getState(oid,
0595:                            retrieveFG.sendFieldsOnFetch ? getForReadState()
0596:                                    : null, retrieveFG.index, -1, -1, false);
0597:                }
0598:
0599:                for (int i = 0; i < classMetaData.managedFields.length; i++) {
0600:                    FieldMetaData fmd = classMetaData.managedFields[i];
0601:                    if (fmd.persistenceModifier == MDStatics.PERSISTENCE_MODIFIER_PERSISTENT) {
0602:                        pc.jdoReplaceField(fmd.managedFieldNo);
0603:                    }
0604:
0605:                }
0606:                callJDOPostLoad();
0607:                dfgLoaded = true;
0608:            }
0609:
0610:            /**
0611:             * Return a state containing the current values of all fake fields. If
0612:             * the instance is hollow then null is returned.
0613:             */
0614:            private State getForReadState() {
0615:                if (state.isEmpty())
0616:                    return null;
0617:                if (forReadState == null)
0618:                    forReadState = classMetaData.createState();
0619:                if (forReadState.isEmpty())
0620:                    state.fillForRead(forReadState, getPm());
0621:                return forReadState;
0622:            }
0623:
0624:            public void deletePersistent() {
0625:                if (isDeleted())
0626:                    return;
0627:                if (isTransientManaged()) {
0628:                    throw BindingSupportImpl.getInstance().invalidOperation(
0629:                            "The deletion of a transient "
0630:                                    + "managed instance is not allowed.");
0631:                }
0632:
0633:                // do notification if required
0634:                VersantPersistenceManagerImp pm = getPm();
0635:                boolean wasDirty = isDirty();
0636:                if (!wasDirty && classMetaData.notifyDataStoreOnDirtyOrDelete
0637:                        && pm.isActiveDS()) {
0638:                    pm.getStorageManager().notifyDirty(oid);
0639:                }
0640:
0641:                pm.fireDelete(classMetaData, pc);
0642:
0643:                // invoke jdoPreDelete
0644:
0645:                if (instanceCallbacks != null) {
0646:                    instanceCallbacks.jdoPreDelete();
0647:                }
0648:                /*END_JVAVONLY*/
0649:
0650:                //the loaded fields is reset for a deleted instance to force it to try and reread their
0651:                //fields and so catch illegal read/write ops on the instance.
0652:                resetLoadedFields();
0653:                setLoadRequired();
0654:
0655:                rfgLoaded = false;
0656:                dfgLoaded = false;
0657:
0658:                clearMtMCollections();
0659:
0660:                // mark us as deleted
0661:                stateM |= MASK_DELETE_TX_DIRTY;
0662:                pm.addTxStateObject(this );
0663:
0664:                deleteDependents();
0665:
0666:                // Make sure the fake fields with LOIDs for secondary fields are
0667:                // sent to the server if using VDS and the instance was clean
0668:                // before delete and has secondary fields. The forRead state is
0669:                // included in the DeletePacket if the tx commits.
0670:                if (jmd.sendStateOnDelete && classMetaData.hasSecondaryFields
0671:                        && !wasDirty) {
0672:                    forReadState = getForReadState();
0673:                } else {
0674:                    forReadState = null;
0675:                }
0676:
0677:                origState.clear();
0678:                state.clear();
0679:                if (beforeState != null)
0680:                    beforeState.clear();
0681:
0682:                //replace the state with DELETED_STATE. This will ensure that user
0683:                //exception is thrown on field access.
0684:                state = DELETED_STATE;
0685:            }
0686:
0687:            /**
0688:             * This is invoked from deletePersistent to delete all the dependent
0689:             * references of this instance.
0690:             */
0691:            private void deleteDependents() {
0692:                // make sure that all dependent fields are in state if there are any
0693:                FetchGroup dep = classMetaData.depFetchGroup;
0694:                if (dep == null)
0695:                    return;
0696:                if (!oid.isNew() && !state.containsFetchGroup(dep)) {
0697:                    getPm().getState(oid,
0698:                            dep.sendFieldsOnFetch ? getForReadState() : null,
0699:                            dep.index, -1, -1, false);
0700:                }
0701:
0702:                // delete all objects referenced by dependent fields
0703:                for (; dep != null; dep = dep.super FetchGroup) {
0704:                    FetchGroupField[] fields = dep.fields;
0705:                    int len = fields.length;
0706:                    for (int j = 0; j < len; j++) {
0707:                        FetchGroupField field = fields[j];
0708:                        FieldMetaData fmd = field.fmd;
0709:                        switch (fmd.category) {
0710:                        case MDStatics.CATEGORY_ARRAY:
0711:                            followArray(fmd);
0712:                            break;
0713:                        case MDStatics.CATEGORY_COLLECTION:
0714:                            followCollection(fmd);
0715:                            break;
0716:                        case MDStatics.CATEGORY_MAP:
0717:                            followMap(fmd);
0718:                            break;
0719:                        case MDStatics.CATEGORY_POLYREF:
0720:                        case MDStatics.CATEGORY_REF:
0721:                            followRef(fmd);
0722:                            break;
0723:                        }
0724:                    }
0725:                }
0726:            }
0727:
0728:            public void collectReachable(String fetchGroup, Collection result) {
0729:                FetchGroup fg = classMetaData.getFetchGroup(fetchGroup);
0730:
0731:                if (fg == null)
0732:                    return;
0733:                boolean deep = fetchGroup.equals(FetchGroup.REF_NAME);
0734:                boolean depend = fetchGroup.equals(FetchGroup.DEP_NAME);
0735:                VersantPersistenceManagerImp _pm = getPm();
0736:
0737:                // make sure everything required has been fetched
0738:                if (!oid.isNew() && !state.containsFetchGroup(fg) && !deep) {
0739:                    // todo: for FetchGroup.REF_NAME, a NPE is thrown for 
0740:                    // collection fields, because FetchGroup.nextFetchGroup is null
0741:                    _pm.getState(oid, fg.sendFieldsOnFetch ? getForReadState()
0742:                            : null, fg.index, -1, -1, false);
0743:                }
0744:
0745:                // collect all referenced objects
0746:                for (; fg != null; fg = fg.super FetchGroup) {
0747:                    FetchGroupField[] fields = fg.fields;
0748:                    int len = fields.length;
0749:                    for (int i = 0; i < len; i++) {
0750:                        FetchGroupField fgField = fields[i];
0751:                        int fieldNo = fgField.fmd.stateFieldNo;
0752:                        int managedFieldNo = fgField.fmd.managedFieldNo;
0753:                        if (!deep && !oid.isNew())
0754:                            pc.jdoReplaceField(managedFieldNo);
0755:
0756:                        String nextFetchGroup = fgField.nextFetchGroup == null ? null
0757:                                : fgField.nextFetchGroup.name;
0758:                        String nextKeyFetchGroup = fgField.nextKeyFetchGroup == null ? null
0759:                                : fgField.nextKeyFetchGroup.name;
0760:                        if (deep) // nextFetchGroup is null
0761:                            nextFetchGroup = nextKeyFetchGroup = FetchGroup.REF_NAME;
0762:                        else if (depend) // nextFetchGroup is default
0763:                            nextFetchGroup = nextKeyFetchGroup = FetchGroup.DEP_NAME;
0764:                        switch (fgField.fmd.category) {
0765:                        case MDStatics.CATEGORY_ARRAY:
0766:                            if (deep && !oid.isNew())
0767:                                doRead(fields[i].fmd); // todo: remove
0768:                            Object[] arr = (Object[]) state.getObjectField(
0769:                                    fieldNo, pc, _pm, oid);
0770:                            if (arr == null)
0771:                                continue;
0772:                            for (int j = 0; j < arr.length; j++) {
0773:                                Object o = arr[j];
0774:                                if (o != null
0775:                                        && o instanceof  PersistenceCapable)
0776:                                    result
0777:                                            .add(new Object[] { o,
0778:                                                    nextFetchGroup });
0779:                            }
0780:                            break;
0781:                        case MDStatics.CATEGORY_COLLECTION:
0782:                            if (deep && !oid.isNew())
0783:                                doRead(fields[i].fmd); // todo: remove
0784:                            Collection c = (Collection) state.getObjectField(
0785:                                    fieldNo, pc, _pm, oid);
0786:                            if (c == null)
0787:                                continue;
0788:                            for (Iterator it = c.iterator(); it.hasNext();) {
0789:                                Object o = it.next();
0790:                                if (o != null
0791:                                        && o instanceof  PersistenceCapable)
0792:                                    result
0793:                                            .add(new Object[] { o,
0794:                                                    nextFetchGroup });
0795:                            }
0796:                            break;
0797:                        case MDStatics.CATEGORY_MAP:
0798:                            if (deep && !oid.isNew())
0799:                                doRead(fields[i].fmd); // todo:remove
0800:                            Map m = (Map) state.getObjectField(fieldNo, pc,
0801:                                    _pm, oid);
0802:                            if (m == null)
0803:                                continue;
0804:                            for (Iterator it = m.entrySet().iterator(); it
0805:                                    .hasNext();) {
0806:                                Map.Entry e = (Map.Entry) it.next();
0807:                                Object o = e.getKey();
0808:                                if (o != null
0809:                                        && o instanceof  PersistenceCapable) {
0810:                                    result.add(new Object[] { o,
0811:                                            nextKeyFetchGroup });
0812:                                }
0813:                                o = e.getValue();
0814:                                if (o != null
0815:                                        && o instanceof  PersistenceCapable) {
0816:                                    result
0817:                                            .add(new Object[] { o,
0818:                                                    nextFetchGroup });
0819:                                }
0820:                            }
0821:                            break;
0822:                        case MDStatics.CATEGORY_POLYREF:
0823:                        case MDStatics.CATEGORY_REF:
0824:                            if (deep && !oid.isNew())
0825:                                doRead(fields[i].fmd); // todo: remove
0826:                            Object o = state.getObjectField(fieldNo, pc, _pm,
0827:                                    oid);
0828:                            if (o != null && (o instanceof  PersistenceCapable))
0829:                                result.add(new Object[] { o, nextFetchGroup });
0830:                            break;
0831:                        }
0832:                    }
0833:                }
0834:            }
0835:
0836:            /**
0837:             * Clear any many-to-many managed collections. This makes sure we
0838:             * are removed from the other side of any of these before we are
0839:             * deleted.
0840:             */
0841:            private void clearMtMCollections() {
0842:                FetchGroup mm = classMetaData.managedManyToManyFetchGroup;
0843:                if (mm != null) {
0844:
0845:                    // make sure the collections have been fetched
0846:                    if (!oid.isNew() && !state.containsFetchGroup(mm)) {
0847:                        getPm()
0848:                                .getState(
0849:                                        oid,
0850:                                        mm.sendFieldsOnFetch ? getForReadState()
0851:                                                : null, mm.index, -1, -1, false);
0852:                    }
0853:
0854:                    // now clear all of them skipping non-collections (e.g. version)
0855:                    for (; mm != null; mm = mm.super FetchGroup) {
0856:                        FetchGroupField[] fields = mm.fields;
0857:                        int len = fields.length;
0858:                        for (int j = 0; j < len; j++) {
0859:                            FetchGroupField field = fields[j];
0860:                            FieldMetaData fmd = field.fmd;
0861:                            if (fmd.category == MDStatics.CATEGORY_COLLECTION) {
0862:                                Collection c = (Collection) state
0863:                                        .getObjectField(fmd.stateFieldNo, pc,
0864:                                                getPm(), oid);
0865:                                if (c != null)
0866:                                    c.clear();
0867:                            }
0868:                        }
0869:                    }
0870:                }
0871:            }
0872:
0873:            private void followRef(FieldMetaData fmd) {
0874:                Object o = state.getObjectField(fmd.stateFieldNo, pc, getPm(),
0875:                        oid);
0876:                if (o != null)
0877:                    deletePersistent(o);
0878:            }
0879:
0880:            private void followCollection(FieldMetaData fmd) {
0881:                Collection c = (Collection) state.getObjectField(
0882:                        fmd.stateFieldNo, pc, getPm(), oid);
0883:                if (c == null)
0884:                    return;
0885:                for (Iterator i = c.iterator(); i.hasNext();) {
0886:                    Object o = i.next();
0887:                    if (o != null)
0888:                        deletePersistent(o);
0889:                }
0890:            }
0891:
0892:            private void followArray(FieldMetaData fmd) {
0893:                Object[] arr = (Object[]) state.getObjectField(
0894:                        fmd.stateFieldNo, pc, getPm(), oid);
0895:                if (arr == null)
0896:                    return;
0897:                for (int i = 0; i < arr.length; i++) {
0898:                    Object o = arr[i];
0899:                    if (o != null)
0900:                        deletePersistent(o);
0901:                }
0902:            }
0903:
0904:            private void followMap(FieldMetaData fmd) {
0905:                Map m = (Map) state.getObjectField(fmd.stateFieldNo, pc,
0906:                        getPm(), oid);
0907:                if (m == null)
0908:                    return;
0909:                for (Iterator i = m.entrySet().iterator(); i.hasNext();) {
0910:                    Map.Entry e = (Map.Entry) i.next();
0911:                    if (fmd.dependentKeys)
0912:                        deletePersistent(e.getKey());
0913:                    if (fmd.dependentValues) {
0914:                        Object o = e.getValue();
0915:                        if (o != null)
0916:                            deletePersistent(o);
0917:                    }
0918:                }
0919:            }
0920:
0921:            /**
0922:             * This is used when following dependent fields on delete. It avoids
0923:             * all the repeat checks done by perMan.deletePersistent(o).
0924:             */
0925:            private void deletePersistent(Object o) {
0926:                getPm().getInternalSM((PersistenceCapable) o)
0927:                        .deletePersistent();
0928:            }
0929:
0930:            /**
0931:             * The instance is only cleared of object references and not the primitives.
0932:             * The loaded fields and the JDO_FLAGS is reset to force the pc to ask the sm for new values.
0933:             * <p/>
0934:             * For application identity the state will not transition to hollow as the pk
0935:             * fields must remain.
0936:             */
0937:            private final void changeToHollowState(boolean clearBeforeState) {
0938:                if (state == null)
0939:                    return;
0940:                if (isHollow())
0941:                    return;
0942:
0943:                if (instanceCallbacks != null) {
0944:                    instanceCallbacks.jdoPreClear();
0945:                }
0946:
0947:                stateM = STATE_HOLLOW;
0948:
0949:                state.unmanageSCOFields();
0950:                state.clear();
0951:                State tmpState = state;
0952:
0953:                state = INIT_STATE;
0954:                //ask pc to replace only the instances that hold refs to other pc instances
0955:                //this helps to gc instances quicker
0956:                pc.jdoReplaceFields(classMetaData.absPCTypeFields);
0957:                state = tmpState;
0958:
0959:                origState.clear();
0960:                if (clearBeforeState && beforeState != null) {
0961:                    beforeState.clear();
0962:                }
0963:
0964:                setLoadRequired();
0965:                resetLoadedFields();
0966:                rfgLoaded = false;
0967:                dfgLoaded = false;
0968:
0969:                if (classMetaData.identityType == MDStatics.IDENTITY_TYPE_APPLICATION) {
0970:                    replaceApplicationPKFields();
0971:                }
0972:
0973:                if (forReadState != null)
0974:                    forReadState.clearFilledFlags();
0975:
0976:                if (Debug.DEBUG) {
0977:                    if (!isHollow()
0978:                            && classMetaData.identityType != MDStatics.IDENTITY_TYPE_APPLICATION) {
0979:                        if (Debug.DEBUG) {
0980:                            Debug.OUT.println("isEmpty = " + state.isEmpty());
0981:                        }
0982:                        dump();
0983:                        throw BindingSupportImpl.getInstance().internal(
0984:                                "The instance is not hollow");
0985:                    }
0986:                }
0987:            }
0988:
0989:            /**
0990:             * The instance is not cleared of its values. The loaded fields and the JDO_FLAGS is
0991:             * reset to force the pc to ask the sm for new values.
0992:             */
0993:            public void changeToHollowState() {
0994:                changeToHollowState(false);
0995:            }
0996:
0997:            public void rollback() {
0998:                if (isTx()) {
0999:                    rollbackImp();
1000:                } else if (readInTx) {
1001:                    changeToHollowState(true);
1002:                }
1003:                clearTxFlags();
1004:            }
1005:
1006:            public void commit(VersantPersistenceManagerImp pm) {
1007:                if (isTx()) {
1008:                    commitImp(pm);
1009:                } else if (readInTx) {
1010:                    changeToHollowState(true);
1011:                    readInTx = false;
1012:                }
1013:                clearTxFlags();
1014:            }
1015:
1016:            public final void resetLoadedFields() {
1017:                final boolean[] lfs = loadedFields;
1018:                for (int i = lfs.length - 1; i >= 0; i--) {
1019:                    lfs[i] = false;
1020:                }
1021:            }
1022:
1023:            private void setAllFieldsToLoaded() {
1024:                final boolean[] lfs = loadedFields;
1025:                for (int i = lfs.length - 1; i >= 0; i--) {
1026:                    lfs[i] = true;
1027:                }
1028:            }
1029:
1030:            private final void changeToTransient(int event) {
1031:                stateM = STATE_TRANSIENT;
1032:                if (event == EVENT_ROLLBACK) {
1033:                    if (getPm().isRestoreValues() && beforeState != null) {
1034:                        state.updateFrom(beforeState);
1035:                    }
1036:                    pc.jdoReplaceFields(classMetaData.allManagedFieldNosArray);
1037:                } else if (event == EVENT_COMMIT) {
1038:                    State tmpState = state;
1039:                    state = INIT_STATE;
1040:                    pc.jdoReplaceFields(classMetaData.allManagedFieldNosArray);
1041:                    state = tmpState;
1042:                }
1043:                unManage();
1044:            }
1045:
1046:            /**
1047:             * Must ensure that all resources is clean up.
1048:             */
1049:            private final void unManage() {
1050:                jdoManagedCache.remove(this );
1051:                setSMToNull();
1052:                state.unmanageSCOFields();
1053:                pc = null;
1054:                oid = null;
1055:                state = null;
1056:                beforeState = null;
1057:                origState = null;
1058:                toStoreState = null;
1059:            }
1060:
1061:            private final void setSMToNull() {
1062:                /**
1063:                 * change state to transient so that call back to replacingStateManager will return null.
1064:                 * and remove it from the txObjects list.
1065:                 */
1066:                stateM = STATE_TRANSIENT;
1067:                pc.jdoReplaceStateManager(null);
1068:            }
1069:
1070:            /**
1071:             * Check if the instance is in a managed transient state.
1072:             */
1073:            public boolean isTransientManaged() {
1074:                return (((stateM ^ STATE_T_CLEAN) == 0) || ((stateM ^ STATE_T_DIRTY) == 0));
1075:            }
1076:
1077:            public boolean isPersistentNew() {
1078:                return ((stateM ^ STATE_P_NEW) == 0);
1079:            }
1080:
1081:            public void loadFetchGroup(String name) {
1082:                if (oid.isNew()) {
1083:                    return;
1084:                }
1085:                FetchGroup fg = classMetaData.getFetchGroup(name);
1086:                if (fg == null) {
1087:                    throw BindingSupportImpl.getInstance().invalidOperation(
1088:                            "fetch group '" + name + "' is not defined");
1089:                }
1090:                if (!state.containsFetchGroup(fg)) {
1091:                    getPm().getState(this .oid,
1092:                            fg.sendFieldsOnFetch ? getForReadState() : null,
1093:                            fg.index, -1, -1, false);
1094:                }
1095:            }
1096:
1097:            /**
1098:             * This is here to do any preparation work before the field can be read.
1099:             * It will check if the fetchGroup for the field is filled in on the state. If not
1100:             * then the required values must be fetched from the server.
1101:             * <p/>
1102:             * Any state changes must also be done.
1103:             * <p/>
1104:             * The returned container reference must be kept until all the required
1105:             * State instances in the local cache have been referenced or they might
1106:             * be GCed. This is important for collections of PC and other fields that
1107:             * involve fetching State instances and loading them into the local cache.
1108:             * They are only hard referenced when the SCO instance has been created.
1109:             */
1110:            private StatesReturned doRead(FieldMetaData fmd) {
1111:                if (Debug.DEBUG) {
1112:                    if (isTransientManaged()) {
1113:                        throw BindingSupportImpl.getInstance().internal(
1114:                                "A transactional instance must not call this");
1115:                    }
1116:                }
1117:                addToProcessList();
1118:
1119:                VersantPersistenceManagerImp rpm = getPm();
1120:                rpm.checkNonTxRead();
1121:                if (fmd.isEmbeddedRef()) {
1122:                    return null;
1123:                }
1124:
1125:                StatesReturned container = null;
1126:                if (!state.containsField(fmd.stateFieldNo)) {
1127:                    if (Debug.DEBUG) {
1128:                        if (oid.isNew()) {
1129:                            throw BindingSupportImpl.getInstance().internal(
1130:                                    "A new OID is not supposed to reach here");
1131:                        }
1132:                        Debug.OUT
1133:                                .println("\n\n>>>>>>>>>>>The field not contained: field = "
1134:                                        + fmd.managedFieldNo
1135:                                        + " fieldName = "
1136:                                        + fmd.name
1137:                                        + " for "
1138:                                        + classMetaData.qname);
1139:                    }
1140:
1141:                    FetchGroup fg = fmd.fetchGroup;
1142:                    container = rpm.getState(this .oid,
1143:                            fg.sendFieldsOnFetch ? getForReadState() : null,
1144:                            fg.index, fmd.managedFieldNo, -1, false);
1145:                    if (Debug.DEBUG) {
1146:                        if (!state.containsFetchGroup(fmd.fetchGroup)) {
1147:                            System.out.println("bad state:\n" + state);
1148:                            throw BindingSupportImpl.getInstance().internal(
1149:                                    "State does not contain the requested fg");
1150:                        }
1151:                    }
1152:                }
1153:
1154:                if (!fmd.embeddedFakeField) {
1155:                    if (fmd.isJDODefaultFetchGroup()) {
1156:                        //replace non loaded dfg fields
1157:                        if (state.containFields(classMetaData.dfgStateFieldNos)) {
1158:                            loadDFGIntoPC(rpm);
1159:                        }
1160:                    } else {
1161:                        pc.jdoReplaceField(fmd.managedFieldNo);
1162:                        setLoaded(fmd);
1163:                        updated(rpm, true);
1164:                    }
1165:                }
1166:
1167:                if (!oid.isNew()) {
1168:                    if (!(doChangeChecking || rfgLoaded)) {
1169:                        loadRequiredFetchGroup();
1170:                    }
1171:                }
1172:
1173:                return container;
1174:            }
1175:
1176:            /**
1177:             * Loads the required fg into the state if not already done.
1178:             */
1179:            private void loadRequiredFetchGroup() {
1180:                if (rfgLoaded)
1181:                    return;
1182:                final FetchGroup reqFetchGroup = classMetaData.reqFetchGroup;
1183:                if (reqFetchGroup != null
1184:                        && !state.containsFetchGroup(reqFetchGroup)) {
1185:                    getPm().getState(this .oid, null, reqFetchGroup.index, -1,
1186:                            -1, false);
1187:                }
1188:                rfgLoaded = true;
1189:            }
1190:
1191:            /**
1192:             * This gets called from the enhanced pc instances. This is only for
1193:             * Application identity key fields. It gives us a chance to
1194:             * fill the field with a valid keygened value.
1195:             */
1196:            public void fillNewAppPKField(int fieldNo) {
1197:                if (oid.isNew()) {
1198:                    NewObjectOID newObjectOID = (NewObjectOID) oid;
1199:                    if (newObjectOID.realOID == null) {
1200:                        if (classMetaData.postInsertKeyGenerator) {
1201:                            getPm().flushRetainState();
1202:                        } else {
1203:                            newObjectOID.realOID = getPm().getStorageManager()
1204:                                    .createOID(classMetaData);
1205:                            newObjectOID.realOID.getClassMetaData();
1206:                            state.copyFields(newObjectOID.realOID);
1207:                            pc.jdoReplaceFields(classMetaData.pkFieldNos);
1208:                        }
1209:                    }
1210:                }
1211:            }
1212:
1213:            private FieldMetaData getFMD(int fieldNo) {
1214:                return classMetaData.managedFields[fieldNo];
1215:            }
1216:
1217:            /**
1218:             * Get the FetchGroup to be loaded with a field.
1219:             */
1220:            private FetchGroup getFetchGroup(int absField) {
1221:                return classMetaData.stateFields[classMetaData.absToRel[absField]].fetchGroup;
1222:            }
1223:
1224:            /**
1225:             * This is here to do any prep. work for a write operation. It must ensure that if a field
1226:             * is written to but is not currently loaded and it is using changed checking that it is first loaded
1227:             * from the server.
1228:             */
1229:            private final void doWrite(FieldMetaData fmd, boolean mustLoad) {
1230:                VersantPersistenceManagerImp pm = this .pm.getRealPM();
1231:                //if this is a transactional field and we should not need to go to the db
1232:                if (fmd.category == MDStatics.CATEGORY_TRANSACTIONAL) {
1233:                    if (pm.isActive())
1234:                        makeInternalDirty();
1235:                    return;
1236:                }
1237:                pm.checkNonTxWrite();
1238:
1239:                if (classMetaData.identityType == MDStatics.IDENTITY_TYPE_APPLICATION
1240:                        && fmd.primaryKey) {
1241:                    throw BindingSupportImpl.getInstance().unsupported(
1242:                            "Change of identity is not suppoted");
1243:                }
1244:
1245:                // if we need to notify the server before we go dirty for the first
1246:                // time do so now
1247:                if (classMetaData.notifyDataStoreOnDirtyOrDelete && !isDirty()
1248:                        && pm.isActiveDS()) {
1249:                    pm.getStorageManager().notifyDirty(oid);
1250:                }
1251:
1252:                // Check for a write operation that will result in a change from p-non-tx to p-dirty.
1253:                // If so then a snapshot of the current state must be taken and the state reloaded from
1254:                // the store.
1255:                // The current state must only be preserved if restoreValues is set to true.
1256:                // If retainValues is set to false then the instance will always be hollow after a commit
1257:                // or a rollback and therefore it overrides restoreValues.
1258:                if (isPNonTx() && pm.isActive()) {
1259:                    if (beforeState != null) {
1260:                        beforeState.clear();
1261:                        if (pm.isRestoreValues())
1262:                            beforeState.updateFrom(state);
1263:                    }
1264:                    // If is is an dataStore tx then the state must be cleared and reloaded from the
1265:                    // store. This is done to ensure that the state is in sync with the
1266:                    // dataStore.
1267:                    if (!pm.isOptimistic())
1268:                        changeToHollowState(false);
1269:                }
1270:
1271:                // Make sure that the state contains required fields before doing the
1272:                // write. For JDBC this will ensure that the optimisic locking field
1273:                // (if any) is loaded. For VDS this will load all fields.
1274:                if (!oid.isNew()) {
1275:                    if (mustLoad && !state.containsField(fmd.stateFieldNo)) {
1276:                        FetchGroup fg = fmd.fetchGroup;
1277:                        getPm()
1278:                                .getState(
1279:                                        this .oid,
1280:                                        fg.sendFieldsOnFetch ? getForReadState()
1281:                                                : null, fg.index,
1282:                                        fmd.managedFieldNo, -1, false);
1283:                    } else if (!(doChangeChecking || rfgLoaded)) {
1284:                        loadRequiredFetchGroup();
1285:                    } else if (doChangeChecking
1286:                            && !state.containsField(fmd.stateFieldNo)) {
1287:                        FetchGroup fg = fmd.fetchGroup;
1288:                        getPm()
1289:                                .getState(
1290:                                        this .oid,
1291:                                        fg.sendFieldsOnFetch ? getForReadState()
1292:                                                : null, fg.index,
1293:                                        fmd.managedFieldNo, -1, false);
1294:                    }
1295:                }
1296:
1297:                if (getPm().isActive()) {
1298:                    if (!isTx())
1299:                        updateDfgFieldMediation();
1300:                    stateM |= MASK_TX;
1301:                    stateM |= MASK_DIRTY;
1302:                    getPm().addTxStateObject(this );
1303:                    addToProcessList();
1304:                }
1305:                loadedFields[fmd.stateFieldNo] = false;
1306:            }
1307:
1308:            private void makeInternalDirty() {
1309:                stateM |= MASK_TX;
1310:                stateM |= MASK_DIRTY;
1311:                getPm().addTxStateObject(this );
1312:                addToProcessList();
1313:            }
1314:
1315:            /**
1316:             * This will be called when ever the state has been updated as result of a
1317:             * query/navigation that brought extra info back for this state.
1318:             * This method will ensure that the proper state changes takes place.
1319:             */
1320:            final void updated(VersantPersistenceManagerImp rpm,
1321:                    boolean addToProccessList) {
1322:                if (rpm.isActive()) {
1323:                    if (rpm.isOptimistic()) {
1324:                        /**
1325:                         * Must change to pers-non-tx
1326:                         * eg. This will change a hollow instance to p-non-tx
1327:                         */
1328:                        stateM |= MASK_PERSISTENT;
1329:                    } else {
1330:                        if (!isTx())
1331:                            updateDfgFieldMediation();
1332:                        stateM |= MASK_TX;
1333:                        stateM |= MASK_PERSISTENT;
1334:                        rpm.addTxStateObject(this );
1335:                    }
1336:
1337:                    if (addToProccessList) {
1338:                        addToProcessList(rpm);
1339:                    }
1340:                } else {
1341:                    stateM |= MASK_PERSISTENT;
1342:                }
1343:            }
1344:
1345:            /**
1346:             * This is a new State that was received from the server via indirect means.
1347:             * This state must be updated with the supplied state. Any state changes nec must
1348:             * also be done.
1349:             *
1350:             * @param suppliedState
1351:             */
1352:            public PCStateMan updateWith(State suppliedState,
1353:                    VersantPersistenceManagerImp pm, boolean overWrite) {
1354:                if (overWrite) {
1355:                    changeToHollowState();
1356:                }
1357:                updated(pm, true);
1358:                if (suppliedState != state) {
1359:                    state.updateNonFilled(suppliedState);
1360:                    if (doChangeChecking || origState.isEmpty()) {
1361:                        maintainOrigState(suppliedState, pm);
1362:                    }
1363:                }
1364:                return this ;
1365:            }
1366:
1367:            public boolean isTx() {
1368:                return ((stateM & MASK_TX) != 0);
1369:            }
1370:
1371:            public boolean readInTx(boolean strict) {
1372:                if (strict)
1373:                    return isTx();
1374:                return readInTx || isTx();
1375:            }
1376:
1377:            public boolean isDirty() {
1378:                return ((stateM & MASK_DIRTY) != 0);
1379:            }
1380:
1381:            private final boolean isNew() {
1382:                return ((stateM & MASK_NEW) != 0);
1383:            }
1384:
1385:            public boolean isHollow() {
1386:                return (state.isEmpty() && ((stateM ^ STATE_HOLLOW) == 0));
1387:            }
1388:
1389:            private boolean isDeleted() {
1390:                return (stateM & MASK_DELETE) != 0;
1391:            }
1392:
1393:            public boolean isPNonTx() {
1394:                return (((stateM ^ STATE_P_NON_TX) == 0) && !state.isEmpty());
1395:            }
1396:
1397:            public boolean isPClean() {
1398:                return (!state.isDirty() && ((stateM ^ STATE_P_CLEAN) == 0));
1399:            }
1400:
1401:            public boolean isPNew() {
1402:                return ((stateM ^ STATE_P_NEW) == 0);
1403:            }
1404:
1405:            public boolean isPNewDeleted() {
1406:                return ((stateM ^ STATE_P_NEW_DEL) == 0);
1407:            }
1408:
1409:            public boolean isPDeleted() {
1410:                return ((stateM ^ STATE_P_DEL) == 0);
1411:            }
1412:
1413:            public boolean isTClean() {
1414:                return ((stateM ^ STATE_T_CLEAN) == 0);
1415:            }
1416:
1417:            public boolean isTDirty() {
1418:                return ((stateM ^ STATE_T_DIRTY) == 0);
1419:            }
1420:
1421:            public boolean isPDirty() {
1422:                return (state.isDirty() && ((stateM ^ STATE_P_DIRTY) == 0));
1423:            }
1424:
1425:            /*
1426:            private String stateMtoString() {
1427:                switch (stateM) {
1428:                    case STATE_TRANSIENT:
1429:                        return "STATE_TRANSIENT";
1430:                    case STATE_T_CLEAN:
1431:                        return "STATE_T_CLEAN";
1432:                    case STATE_T_DIRTY:
1433:                        return "STATE_T_DIRTY";
1434:                    case STATE_HOLLOW:
1435:                        return "STATE_HOLLOW";
1436:                    case STATE_P_CLEAN:
1437:                        return "STATE_P_CLEAN";
1438:                    case STATE_P_DIRTY:
1439:                        return "STATE_P_DIRTY";
1440:                    case STATE_P_DEL:
1441:                        return "STATE_P_DEL";
1442:                    case STATE_P_NEW:
1443:                        return "STATE_P_NEW";
1444:                    case STATE_P_NEW_DEL:
1445:                        return "STATE_P_NEW_DEL";
1446:                }
1447:                return "UNKNOWN(" + stateM + ")";
1448:            }
1449:             */
1450:
1451:            private void rollbackImp() {
1452:                try {
1453:                    switch (stateM) {
1454:                    case STATE_TRANSIENT:
1455:                        break;
1456:                    case STATE_T_CLEAN:
1457:                        break;
1458:                    case STATE_T_DIRTY:
1459:                        if (beforeState != null) {
1460:                            State s = state;
1461:                            state = beforeState;
1462:                            beforeState = s;
1463:                            state.updateNonFilled(beforeState);
1464:                            beforeState.clear();
1465:                        }
1466:                        pc
1467:                                .jdoReplaceFields(classMetaData.allManagedFieldNosArray);
1468:                        if (forReadState != null)
1469:                            forReadState.clearFilledFlags();
1470:                        origState.clear();
1471:                        stateM = STATE_T_CLEAN;
1472:                        break;
1473:                    case STATE_HOLLOW:
1474:                        break;
1475:                    case STATE_P_CLEAN:
1476:                        if (getPm().isRestoreValues()) {
1477:                            stateM = STATE_P_NON_TX;
1478:                        } else {
1479:                            changeToHollowState(true);
1480:                        }
1481:                        break;
1482:                    case STATE_P_DEL:
1483:                        //the state was replaced with DELETED_STATE so create a new one
1484:                        state = createStateImp();
1485:                        changeToHollowState(true);
1486:                        break;
1487:                    case STATE_P_DIRTY:
1488:                        if (getPm().isRestoreValues()) {
1489:                            stateM = STATE_P_NON_TX;
1490:                            state.clearDirtyFields();
1491:                            if (beforeState != null) {
1492:                                beforeState.clearSCOFields();
1493:                                state.updateFrom(beforeState);
1494:                                beforeState.clear();
1495:                            }
1496:                            state.clearSCOFields();
1497:                            if (forReadState != null)
1498:                                forReadState.clearFilledFlags();
1499:                            setLoadRequired();
1500:                            resetLoadedFields();
1501:
1502:                            //there is no read interrogation for tx transient fields and therefore
1503:                            //they must be replaced now.
1504:                            pc
1505:                                    .jdoReplaceFields(classMetaData.txfieldManagedFieldNos);
1506:
1507:                            rfgLoaded = false;
1508:                            dfgLoaded = false;
1509:                        } else {
1510:                            if (beforeState != null) {
1511:                                State tmpState = state;
1512:                                state = beforeState;
1513:                                pc
1514:                                        .jdoReplaceFields(classMetaData.txfieldManagedFieldNos);
1515:                                state = tmpState;
1516:                            }
1517:                            changeToHollowState(true);
1518:                        }
1519:                        break;
1520:                    case STATE_P_NEW:
1521:                        changeToTransient(EVENT_ROLLBACK);
1522:                        break;
1523:                    case STATE_P_NEW_DEL:
1524:                        state = createStateImp();
1525:                        changeToTransient(EVENT_ROLLBACK);
1526:                        break;
1527:                    default:
1528:                        throw BindingSupportImpl.getInstance().internal(
1529:                                "The state is unreachable");
1530:                    }
1531:                } finally {
1532:                    if (toStoreState != null)
1533:                        toStoreState.clear();
1534:                    clearTxFlags();
1535:                }
1536:            }
1537:
1538:            /**
1539:             * This will load the defaulFetchGroup fields into the state and in
1540:             * the mananged instance. This is only called to change from hollow.
1541:             */
1542:            public void loadDfgFromHollow() {
1543:                if (Debug.DEBUG) {
1544:                    if (!isHollow()) {
1545:                        throw BindingSupportImpl
1546:                                .getInstance()
1547:                                .internal(
1548:                                        "This is only allowed to be called on hollow instances");
1549:                    }
1550:                }
1551:                getPm().getState(this .oid, null, 0, -1, -1, false);
1552:                loadDFGIntoPC(getPm());
1553:            }
1554:
1555:            /**
1556:             * This will load all the dfg fields into the PC instance.
1557:             */
1558:            public void loadDFGIntoPC(VersantPersistenceManagerImp rpm) {
1559:                if (dfgLoaded) {
1560:                    if (Debug.DEBUG)
1561:                        checkDfgLoaded();
1562:                    return;
1563:                }
1564:                pc.jdoReplaceFields(classMetaData.dfgAbsFieldNos);
1565:                updated(rpm, true);
1566:                callJDOPostLoad();
1567:
1568:                /**
1569:                 * Why only if it is transactional ??
1570:                 *
1571:                 * This is not set because in the case of a datastore tx with non-tx
1572:                 * read's allowed, and then setting the read ok flag will cause it not
1573:                 * to ask the sm for the next field access. This means if a ds tx starts
1574:                 * and the fields is accessed again that the sm will not reload the fields
1575:                 * from the db.
1576:                 */
1577:
1578:                //todo must also check if this is a subclass of a horizontal class
1579:                // where dfg fields have been changed
1580:                if (classMetaData.horizontalCMD == null
1581:                        && (isTx() || !rpm.isInterceptDfgFieldAccess())) {
1582:                    jdoFlags = PersistenceCapable.READ_OK;
1583:                    pc.jdoReplaceFlags();
1584:                }
1585:                dfgLoaded = true;
1586:                if (Debug.DEBUG)
1587:                    checkDfgLoaded();
1588:            }
1589:
1590:            private void callJDOPostLoad() {
1591:
1592:                if (instanceCallbacks != null && !dfgLoaded) {
1593:
1594:                    instanceCallbacks.jdoPostLoad();
1595:
1596:                }
1597:            }
1598:
1599:            /**
1600:             * Utils method to reset the flag of the pc instance to indicate that fields
1601:             * must be reloaded.
1602:             */
1603:            void setLoadRequired() {
1604:                jdoFlags = PersistenceCapable.LOAD_REQUIRED;
1605:                pc.jdoReplaceFlags();
1606:            }
1607:
1608:            public void setInterceptDfgFieldAccess(boolean on) {
1609:                if (isPNonTx()) {
1610:                    if (on) {
1611:                        setLoadRequired();
1612:                    } else {
1613:                        updateDfgFieldMediation();
1614:                    }
1615:                }
1616:            }
1617:
1618:            public void makeTransient() {
1619:                if (isDirty(null)) {
1620:                    throw BindingSupportImpl.getInstance().invalidOperation(
1621:                            "The instance is dirty.");
1622:                }
1623:                if (isTransientManaged())
1624:                    return;
1625:                //fill the pc instance with data in state.
1626:                final int[] stateFieldNos = new int[classMetaData.stateFieldNos.length];
1627:                for (int i = 0; i < state.getFieldNos(stateFieldNos); i++) {
1628:                    final FieldMetaData fmd = classMetaData.stateFields[stateFieldNos[i]];
1629:                    int cat = fmd.category;
1630:                    if (cat == MDStatics.CATEGORY_REF
1631:                            || cat == MDStatics.CATEGORY_POLYREF)
1632:                        continue;
1633:                    if (fmd.managedFieldNo < 0)
1634:                        continue;
1635:                    if (!loadedFields[fmd.managedFieldNo]) {
1636:                        pc.jdoReplaceField(fmd.managedFieldNo);
1637:                    }
1638:                }
1639:                unManage();
1640:                getPm().removeTxStateObject(this );
1641:            }
1642:
1643:            public void makeTransientRecursive() {
1644:                if (isDirty(null)) {
1645:                    throw BindingSupportImpl.getInstance().invalidOperation(
1646:                            "The instance is dirty.");
1647:                }
1648:                if (isTransientManaged())
1649:                    return;
1650:
1651:                final int[] stateFieldNos = new int[classMetaData.stateFieldNos.length];
1652:                for (int i = 0; i < state.getFieldNos(stateFieldNos); i++) {
1653:                    final FieldMetaData fmd = classMetaData.stateFields[stateFieldNos[i]];
1654:                    if (fmd.managedFieldNo < 0)
1655:                        continue;
1656:                    int cat = fmd.category;
1657:                    if (!loadedFields[fmd.managedFieldNo]) {
1658:                        if (cat == MDStatics.CATEGORY_REF
1659:                                || cat == MDStatics.CATEGORY_POLYREF)
1660:                            continue;
1661:                        pc.jdoReplaceField(fmd.managedFieldNo);
1662:                    } else {
1663:                        if (cat == MDStatics.CATEGORY_REF
1664:                                || cat == MDStatics.CATEGORY_POLYREF) {
1665:                            getPm().makeTransientRecursive(
1666:                                    state.getObjectField(fmd.stateFieldNo, pc,
1667:                                            getPm(), oid));
1668:                        }
1669:                    }
1670:                }
1671:
1672:                unManage();
1673:                getPm().removeTxStateObject(this );
1674:            }
1675:
1676:            public void makeTransactional() {
1677:                /**
1678:                 * This first case cover both ds and optimistic tx.
1679:                 * For ds the state is cleaned and for optimistic tx
1680:                 * the refresh depends on the user.
1681:                 */
1682:                if (((stateM ^ STATE_P_NON_TX) == 0)) {
1683:                    if (!getPm().isOptimistic()) {
1684:                        changeToHollowState(true);
1685:                    } else {
1686:                        updateDfgFieldMediation();
1687:                    }
1688:                    stateM = STATE_P_CLEAN;
1689:                    getPm().addTxStateObject(this );
1690:                    return;
1691:                } else if (((stateM ^ STATE_TRANSIENT) == 0)) {
1692:                    stateM = STATE_T_CLEAN;
1693:                }
1694:            }
1695:
1696:            /**
1697:             * Update the mediation of dfg fields. This method should be called when
1698:             * transitioning from p-non-tx to a tx state.
1699:             */
1700:            private void updateDfgFieldMediation() {
1701:                if (dfgLoaded) {
1702:                    //must reset the dfg field mediation.
1703:                    jdoFlags = PersistenceCapable.READ_OK;
1704:                    pc.jdoReplaceFlags();
1705:                }
1706:            }
1707:
1708:            public void makeNonTransactional() {
1709:                if (isDirty()) {
1710:                    throw BindingSupportImpl
1711:                            .getInstance()
1712:                            .invalidOperation(
1713:                                    "A Dirty instance may not be made NonTransactional");
1714:                }
1715:                if (isTClean()) {
1716:                    changeToTransient(EVENT_COMMIT);
1717:                } else if (isPClean()) {
1718:                    stateM = STATE_P_NON_TX;
1719:                }
1720:            }
1721:
1722:            /**
1723:             * The idea behind refresh is to reload the already loaded data from the server.
1724:             * This is mostly needed for optismistic transactions to minimize the concurrent
1725:             * updates.
1726:             * <p/>
1727:             * The only state change that occurs is for P-Dirty instances that change to
1728:             * P-Clean.
1729:             * <p/>
1730:             * This call is a no-op for all new instances, because there is nothing to
1731:             * relaod from the server.
1732:             * Hollow instances are also an no-op because nothing has been fetched.
1733:             * <p/>
1734:             * For all the rest this is a relead of the currently loaded fields.
1735:             */
1736:            public void refresh() {
1737:                /**
1738:                 * All new instances are no-ops because there is nothing in the store
1739:                 * to refresh from.
1740:                 */
1741:                if (isNew()) {
1742:                    return;
1743:                } else {
1744:                    if (getPm().isActive()) {
1745:                        if (((stateM ^ STATE_P_DIRTY) == 0)) {
1746:                            if (getPm().isOptimistic()) {
1747:                                stateM = STATE_P_NON_TX;
1748:                            } else {
1749:                                stateM = STATE_P_CLEAN;
1750:                            }
1751:                            getPm().addTxStateObject(this );
1752:                        }
1753:                    }
1754:                    changeToHollowState(true);
1755:                    getPm()
1756:                            .getStateForRefresh(
1757:                                    this .oid,
1758:                                    classMetaData.fetchGroups[0].sendFieldsOnFetch ? getForReadState()
1759:                                            : null, 0);
1760:                }
1761:            }
1762:
1763:            /**
1764:             * Check the model consistency of all of the fields in our State.
1765:             * This currently only makes sure that bidirectional relationships have
1766:             * been properly completed but other checks may be added in future.
1767:             */
1768:            public void checkModelConsistency() {
1769:                if (isDeleted())
1770:                    return;
1771:                FieldMetaData[] fields = classMetaData.fields;
1772:                for (int fieldNo = 0; fieldNo < fields.length; fieldNo++) {
1773:                    FieldMetaData fmd = fields[fieldNo];
1774:                    if (fmd.isMaster) { // one side of one-to-many
1775:                        checkOneToManyMaster(fieldNo);
1776:                    } else if (fmd.isDetail) { // many side of one-to-many
1777:                        checkOneToManyDetail(fieldNo);
1778:                    } else if (fmd.isManyToMany) {
1779:                        checkManyToMany(fieldNo);
1780:                    }
1781:                }
1782:            }
1783:
1784:            /**
1785:             * Check the one side of a one-to-many. Make sure that all of the details
1786:             * added to the collection have the correct master set.
1787:             */
1788:            private void checkOneToManyMaster(int fieldNo) {
1789:                FieldMetaData fmd = classMetaData.fields[fieldNo];
1790:                VersantPersistenceManagerImp realPM = getPm();
1791:                Collection col = (Collection) state.getObjectField(
1792:                        fmd.stateFieldNo, pc, getPm(), oid);
1793:                if (col == null)
1794:                    return;
1795:                // check that all of the objects in col have us as the master
1796:                int index = 0;
1797:                for (Iterator i = col.iterator(); i.hasNext(); index++) {
1798:                    Object detail = i.next();
1799:                    if (detail == null) {
1800:                        throw BindingSupportImpl.getInstance().runtime(
1801:                                "Inconsistent one-to-many: "
1802:                                        + "null object at index " + index
1803:                                        + " in collection " + fmd.getQName()
1804:                                        + " on " + toErrString(oid, pc));
1805:                    }
1806:                    PCStateMan detailSM = realPM
1807:                            .getInternalSM((PersistenceCapable) detail);
1808:                    if (detailSM.isDeleted()) {
1809:                        throw BindingSupportImpl.getInstance().runtime(
1810:                                "Inconsistent one-to-many: "
1811:                                        + "deleted object "
1812:                                        + toErrString(detailSM.oid, null)
1813:                                        + " at index " + index
1814:                                        + " in collection " + fmd.getQName()
1815:                                        + " on " + toErrString(oid, pc));
1816:                    }
1817:                    if (fmd.inverseFieldMetaData.fake)
1818:                        return;
1819:                    Object master = detailSM.getObjectField(null,
1820:                            fmd.inverseFieldNo, null);
1821:                    if (master != pc) {
1822:                        StringBuffer s = new StringBuffer();
1823:                        s.append("Inconsistent one-to-many: object ");
1824:                        s.append(toErrString(detailSM.oid, detailSM.pc));
1825:                        s.append(" at index ");
1826:                        s.append(index);
1827:                        s.append(" in collection ");
1828:                        s.append(fmd.getQName());
1829:                        s.append(" on ");
1830:                        s.append(toErrString(oid, pc));
1831:                        if (master == null) {
1832:                            s.append(" has null ");
1833:                        } else {
1834:                            s.append(" has wrong ");
1835:                        }
1836:                        s.append(fmd.inverseFieldMetaData.getQName());
1837:                        if (master != null) {
1838:                            s.append(' ');
1839:                            PCStateMan masterSM = realPM
1840:                                    .getInternalSM((PersistenceCapable) master);
1841:                            s.append(toErrString(masterSM.oid, master));
1842:                        }
1843:                        throw BindingSupportImpl.getInstance().runtime(
1844:                                s.toString());
1845:                    }
1846:                }
1847:            }
1848:
1849:            /**
1850:             * Check the many side of a one-to-many. Make sure that the master has
1851:             * been set correctly and that the master has us in its list of details.
1852:             */
1853:            private void checkOneToManyDetail(int fieldNo) {
1854:                FieldMetaData fmd = classMetaData.fields[fieldNo];
1855:                VersantPersistenceManagerImp realPM = getPm();
1856:                Object master = state.getObjectField(fmd.stateFieldNo, pc,
1857:                        getPm(), oid);
1858:                if (master == null) {
1859:                    if (fmd.nullValue == MDStatics.NULL_VALUE_EXCEPTION) {
1860:                        throw BindingSupportImpl.getInstance().runtime(
1861:                                "Inconsistent one-to-many: " + "'many' object "
1862:                                        + toErrString(oid, pc) + " field "
1863:                                        + fmd.getQName() + " is null");
1864:                    }
1865:                    // the master not set case is caught in checkOneToManyMaster
1866:                    // as it is ok to have a null master if the detail
1867:                    // is not part of any master's collection
1868:                    return;
1869:                }
1870:                if (master instanceof  OID) {
1871:                    try {
1872:                        master = realPM.getObjectById(master, true);
1873:                    } catch (RuntimeException e) {
1874:                        if (BindingSupportImpl.getInstance().isOwnException(e)) {
1875:                            throw BindingSupportImpl
1876:                                    .getInstance()
1877:                                    .runtime(
1878:                                            "Inconsistent one-to-many: "
1879:                                                    + "'many' object "
1880:                                                    + toErrString(oid, pc)
1881:                                                    + " field "
1882:                                                    + fmd.getQName()
1883:                                                    + " references invalid 'one' object: "
1884:                                                    + e.getMessage(), e);
1885:                        } else {
1886:                            throw e;
1887:                        }
1888:                    }
1889:                }
1890:                PCStateMan masterSM = realPM
1891:                        .getInternalSM((PersistenceCapable) master);
1892:                //        if(fmd.inverseFieldMetaData.fake)return;
1893:                Object o = masterSM.getObjectField(null, fmd.inverseFieldNo,
1894:                        null);
1895:                if (o instanceof  Collection) {
1896:                    if (!((Collection) o).contains(pc)) {
1897:                        throw BindingSupportImpl
1898:                                .getInstance()
1899:                                .runtime(
1900:                                        "Inconsistent one-to-many: "
1901:                                                + "'many' object "
1902:                                                + toErrString(oid, pc)
1903:                                                + " is not in collection on 'one' instance "
1904:                                                + toErrString(masterSM.oid,
1905:                                                        masterSM.pc)
1906:                                                + " "
1907:                                                + fmd.inverseFieldMetaData
1908:                                                        .getQName());
1909:                    }
1910:                } else {
1911:                    PersistenceCapable[] pcs = (PersistenceCapable[]) o;
1912:                    boolean contains = false;
1913:                    for (int i = 0; i < pcs.length; i++) {
1914:                        PersistenceCapable persistenceCapable = pcs[i];
1915:                        if (persistenceCapable == pc) {
1916:                            contains = true;
1917:                            break;
1918:                        }
1919:                    }
1920:                    if (!contains) {
1921:                        throw BindingSupportImpl
1922:                                .getInstance()
1923:                                .runtime(
1924:                                        "Inconsistent one-to-many: "
1925:                                                + "'many' object "
1926:                                                + toErrString(oid, pc)
1927:                                                + " is not in collection on 'one' instance "
1928:                                                + toErrString(masterSM.oid,
1929:                                                        masterSM.pc)
1930:                                                + " "
1931:                                                + fmd.inverseFieldMetaData
1932:                                                        .getQName());
1933:                    }
1934:                }
1935:            }
1936:
1937:            /**
1938:             * Check a many-to-many. Make sure that each collection is the inverse
1939:             * of the other.
1940:             */
1941:            private void checkManyToMany(int fieldNo) {
1942:                FieldMetaData fmd = classMetaData.fields[fieldNo];
1943:                VersantPersistenceManagerImp realPM = getPm();
1944:                Collection col = (Collection) state.getObjectField(
1945:                        fmd.stateFieldNo, pc, getPm(), oid);
1946:                if (col == null)
1947:                    return;
1948:                // check that all of the objects in col have us in their own col
1949:                int index = 0;
1950:                for (Iterator i = col.iterator(); i.hasNext(); index++) {
1951:                    Object other = i.next();
1952:                    if (other == null) {
1953:                        throw BindingSupportImpl.getInstance().runtime(
1954:                                "Inconsistent many-to-many: "
1955:                                        + "null object at index " + index
1956:                                        + " in collection " + fmd.getQName()
1957:                                        + " on " + toErrString(oid, pc));
1958:                    }
1959:                    PCStateMan otherSM = realPM
1960:                            .getInternalSM((PersistenceCapable) other);
1961:                    if (otherSM.isDeleted()) {
1962:                        throw BindingSupportImpl.getInstance().runtime(
1963:                                "Inconsistent many-to-many: "
1964:                                        + "deleted object "
1965:                                        + toErrString(otherSM.oid, null)
1966:                                        + " at index " + index
1967:                                        + " in collection " + fmd.getQName()
1968:                                        + " on " + toErrString(oid, pc));
1969:                    }
1970:                    Collection otherCol = (Collection) otherSM.getObjectField(
1971:                            null, fmd.inverseFieldNo, null);
1972:                    if (!otherCol.contains(pc)) {
1973:                        throw BindingSupportImpl.getInstance().runtime(
1974:                                "Inconsistent many-to-many: " + "object "
1975:                                        + toErrString(oid, pc) + " at index "
1976:                                        + index + "in collection "
1977:                                        + fmd.getQName() + " contains "
1978:                                        + toErrString(otherSM.oid, otherSM.pc)
1979:                                        + " but "
1980:                                        + fmd.inverseFieldMetaData.getQName()
1981:                                        + " does not contain it");
1982:                    }
1983:                }
1984:            }
1985:
1986:            /**
1987:             * Format an oid and its associated pc instance (can be null) into a nice
1988:             * String for error messages.
1989:             */
1990:            private static String toErrString(OID oid, Object pc) {
1991:                StringBuffer s = new StringBuffer();
1992:                s.append('[');
1993:                if (oid.isNew()) {
1994:                    s.append("new");
1995:                } else {
1996:                    s.append(oid.toStringImp());
1997:                }
1998:                if (pc != null) {
1999:                    s.append(' ');
2000:                    s.append(Utils.toString(pc));
2001:                }
2002:                s.append(']');
2003:                return s.toString();
2004:            }
2005:
2006:            /**
2007:             * If the PC instance implements InstanceCallbacks and has not been deleted
2008:             * then call its jdoPreStore method and also invoke the store lifecycle
2009:             * callback if listeners is not null. Returns true if jdoPreStore was
2010:             * called or there were store listeners.
2011:             */
2012:            public boolean doJDOPreStore(LifecycleListenerManager listeners) {
2013:                if ((stateM & MASK_DELETE) == 0) {
2014:                    boolean ans = listeners != null
2015:                            && listeners.firePreStore(pc);
2016:                    if (instanceCallbacks != null) {
2017:
2018:                        instanceCallbacks.jdoPreStore();
2019:
2020:                        return true;
2021:                    }
2022:                    return ans;
2023:                }
2024:                return false;
2025:            }
2026:
2027:            /**
2028:             * This is called on all transactional objects so that they can prepare for
2029:             * the commit or flush. If the state was deleted it will call add itself
2030:             * to the list of instances to be deleted etc.
2031:             */
2032:            public void prepareCommitOrFlush(boolean commit) {
2033:                addToProcessList();
2034:                /**
2035:                 * Add all the instance that must be deleted to the toBeDeleted collection.
2036:                 * If the oid is new then it must not be added because it is not in the db and therefore
2037:                 * not to be removed.
2038:                 */
2039:                if (isDeleted()) {
2040:                    addForDelete();
2041:                    //ignore
2042:                } else if (isDirty()) {
2043:
2044:                    // If delete-orphans is true and this class contains refs used to
2045:                    // complete collections mapped using a foreign key in the element
2046:                    // class and all of these references are null and we are doing
2047:                    // a commit then delete this instance.
2048:                    if (commit
2049:                            && classMetaData.deleteOrphans
2050:                            && classMetaData.fkCollectionRefStateFieldNos != null) {
2051:                        int[] a = classMetaData.fkCollectionRefStateFieldNos;
2052:                        int i;
2053:                        for (i = a.length - 1; i >= 0; i--) {
2054:                            int sno = a[i];
2055:                            if (!state.containsField(sno) || !state.isNull(sno))
2056:                                break;
2057:                        }
2058:                        if (i < 0) {
2059:                            deletePersistent();
2060:                            addForDelete();
2061:                            return;
2062:                        }
2063:                    }
2064:                    preparedStatus = 1;
2065:
2066:                    // clear transactional fields if this is a commit
2067:                    if (commit)
2068:                        state.clearTransactionNonPersistentFields();
2069:
2070:                    VersantPersistenceManagerImp realPM = getPm();
2071:                    State toStoreState = createToStoreState();
2072:                    boolean isNew = oid.isNew();
2073:
2074:                    if (!oid.isResolved())
2075:                        oid.resolve(state);
2076:                    origState.clearCollectionFields();
2077:
2078:                    // If nothing is copied to toStoreState then only transactional
2079:                    // fields were dirty. If this is a commit and the instance is new
2080:                    // then persist it anyway.
2081:                    if (!state.fillToStoreState(toStoreState, realPM, this )
2082:                            && (!commit || !isNew)) {
2083:                        return;
2084:                    }
2085:                    addToStoreOidContainer(toStoreState, realPM, isNew);
2086:                }
2087:            }
2088:
2089:            private void addToStoreOidContainer(State toStoreState,
2090:                    VersantPersistenceManagerImp realPM, boolean aNew) {
2091:                if (doChangeChecking) {
2092:                    if (origState != null)
2093:                        origState.clearNonFilled(toStoreState);
2094:                    realPM.storeOidStateContainer.add(oid, toStoreState,
2095:                            origState, aNew
2096:                                    && classMetaData.postInsertKeyGenerator);
2097:                } else {
2098:                    if (aNew) {
2099:                        realPM.storeOidStateContainer
2100:                                .add(oid, toStoreState, null, aNew
2101:                                        && classMetaData.postInsertKeyGenerator);
2102:                    } else {
2103:                        realPM.storeOidStateContainer
2104:                                .add(oid, toStoreState, origState, aNew
2105:                                        && classMetaData.postInsertKeyGenerator);
2106:                    }
2107:                }
2108:                preparedStatus = 2;
2109:            }
2110:
2111:            private void addForDelete() {
2112:                if (!oid.isNew() && !addedForDelete) {
2113:                    // The forReadState must have been previously filled with whatever
2114:                    // needs to be sent back to the server with the OID.
2115:                    if (oid.getAvailableClassMetaData() == null) {
2116:                        // create a typed OID as untyped OIDs cannot be deleted
2117:                        OID o = classMetaData.createOID(true);
2118:                        o.setLongPrimaryKey(oid.getLongPrimaryKey());
2119:                        getPm().addForDelete(o, forReadState);
2120:                    } else {
2121:                        getPm().addForDelete(oid, forReadState);
2122:                    }
2123:                    addedForDelete = true;
2124:                }
2125:            }
2126:
2127:            public String toString() {
2128:                return "SM@" + System.identityHashCode(this ) + " "
2129:                        + (oid == null ? "null" : oid.toStringImp())
2130:                        + " cacheKey: "
2131:                        + (cacheEntry == null ? "NULL" : cacheEntry.toString())
2132:                        + " inProcessList: "
2133:                        + pm.getRealPM().getCache().inProcessList(this );
2134:            }
2135:
2136:            /**
2137:             * This is called after the server side commit is done. This will ensure
2138:             * that the instance changes to the correct state.
2139:             */
2140:            private void commitImp(VersantPersistenceManagerImp rpm) {
2141:                try {
2142:                    switch (stateM) {
2143:                    case STATE_TRANSIENT:
2144:                        break;
2145:                    case STATE_T_CLEAN:
2146:                        break;
2147:                    case STATE_T_DIRTY:
2148:                        stateM = STATE_T_CLEAN;
2149:                        if (beforeState != null)
2150:                            beforeState.clear();
2151:                        if (toStoreState != null)
2152:                            toStoreState.clear();
2153:                        break;
2154:                    case STATE_HOLLOW:
2155:                        break;
2156:                    case STATE_P_NEW:
2157:                        changeTmpOIDToRealOID();
2158:                    case STATE_P_CLEAN:
2159:                    case STATE_P_DIRTY:
2160:                        if (rpm.isRetainValues()) {
2161:                            if (!toBeEvictedFlag) {
2162:                                changeToPNonTxForCommit(rpm);
2163:                            } else {
2164:                                changeToHollowState();
2165:                                cacheEntry
2166:                                        .changeToRefType(
2167:                                                jdoManagedCache.queue,
2168:                                                VersantPersistenceManager.PM_CACHE_REF_TYPE_WEAK);
2169:                            }
2170:                        } else {
2171:                            changeToHollowState();
2172:                            if (toBeEvictedFlag) {
2173:                                cacheEntry
2174:                                        .changeToRefType(
2175:                                                jdoManagedCache.queue,
2176:                                                VersantPersistenceManager.PM_CACHE_REF_TYPE_WEAK);
2177:                            }
2178:                        }
2179:                        if (beforeState != null)
2180:                            beforeState.clear();
2181:                        if (toStoreState != null)
2182:                            toStoreState.clear();
2183:                        break;
2184:                    case STATE_P_DEL:
2185:                    case STATE_P_NEW_DEL:
2186:                        state = createStateImp();
2187:                        deleteImpForCommit();
2188:                        break;
2189:                    default:
2190:                        throw BindingSupportImpl.getInstance().internal(
2191:                                "The state is unreachable");
2192:                    }
2193:                } finally {
2194:                    clearTxFlags();
2195:                }
2196:            }
2197:
2198:            private void clearTxFlags() {
2199:                addedForDelete = false;
2200:                readInTx = false;
2201:                toBeEvictedFlag = false;
2202:                preparedStatus = 0;
2203:            }
2204:
2205:            public void flushCommit() {
2206:                switch (stateM) {
2207:                case STATE_TRANSIENT:
2208:                    break;
2209:                case STATE_T_CLEAN:
2210:                    break;
2211:                case STATE_T_DIRTY:
2212:                    break;
2213:                case STATE_HOLLOW:
2214:                    break;
2215:                case STATE_P_NEW:
2216:                    changeTmpOIDToRealOID();
2217:                case STATE_P_CLEAN:
2218:                case STATE_P_DIRTY:
2219:                    this .state.makeClean();
2220:                    replaceSCOFields();
2221:                    break;
2222:                case STATE_P_DEL:
2223:                case STATE_P_NEW_DEL:
2224:                    break;
2225:                default:
2226:                    throw BindingSupportImpl.getInstance().internal(
2227:                            "The state is unreachable");
2228:                }
2229:            }
2230:
2231:            public void updateAutoFields(State autoS) {
2232:                if (classMetaData.hasAutoSetFields) {
2233:                    this .state.updateFrom(autoS);
2234:                    this .origState.updateFrom(autoS);
2235:                }
2236:            }
2237:
2238:            /**
2239:             * Helper method for commit to do work for deleting an instance. This must remove all
2240:             * resources held by this instance.
2241:             */
2242:            public void deleteImpForCommit() {
2243:                changeToTransient(EVENT_COMMIT);
2244:            }
2245:
2246:            /**
2247:             * This changes the current 'new' oid to an actual oid retrieved from the store. This is
2248:             * called as part of a commit from a PNew state.
2249:             */
2250:            private void changeTmpOIDToRealOID() {
2251:                if (!oid.isNew())
2252:                    return;
2253:                if (cacheEntry.mappedOID != oid.getRealOID()) {
2254:                    jdoManagedCache.addRealOID(this );
2255:                }
2256:                this .oid = this .oid.getRealOID();
2257:                replaceApplicationPKFields();
2258:            }
2259:
2260:            /**
2261:             * This is called from commit and retainValues is set.
2262:             * The state must be P-Non-Tx after this.
2263:             */
2264:            public void changeToPNonTxForCommit(VersantPersistenceManagerImp rpm) {
2265:                stateM = STATE_P_NON_TX;
2266:                dfgLoaded = false;
2267:                setLoadRequired();
2268:                resetLoadedFields();
2269:                this .state.makeClean();
2270:
2271:                replaceSCOFields();
2272:
2273:                if (doChangeChecking) {
2274:                    this .origState.clear();
2275:                    maintainOrigState(state, rpm);
2276:                } else {
2277:                    this .origState.clear();
2278:                }
2279:                toBeEvictedFlag = false;
2280:            }
2281:
2282:            /**
2283:             * Make all PC instances referenced by us persistent. This is called by
2284:             * the PM on makePersistent and commit as part of the reachability
2285:             * search.<p>
2286:             */
2287:            public void addRefs() {
2288:                state.addRefs(getPm(), this );
2289:            }
2290:
2291:            /**
2292:             * This is currently only called for an instance that transitioned from new to
2293:             * persistent but is a good method to call if a application pk has changed.
2294:             * <p/>
2295:             * This is called from the commit method after the new oid is received for
2296:             * the state.
2297:             */
2298:            private final void replaceApplicationPKFields() {
2299:                if (classMetaData.identityType != MDStatics.IDENTITY_TYPE_APPLICATION)
2300:                    return;
2301:                this .state.copyFields(oid);
2302:                pc.jdoReplaceFields(classMetaData.pkFieldNos);
2303:            }
2304:
2305:            public byte replacingFlags(PersistenceCapable pc) {
2306:                return jdoFlags;
2307:            }
2308:
2309:            public StateManager replacingStateManager(PersistenceCapable pc,
2310:                    StateManager sm) {
2311:                /**
2312:                 * The instance is transitioning to transient.
2313:                 */
2314:                if (stateM == STATE_TRANSIENT) {
2315:                    return null;
2316:                }
2317:                return sm;
2318:            }
2319:
2320:            //==============================state checks====================================
2321:
2322:            public boolean isDirty(PersistenceCapable pc) {
2323:                return ((stateM & MASK_DIRTY) != 0);
2324:            }
2325:
2326:            public boolean isTransactional(PersistenceCapable pc) {
2327:                return ((stateM & MASK_TX) != 0);
2328:            }
2329:
2330:            public boolean isPersistent(PersistenceCapable pc) {
2331:                return ((stateM & MASK_PERSISTENT) != 0);
2332:            }
2333:
2334:            public boolean isNew(PersistenceCapable pc) {
2335:                return ((stateM & MASK_NEW) != 0);
2336:            }
2337:
2338:            public boolean isDeleted(PersistenceCapable pc) {
2339:                return ((stateM & MASK_DELETE) != 0);
2340:            }
2341:
2342:            //==============================================================================
2343:
2344:            public PersistenceManager getPersistenceManager(
2345:                    PersistenceCapable pc) {
2346:                getPm().requestedPCState = this ;
2347:                return pm;
2348:            }
2349:
2350:            public void makeDirty(PersistenceCapable pc, String fieldName) {
2351:                try {
2352:                    final FieldMetaData fmd = oid.getClassMetaData()
2353:                            .getFieldMetaData(fieldName);
2354:                    doWrite(fmd, false);
2355:                    state.makeDirtyAbs(fmd.managedFieldNo);
2356:                } catch (Exception e) {
2357:                    handleException(e);
2358:                }
2359:            }
2360:
2361:            public void makeDirty(PersistenceCapable persistenceCapable,
2362:                    int fieldNo) {
2363:                try {
2364:                    doWrite(getFMD(fieldNo), false);
2365:                    state.makeDirtyAbs(fieldNo);
2366:                } catch (Exception e) {
2367:                    handleException(e);
2368:                }
2369:            }
2370:
2371:            /**
2372:             * Get the LOID of this instance. This should only be called for classes
2373:             * stored in VDS. This will assign it real LOID if it does not already
2374:             * have one.
2375:             */
2376:            public long getLOID() {
2377:                return getRealOID().getLongPrimaryKey();
2378:            }
2379:
2380:            public Object getObjectId(PersistenceCapable pcParam) {
2381:                try {
2382:                    if (classMetaData.identityType == MDStatics.IDENTITY_TYPE_DATASTORE) {
2383:                        return new VersantOid(this , jmd, oid.isResolved());
2384:                    } else if (classMetaData.identityType == MDStatics.IDENTITY_TYPE_APPLICATION) {
2385:                        if (oid.isNew() && classMetaData.postInsertKeyGenerator) {
2386:                            getPm().flushRetainState();
2387:                        }
2388:                        // If this is called directly after a commit with retain values to false
2389:                        // then the state does not contiain any field and hence
2390:                        if (oid.isNew()) {
2391:                            if (classMetaData.useKeyGen) {
2392:                                NewObjectOID newOID = (NewObjectOID) oid;
2393:                                if (newOID.realOID == null) {
2394:                                    newOID.realOID = getPm()
2395:                                            .getStorageManager().createOID(
2396:                                                    classMetaData);
2397:                                    newOID.realOID.getClassMetaData();
2398:                                    jdoManagedCache.addRealOID(this );
2399:                                    state.copyFields(newOID.realOID);
2400:                                    pc
2401:                                            .jdoReplaceFields(classMetaData.pkFieldNos);
2402:                                }
2403:                            } else {
2404:                                NewObjectOID newOID = (NewObjectOID) oid;
2405:                                if (newOID.realOID == null) {
2406:                                    newOID.realOID = classMetaData
2407:                                            .createOID(true);
2408:                                    newOID.realOID.getClassMetaData();
2409:                                    state.copyKeyFields(newOID.realOID);
2410:                                    jdoManagedCache.addRealOID(this );
2411:                                }
2412:                            }
2413:                        }
2414:                        Object pcID = pc.jdoNewObjectIdInstance();
2415:                        pc.jdoCopyKeyFieldsToObjectId(pcID);
2416:                        return pcID;
2417:                    } else {
2418:                        throw BindingSupportImpl.getInstance().internal(
2419:                                "Unknown identity type: '"
2420:                                        + classMetaData.identityType + "' for "
2421:                                        + classMetaData.qname);
2422:                    }
2423:                } catch (Exception e) {
2424:                    handleException(e);
2425:                    return null; // keep compiler happy
2426:                }
2427:            }
2428:
2429:            /**
2430:             * This is called from VersantOid if it need the
2431:             */
2432:            public OID getRealOID() {
2433:                try {
2434:                    if (classMetaData.identityType == MDStatics.IDENTITY_TYPE_DATASTORE) {
2435:                        if (oid.isNew()) {
2436:                            NewObjectOID newOID = (NewObjectOID) oid;
2437:                            OID realOid = newOID.realOID;
2438:                            if (realOid == null) {
2439:                                if (oid.isNew()
2440:                                        && classMetaData.postInsertKeyGenerator) {
2441:                                    getPm().flushRetainState();
2442:                                }
2443:                                newOID.realOID = realOid = getPm()
2444:                                        .getStorageManager().createOID(
2445:                                                classMetaData);
2446:                                realOid.resolve(state);
2447:                                realOid.getClassMetaData();
2448:                                jdoManagedCache.addRealOID(this );
2449:                            }
2450:                            return newOID.realOID;
2451:                        }
2452:                        return oid;
2453:                    } else {
2454:                        throw BindingSupportImpl.getInstance().internal(
2455:                                "This method should only be "
2456:                                        + "called for DataStore identity");
2457:                    }
2458:                } catch (Exception e) {
2459:                    handleException(e);
2460:                    return null;
2461:                }
2462:            }
2463:
2464:            public Object getTransactionalObjectId(PersistenceCapable pc) {
2465:                return getObjectId(pc);
2466:            }
2467:
2468:            /**
2469:             * This will only load the fields for the pc instance. It does not force aload and not any reachable pc instances.
2470:             *
2471:             * @param pc
2472:             */
2473:            public void preSerialize(PersistenceCapable pc) {
2474:                loadAllPersistentFieldsToPC(getPm());
2475:            }
2476:
2477:            //==============================getXXXFields====================================
2478:
2479:            public boolean getBooleanField(PersistenceCapable pc, int field,
2480:                    boolean currentValue) {
2481:                try {
2482:                    return getBooleanFieldImp(pc, getFMD(field), currentValue);
2483:                } catch (Exception e) {
2484:                    handleException(e);
2485:                }
2486:                return false;
2487:            }
2488:
2489:            public boolean getBooleanFieldImp(PersistenceCapable pc,
2490:                    FieldMetaData fmd, boolean currentValue) {
2491:                try {
2492:                    doRead(fmd);
2493:                    return state.getBooleanField(fmd.stateFieldNo);
2494:                } catch (Exception e) {
2495:                    handleException(e);
2496:                }
2497:                return false;
2498:            }
2499:
2500:            public char getCharField(PersistenceCapable pc, int field,
2501:                    char currentValue) {
2502:                try {
2503:                    return getCharFieldImp(pc, getFMD(field), currentValue);
2504:                } catch (Exception e) {
2505:                    handleException(e);
2506:                }
2507:                return 0;
2508:            }
2509:
2510:            public char getCharFieldImp(PersistenceCapable pc,
2511:                    FieldMetaData fmd, char currentValue) {
2512:                try {
2513:                    doRead(fmd);
2514:                    return state.getCharField(fmd.stateFieldNo);
2515:                } catch (Exception e) {
2516:                    handleException(e);
2517:                }
2518:                return 0;
2519:            }
2520:
2521:            public byte getByteField(PersistenceCapable pc, int field,
2522:                    byte currentValue) {
2523:                try {
2524:                    return getByteFieldImp(pc, getFMD(field), currentValue);
2525:                } catch (Exception e) {
2526:                    handleException(e);
2527:                }
2528:                return 0;
2529:            }
2530:
2531:            public byte getByteFieldImp(PersistenceCapable pc,
2532:                    FieldMetaData fmd, byte currentValue) {
2533:                try {
2534:                    doRead(fmd);
2535:                    return state.getByteField(fmd.stateFieldNo);
2536:                } catch (Exception e) {
2537:                    handleException(e);
2538:                }
2539:                return 0;
2540:            }
2541:
2542:            public short getShortField(PersistenceCapable pc, int field,
2543:                    short currentValue) {
2544:                try {
2545:                    return getShortFieldImp(pc, getFMD(field), currentValue);
2546:                } catch (Exception e) {
2547:                    handleException(e);
2548:                }
2549:                return 0;
2550:            }
2551:
2552:            public short getShortFieldImp(PersistenceCapable pc,
2553:                    FieldMetaData fmd, short currentValue) {
2554:                try {
2555:                    doRead(fmd);
2556:                    return state.getShortField(fmd.stateFieldNo);
2557:                } catch (Exception e) {
2558:                    handleException(e);
2559:                }
2560:                return 0;
2561:            }
2562:
2563:            public int getIntField(PersistenceCapable pc, int field,
2564:                    int currentValue) {
2565:                try {
2566:                    return getIntFieldImp(pc, getFMD(field), currentValue);
2567:                } catch (Exception e) {
2568:                    handleException(e);
2569:                }
2570:                return 0;
2571:            }
2572:
2573:            public int getIntFieldImp(PersistenceCapable pc, FieldMetaData fmd,
2574:                    int currentValue) {
2575:                try {
2576:                    doRead(fmd);
2577:                    return state.getIntField(fmd.stateFieldNo);
2578:                } catch (Exception e) {
2579:                    handleException(e);
2580:                }
2581:                return 0;
2582:            }
2583:
2584:            public float getFloatField(PersistenceCapable pc, int field,
2585:                    float currentValue) {
2586:                try {
2587:                    return getFloatFieldImp(pc, getFMD(field), currentValue);
2588:                } catch (Exception e) {
2589:                    handleException(e);
2590:                }
2591:                return 0;
2592:            }
2593:
2594:            public float getFloatFieldImp(PersistenceCapable pc,
2595:                    FieldMetaData fmd, float currentValue) {
2596:                try {
2597:                    doRead(fmd);
2598:                    return state.getFloatField(fmd.stateFieldNo);
2599:                } catch (Exception e) {
2600:                    handleException(e);
2601:                }
2602:                return 0;
2603:            }
2604:
2605:            public double getDoubleField(PersistenceCapable pc, int field,
2606:                    double currentValue) {
2607:                try {
2608:                    return getDoubleFieldImp(pc, getFMD(field), currentValue);
2609:                } catch (Exception e) {
2610:                    handleException(e);
2611:                }
2612:                return 0;
2613:            }
2614:
2615:            public double getDoubleFieldImp(PersistenceCapable pc,
2616:                    FieldMetaData fmd, double currentValue) {
2617:                try {
2618:                    doRead(fmd);
2619:                    return state.getDoubleField(fmd.stateFieldNo);
2620:                } catch (Exception e) {
2621:                    handleException(e);
2622:                }
2623:                return 0;
2624:            }
2625:
2626:            public long getLongField(PersistenceCapable pc, int field,
2627:                    long currentValue) {
2628:                try {
2629:                    return getLongFieldImp(pc, getFMD(field), currentValue);
2630:                } catch (Exception e) {
2631:                    handleException(e);
2632:                }
2633:                return 0;
2634:            }
2635:
2636:            public long getLongFieldImp(PersistenceCapable pc,
2637:                    FieldMetaData fmd, long currentValue) {
2638:                try {
2639:                    doRead(fmd);
2640:                    return state.getLongField(fmd.stateFieldNo);
2641:                } catch (Exception e) {
2642:                    handleException(e);
2643:                }
2644:                return 0;
2645:            }
2646:
2647:            public String getStringField(PersistenceCapable pc, int field,
2648:                    String currentValue) {
2649:                return getStringFieldImp(pc, getFMD(field), currentValue);
2650:            }
2651:
2652:            public String getStringFieldImp(PersistenceCapable pc,
2653:                    FieldMetaData fmd, String currentValue) {
2654:                try {
2655:                    doRead(fmd);
2656:                    return state.getStringField(fmd.stateFieldNo);
2657:                } catch (Exception e) {
2658:                    handleException(e);
2659:                }
2660:                return null;
2661:            }
2662:
2663:            public Object getObjectField(PersistenceCapable pc, int field,
2664:                    Object currentValue) {
2665:                return getObjectFieldImp(pc, getFMD(field), currentValue);
2666:            }
2667:
2668:            public Object getObjectFieldImp(PersistenceCapable pc,
2669:                    FieldMetaData fmd, Object currentValue) {
2670:                try {
2671:                    StatesReturned nogc = doRead(fmd);
2672:                    // Keep a reference to the fetched States (if any) to make sure
2673:                    // they do not get GCed after being loaded into the local cache.
2674:                    // This is important for collections of PC and other fields that
2675:                    // involve fetching State instances and loading them into the local
2676:                    // cache. They are only hard referenced when the SCO instance has
2677:                    // been created by the next line.
2678:                    Object ans = state.getObjectField(fmd.stateFieldNo,
2679:                            this .pc, getPm(), oid);
2680:                    if (nogc == null) {
2681:                        // dummy code to keep IDE happy and to hopefully prevent
2682:                        // any overzealous optimization from removing nogc
2683:                    }
2684:                    return ans;
2685:                } catch (Exception e) {
2686:                    handleException(e);
2687:                }
2688:                return null;
2689:            }
2690:
2691:            //================================setXXXField===================================
2692:
2693:            public void setBooleanField(PersistenceCapable pc, int field,
2694:                    boolean currentValue, boolean newValue) {
2695:                try {
2696:                    setBooleanFieldImp(pc, getFMD(field), currentValue,
2697:                            newValue);
2698:                    pc.jdoReplaceField(field);
2699:                } catch (Exception e) {
2700:                    handleException(e);
2701:                }
2702:            }
2703:
2704:            public void setBooleanFieldImp(PersistenceCapable pc,
2705:                    FieldMetaData fmd, boolean currentValue, boolean newValue) {
2706:                try {
2707:                    if (isTransientManaged()) {
2708:                        state.setBooleanField(fmd.stateFieldNo, newValue);
2709:                        if (getPm().isActive()) {
2710:                            stateM |= MASK_DIRTY;
2711:                            setBeforeState(fmd, currentValue);
2712:                        }
2713:                        addToProcessList();
2714:                    } else {
2715:                        if (loadedFields[fmd.stateFieldNo]
2716:                                && newValue == currentValue)
2717:                            return;
2718:                        doWrite(fmd, false);
2719:                        state.setBooleanField(fmd.stateFieldNo, newValue);
2720:                        setBeforeState(fmd, currentValue);
2721:                    }
2722:                } catch (Exception e) {
2723:                    handleException(e);
2724:                }
2725:            }
2726:
2727:            public void setCharField(PersistenceCapable pc, int field,
2728:                    char currentValue, char newValue) {
2729:                try {
2730:                    setCharFieldImp(pc, getFMD(field), currentValue, newValue);
2731:                    pc.jdoReplaceField(field);
2732:                } catch (Exception e) {
2733:                    handleException(e);
2734:                }
2735:            }
2736:
2737:            public void setCharFieldImp(PersistenceCapable pc,
2738:                    FieldMetaData fmd, char currentValue, char newValue) {
2739:                try {
2740:                    if (isTransientManaged()) {
2741:                        state.setCharField(fmd.stateFieldNo, newValue);
2742:                        if (getPm().isActive()) {
2743:                            stateM |= MASK_DIRTY;
2744:                            setBeforeState(fmd, currentValue);
2745:                        }
2746:                        addToProcessList();
2747:                    } else {
2748:                        if (loadedFields[fmd.stateFieldNo]
2749:                                && newValue == currentValue)
2750:                            return;
2751:                        doWrite(fmd, false);
2752:                        state.setCharField(fmd.stateFieldNo, newValue);
2753:                        setBeforeState(fmd, currentValue);
2754:                    }
2755:                } catch (Exception e) {
2756:                    handleException(e);
2757:                }
2758:            }
2759:
2760:            public void setByteField(PersistenceCapable pc, int field,
2761:                    byte currentValue, byte newValue) {
2762:                try {
2763:                    setByteFieldImp(pc, getFMD(field), currentValue, newValue);
2764:                    pc.jdoReplaceField(field);
2765:                } catch (Exception e) {
2766:                    handleException(e);
2767:                }
2768:            }
2769:
2770:            public void setByteFieldImp(PersistenceCapable pc,
2771:                    FieldMetaData fmd, byte currentValue, byte newValue) {
2772:                try {
2773:                    if (isTransientManaged()) {
2774:                        state.setByteField(fmd.stateFieldNo, newValue);
2775:                        if (getPm().isActive()) {
2776:                            stateM |= MASK_DIRTY;
2777:                            setBeforeState(fmd, currentValue);
2778:                        }
2779:                        addToProcessList();
2780:                    } else {
2781:                        if (loadedFields[fmd.stateFieldNo]
2782:                                && newValue == currentValue)
2783:                            return;
2784:                        doWrite(fmd, false);
2785:                        state.setByteField(fmd.stateFieldNo, newValue);
2786:                        setBeforeState(fmd, currentValue);
2787:                    }
2788:                } catch (Exception e) {
2789:                    handleException(e);
2790:                }
2791:            }
2792:
2793:            public void setShortField(PersistenceCapable pc, int field,
2794:                    short currentValue, short newValue) {
2795:                try {
2796:                    setShortFieldImp(pc, getFMD(field), currentValue, newValue);
2797:                    pc.jdoReplaceField(field);
2798:                } catch (Exception e) {
2799:                    handleException(e);
2800:                }
2801:            }
2802:
2803:            public void setShortFieldImp(PersistenceCapable pc,
2804:                    FieldMetaData fmd, short currentValue, short newValue) {
2805:                try {
2806:                    if (isTransientManaged()) {
2807:                        state.setShortField(fmd.stateFieldNo, newValue);
2808:                        if (getPm().isActive()) {
2809:                            stateM |= MASK_DIRTY;
2810:                            setBeforeState(fmd, currentValue);
2811:                        }
2812:                        addToProcessList();
2813:                    } else {
2814:                        if (loadedFields[fmd.stateFieldNo]
2815:                                && newValue == currentValue)
2816:                            return;
2817:                        doWrite(fmd, false);
2818:                        state.setShortField(fmd.stateFieldNo, newValue);
2819:                        setBeforeState(fmd, currentValue);
2820:                    }
2821:                } catch (Exception e) {
2822:                    handleException(e);
2823:                }
2824:            }
2825:
2826:            public void setIntField(PersistenceCapable pc, int field,
2827:                    int currentValue, int newValue) {
2828:                try {
2829:                    setIntFieldImp(pc, getFMD(field), currentValue, newValue);
2830:                    pc.jdoReplaceField(field);
2831:                } catch (Exception e) {
2832:                    handleException(e);
2833:                }
2834:            }
2835:
2836:            public void setIntFieldImp(PersistenceCapable pc,
2837:                    FieldMetaData fmd, int currentValue, int newValue) {
2838:                try {
2839:                    if (isTransientManaged()) {
2840:                        state.setIntField(fmd.stateFieldNo, newValue);
2841:                        if (getPm().isActive()) {
2842:                            stateM |= MASK_DIRTY;
2843:                            setBeforeState(fmd, currentValue);
2844:                        }
2845:                        addToProcessList();
2846:                    } else {
2847:                        if (loadedFields[fmd.stateFieldNo]
2848:                                && newValue == currentValue)
2849:                            return;
2850:                        doWrite(fmd, false);
2851:                        state.setIntField(fmd.stateFieldNo, newValue);
2852:                        setBeforeState(fmd, currentValue);
2853:                    }
2854:                } catch (Exception e) {
2855:                    handleException(e);
2856:                }
2857:            }
2858:
2859:            public void setFloatField(PersistenceCapable pc, int field,
2860:                    float currentValue, float newValue) {
2861:                try {
2862:                    setFloatFieldImp(pc, getFMD(field), currentValue, newValue);
2863:                    pc.jdoReplaceField(field);
2864:                } catch (Exception e) {
2865:                    handleException(e);
2866:                }
2867:            }
2868:
2869:            public void setFloatFieldImp(PersistenceCapable pc,
2870:                    FieldMetaData fmd, float currentValue, float newValue) {
2871:                try {
2872:                    if (isTransientManaged()) {
2873:                        state.setFloatField(fmd.stateFieldNo, newValue);
2874:                        if (getPm().isActive()) {
2875:                            stateM |= MASK_DIRTY;
2876:                            setBeforeState(fmd, currentValue);
2877:                        }
2878:                        addToProcessList();
2879:                    } else {
2880:                        if (loadedFields[fmd.stateFieldNo]
2881:                                && newValue == currentValue)
2882:                            return;
2883:                        doWrite(fmd, false);
2884:                        state.setFloatField(fmd.stateFieldNo, newValue);
2885:                        setBeforeState(fmd, currentValue);
2886:                    }
2887:                } catch (Exception e) {
2888:                    handleException(e);
2889:                }
2890:            }
2891:
2892:            public void setDoubleField(PersistenceCapable pc, int field,
2893:                    double currentValue, double newValue) {
2894:                try {
2895:                    setDoubleFieldImp(pc, getFMD(field), currentValue, newValue);
2896:                    pc.jdoReplaceField(field);
2897:                } catch (Exception e) {
2898:                    handleException(e);
2899:                }
2900:            }
2901:
2902:            public void setDoubleFieldImp(PersistenceCapable pc,
2903:                    FieldMetaData fmd, double currentValue, double newValue) {
2904:                try {
2905:                    if (isTransientManaged()) {
2906:                        state.setDoubleField(fmd.stateFieldNo, newValue);
2907:                        if (getPm().isActive()) {
2908:                            stateM |= MASK_DIRTY;
2909:                            setBeforeState(fmd, currentValue);
2910:                        }
2911:                        addToProcessList();
2912:                    } else {
2913:                        if (loadedFields[fmd.stateFieldNo]
2914:                                && newValue == currentValue)
2915:                            return;
2916:                        doWrite(fmd, false);
2917:                        state.setDoubleField(fmd.stateFieldNo, newValue);
2918:                        setBeforeState(fmd, currentValue);
2919:                    }
2920:                } catch (Exception e) {
2921:                    handleException(e);
2922:                }
2923:            }
2924:
2925:            public void setLongField(PersistenceCapable pc, int field,
2926:                    long currentValue, long newValue) {
2927:                try {
2928:                    setLongFieldImp(pc, getFMD(field), currentValue, newValue);
2929:                    pc.jdoReplaceField(field);
2930:                } catch (Exception e) {
2931:                    throw BindingSupportImpl.getInstance().internal(
2932:                            e.getMessage(), e);
2933:                }
2934:            }
2935:
2936:            public void setLongFieldImp(PersistenceCapable pc,
2937:                    FieldMetaData fmd, long currentValue, long newValue) {
2938:                try {
2939:                    if (isTransientManaged()) {
2940:                        state.setLongField(fmd.stateFieldNo, newValue);
2941:                        if (getPm().isActive()) {
2942:                            stateM |= MASK_DIRTY;
2943:                            setBeforeState(fmd, currentValue);
2944:                        }
2945:                        addToProcessList();
2946:                    } else {
2947:                        if (loadedFields[fmd.stateFieldNo]
2948:                                && newValue == currentValue)
2949:                            return;
2950:                        doWrite(fmd, false);
2951:                        state.setLongField(fmd.stateFieldNo, newValue);
2952:                        setBeforeState(fmd, currentValue);
2953:                    }
2954:                } catch (Exception e) {
2955:                    throw BindingSupportImpl.getInstance().internal(
2956:                            e.getMessage(), e);
2957:                }
2958:            }
2959:
2960:            public void setStringField(PersistenceCapable pc, int field,
2961:                    String currentValue, String newValue) {
2962:                setStringFieldImp(pc, getFMD(field), currentValue, newValue);
2963:                pc.jdoReplaceField(field);
2964:            }
2965:
2966:            public void setStringFieldImp(PersistenceCapable pc,
2967:                    FieldMetaData fmd, String currentValue, String newValue) {
2968:                try {
2969:                    if (isTransientManaged()) {
2970:                        state.setStringField(fmd.stateFieldNo, newValue);
2971:                        if (getPm().isActive()) {
2972:                            stateM |= MASK_DIRTY;
2973:                            setBeforeState(fmd, currentValue);
2974:                        }
2975:                        addToProcessList();
2976:                    } else {
2977:                        if (loadedFields[fmd.stateFieldNo]
2978:                                && newValue == currentValue)
2979:                            return;
2980:                        doWrite(fmd, false);
2981:                        state.setStringField(fmd.stateFieldNo, newValue);
2982:                        setBeforeState(fmd, currentValue);
2983:                    }
2984:                } catch (Exception e) {
2985:                    handleException(e);
2986:                }
2987:            }
2988:
2989:            public void setObjectField(PersistenceCapable pc, int field,
2990:                    Object currentValue, Object newValue) {
2991:                setObjectFieldImp(pc, getFMD(field), currentValue, newValue);
2992:                pc.jdoReplaceField(field);
2993:            }
2994:
2995:            public void setObjectFieldImp(PersistenceCapable pc,
2996:                    FieldMetaData fmd, Object currentValue, Object newValue) {
2997:                try {
2998:                    if (isTransientManaged()) {
2999:                        state.setObjectField(fmd.stateFieldNo, newValue);
3000:                        if (getPm().isActive()) {
3001:                            stateM |= MASK_DIRTY;
3002:                            setBeforeState(fmd, currentValue);
3003:                        }
3004:                        addToProcessList();
3005:                    } else {
3006:                        if (loadedFields[fmd.stateFieldNo]
3007:                                && newValue == currentValue)
3008:                            return;
3009:                        doWrite(fmd, fmd.isDetail && fmd.managed);
3010:                        if (fmd.isDetail) {
3011:                            PersistenceCapable currentMaster = (PersistenceCapable) getObjectFieldImp(
3012:                                    null, fmd, null);
3013:                            VersantPersistenceManagerImp pm = getPm();
3014:                            if (fmd.managed) {
3015:                                int mastColFieldNo = fmd.inverseFieldNo;
3016:                                if (currentMaster != null) {
3017:                                    PCStateMan masterSM = pm
3018:                                            .getInternalSM(currentMaster);
3019:                                    if (masterSM.classMetaData.managedFields[mastColFieldNo].type
3020:                                            .getComponentType() != null) {
3021:                                        PersistenceCapable[] pcs = (PersistenceCapable[]) masterSM
3022:                                                .getObjectField(null,
3023:                                                        mastColFieldNo, null);
3024:                                        if (pcs != null) {
3025:                                            for (int i = 0; i < pcs.length; i++) {
3026:                                                PersistenceCapable pcInst = pcs[i];
3027:                                                if (pcInst == this .pc) {
3028:                                                    pcs[i] = null;
3029:                                                }
3030:                                            }
3031:                                        }
3032:                                    } else {
3033:                                        ((Collection) masterSM.getObjectField(
3034:                                                null, mastColFieldNo, null))
3035:                                                .remove(this .pc);
3036:                                    }
3037:                                }
3038:                                if (newValue != null) {
3039:                                    PersistenceCapable newMaster = (PersistenceCapable) newValue;
3040:                                    if (!newMaster.jdoIsPersistent()) {
3041:                                        this .pc.jdoGetPersistenceManager()
3042:                                                .makePersistent(newMaster);
3043:                                    }
3044:                                    PCStateMan masterSM = pm
3045:                                            .getInternalSM(newMaster);
3046:                                    ((Collection) masterSM.getObjectField(null,
3047:                                            mastColFieldNo, null)).add(this .pc);
3048:                                }
3049:                            } else {
3050:                                // Make sure current master and new value is evicted
3051:                                // on commit.
3052:                                // This prevents stale data from remaining in the L2
3053:                                // cache when only the back reference is updated.
3054:                                if (currentMaster != null) {
3055:                                    pm
3056:                                            .evictFromL2CacheAfterCommitImp(currentMaster);
3057:                                }
3058:                                if (newValue != null) {
3059:                                    pm.evictFromL2CacheAfterCommitImp(newValue);
3060:                                }
3061:                            }
3062:                        } else if (fmd.category == MDStatics.CATEGORY_COLLECTION
3063:                                && fmd.inverseFieldMetaData != null
3064:                                && fmd.inverseFieldMetaData.fake) {
3065:                            if (!state.containsField(fmd.stateFieldNo)) {
3066:                                FetchGroup fg = getFetchGroup(fmd.managedFieldNo);
3067:                                getPm()
3068:                                        .getState(
3069:                                                this .oid,
3070:                                                fg.sendFieldsOnFetch ? getForReadState()
3071:                                                        : null, fg.index,
3072:                                                fmd.managedFieldNo, -1, false);
3073:                            }
3074:                            FieldMetaData inverseFieldMetaData = fmd.inverseFieldMetaData;
3075:                            Object o = state
3076:                                    .getInternalObjectField(fmd.stateFieldNo);
3077:                            if (o != null) {
3078:                                if (o instanceof  VersantSimpleSCO) {
3079:                                    VersantPersistenceManagerImp rpm = getPm();
3080:                                    Collection col = (Collection) o;
3081:                                    for (Iterator iterator = col.iterator(); iterator
3082:                                            .hasNext();) {
3083:                                        PCStateMan detailSm = jdoManagedCache
3084:                                                .getByOID(
3085:                                                        rpm
3086:                                                                .getInternalOID((PersistenceCapable) iterator
3087:                                                                        .next()),
3088:                                                        true);
3089:                                        detailSm.makeInternalDirty();
3090:                                        detailSm.state
3091:                                                .setObjectField(
3092:                                                        inverseFieldMetaData.stateFieldNo,
3093:                                                        null);
3094:                                    }
3095:                                } else {
3096:                                    Object[] oa = (Object[]) o;
3097:                                    for (int i = 0; i < oa.length; i++) {
3098:                                        if (oa[i] == null)
3099:                                            break;
3100:                                        PCStateMan detailSm = jdoManagedCache
3101:                                                .getByOID((OID) oa[i], true);
3102:                                        detailSm.makeInternalDirty();
3103:                                        detailSm.state
3104:                                                .setObjectField(
3105:                                                        inverseFieldMetaData.stateFieldNo,
3106:                                                        null);
3107:                                    }
3108:                                }
3109:                            }
3110:                        }
3111:                        state.setObjectField(fmd.stateFieldNo, newValue);
3112:                        setBeforeState(fmd, currentValue);
3113:                    }
3114:                } catch (Exception e) {
3115:                    handleException(e);
3116:                }
3117:            }
3118:
3119:            /**
3120:             * This is called from managed SCO classes to ensure that the back
3121:             * reference of a newly added detail is updated property. It is
3122:             * not possible to just call setObject in this case as this will result
3123:             * in an endless loop as setObject adds the detail to its master.
3124:             * If removeFromCurrentMaster is true then this instance is removed
3125:             * from its current master (if any and if different).
3126:             */
3127:            public void setMaster(int field, Object newMaster,
3128:                    boolean removeFromCurrentMaster) {
3129:                try {
3130:                    Object currentMaster = getObjectField(null, field, null);
3131:                    if (loadedFields[field] && newMaster == currentMaster)
3132:                        return;
3133:                    doWrite(getFMD(field), false);
3134:                    if (removeFromCurrentMaster && currentMaster != null) {
3135:                        int mastColFieldNo = getFMD(field).inverseFieldNo;
3136:                        PCStateMan masterSM = getPm().getInternalSM(
3137:                                (PersistenceCapable) currentMaster);
3138:                        ((Collection) masterSM.getObjectField(null,
3139:                                mastColFieldNo, null)).remove(pc);
3140:                    }
3141:                    state.setObjectFieldAbs(field, newMaster);
3142:                    pc.jdoReplaceField(field);
3143:                    setBeforeState(getFMD(field), currentMaster);
3144:                } catch (Exception e) {
3145:                    handleException(e);
3146:                }
3147:            }
3148:
3149:            /**
3150:             * This is called from managed SCO classes to ensure that the back
3151:             * reference of a newly added detail is updated property. It is
3152:             * not possible to just call setObject in this case as this will result
3153:             * in an endless loop as setObject adds the detail to its master.
3154:             * If removeFromCurrentMaster is true then this instance is removed
3155:             * from its current master (if any and if different).
3156:             */
3157:            public void setFakeMaster(int stateFieldNo,
3158:                    VersantStateManager master, boolean remove) {
3159:                VersantPersistenceManagerImp rpm = getPm();
3160:
3161:                try {
3162:                    if (isPrepared()) {
3163:                        if (inToStoreList()) {
3164:                            //already prepared so add oid to the tostorestate
3165:                            setOidOnState(toStoreState, stateFieldNo, master,
3166:                                    remove);
3167:                        } else {
3168:                            //prepared was called but no dirty fields was found
3169:                            //so prepare must be called again
3170:                            if (setOidOnState(state, stateFieldNo, master,
3171:                                    remove)) {
3172:                                state.fillToStoreState(toStoreState, rpm, this );
3173:                            }
3174:                            //must add to toStoreList
3175:                            addToStoreOidContainer(toStoreState, rpm, master
3176:                                    .getOID().isNew());
3177:                        }
3178:                    } else {
3179:                        setOidOnState(state, stateFieldNo, master, remove);
3180:                    }
3181:                    makeInternalDirty();
3182:                } catch (Exception e) {
3183:                    handleException(e);
3184:                }
3185:            }
3186:
3187:            private boolean setOidOnState(State state, int stateFieldNo,
3188:                    VersantStateManager master, boolean remove) {
3189:                if (state instanceof  DeletedState) {
3190:                    return false;
3191:                }
3192:                if (remove) {
3193:                    Object o = state.getInternalObjectField(stateFieldNo);
3194:                    if (o != null && !o.equals(master.getOID())
3195:                            && o != master.getPersistenceCapable()) {
3196:                        return false;
3197:                    }
3198:                }
3199:                if (remove) {
3200:                    state.setObjectField(stateFieldNo, null);
3201:                } else {
3202:                    state.setObjectFieldUnresolved(stateFieldNo, master
3203:                            .getOID());
3204:                }
3205:                return true;
3206:            }
3207:
3208:            private boolean inToStoreList() {
3209:                return preparedStatus == 2;
3210:            }
3211:
3212:            private boolean isPrepared() {
3213:                return preparedStatus > 0;
3214:            }
3215:
3216:            //===================================providedXXXFields============================
3217:
3218:            public void providedBooleanField(PersistenceCapable pc, int field,
3219:                    boolean currentValue) {
3220:                try {
3221:                    providedBooleanFieldImp(pc, getFMD(field), currentValue);
3222:                } catch (Exception e) {
3223:                    handleException(e);
3224:                }
3225:            }
3226:
3227:            public void providedBooleanFieldImp(PersistenceCapable pc,
3228:                    FieldMetaData fmd, boolean currentValue) {
3229:                try {
3230:                    state.setBooleanField(fmd.stateFieldNo, currentValue);
3231:                    setBeforeState(fmd, currentValue);
3232:                } catch (Exception e) {
3233:                    handleException(e);
3234:                }
3235:            }
3236:
3237:            public void providedCharField(PersistenceCapable pc, int field,
3238:                    char currentValue) {
3239:                try {
3240:                    providedCharFieldImp(pc, getFMD(field), currentValue);
3241:                } catch (Exception e) {
3242:                    handleException(e);
3243:                }
3244:            }
3245:
3246:            public void providedCharFieldImp(PersistenceCapable pc,
3247:                    FieldMetaData fmd, char currentValue) {
3248:                try {
3249:                    state.setCharField(fmd.stateFieldNo, currentValue);
3250:                    setBeforeState(fmd, currentValue);
3251:                } catch (Exception e) {
3252:                    handleException(e);
3253:                }
3254:            }
3255:
3256:            public void providedByteField(PersistenceCapable pc, int field,
3257:                    byte currentValue) {
3258:                try {
3259:                    providedByteFieldImp(pc, getFMD(field), currentValue);
3260:                } catch (Exception e) {
3261:                    handleException(e);
3262:                }
3263:            }
3264:
3265:            public void providedByteFieldImp(PersistenceCapable pc,
3266:                    FieldMetaData fmd, byte currentValue) {
3267:                try {
3268:                    state.setByteField(fmd.stateFieldNo, currentValue);
3269:                    setBeforeState(fmd, currentValue);
3270:                } catch (Exception e) {
3271:                    handleException(e);
3272:                }
3273:            }
3274:
3275:            public void providedShortField(PersistenceCapable pc, int field,
3276:                    short currentValue) {
3277:                try {
3278:                    providedShortFieldImp(pc, getFMD(field), currentValue);
3279:                } catch (Exception e) {
3280:                    handleException(e);
3281:                }
3282:            }
3283:
3284:            public void providedShortFieldImp(PersistenceCapable pc,
3285:                    FieldMetaData fmd, short currentValue) {
3286:                try {
3287:                    state.setShortField(fmd.stateFieldNo, currentValue);
3288:                    setBeforeState(fmd, currentValue);
3289:                } catch (Exception e) {
3290:                    handleException(e);
3291:                }
3292:            }
3293:
3294:            public void providedIntField(PersistenceCapable pc, int field,
3295:                    int currentValue) {
3296:                try {
3297:                    providedIntFieldImp(pc, getFMD(field), currentValue);
3298:                } catch (Exception e) {
3299:                    handleException(e);
3300:                }
3301:            }
3302:
3303:            public void providedIntFieldImp(PersistenceCapable pc,
3304:                    FieldMetaData fmd, int currentValue) {
3305:                try {
3306:                    state.setIntField(fmd.stateFieldNo, currentValue);
3307:                    setBeforeState(fmd, currentValue);
3308:                } catch (Exception e) {
3309:                    handleException(e);
3310:                }
3311:            }
3312:
3313:            public void providedFloatField(PersistenceCapable pc, int field,
3314:                    float currentValue) {
3315:                try {
3316:                    providedFloatFieldImp(pc, getFMD(field), currentValue);
3317:                } catch (Exception e) {
3318:                    handleException(e);
3319:                }
3320:            }
3321:
3322:            public void providedFloatFieldImp(PersistenceCapable pc,
3323:                    FieldMetaData fmd, float currentValue) {
3324:                try {
3325:                    state.setFloatField(fmd.stateFieldNo, currentValue);
3326:                    setBeforeState(fmd, currentValue);
3327:                } catch (Exception e) {
3328:                    handleException(e);
3329:                }
3330:            }
3331:
3332:            public void providedDoubleField(PersistenceCapable pc, int field,
3333:                    double currentValue) {
3334:                try {
3335:                    providedDoubleFieldImp(pc, getFMD(field), currentValue);
3336:                } catch (Exception e) {
3337:                    handleException(e);
3338:                }
3339:            }
3340:
3341:            public void providedDoubleFieldImp(PersistenceCapable pc,
3342:                    FieldMetaData fmd, double currentValue) {
3343:                try {
3344:                    state.setDoubleField(fmd.stateFieldNo, currentValue);
3345:                    setBeforeState(fmd, currentValue);
3346:                } catch (Exception e) {
3347:                    handleException(e);
3348:                }
3349:            }
3350:
3351:            public void providedLongField(PersistenceCapable pc, int field,
3352:                    long currentValue) {
3353:                try {
3354:                    providedLongFieldImp(pc, getFMD(field), currentValue);
3355:                } catch (Exception e) {
3356:                    handleException(e);
3357:                }
3358:            }
3359:
3360:            public void providedLongFieldImp(PersistenceCapable pc,
3361:                    FieldMetaData fmd, long currentValue) {
3362:                try {
3363:                    state.setLongField(fmd.stateFieldNo, currentValue);
3364:                    setBeforeState(fmd, currentValue);
3365:                } catch (Exception e) {
3366:                    handleException(e);
3367:                }
3368:            }
3369:
3370:            public void providedStringField(PersistenceCapable pc, int field,
3371:                    String currentValue) {
3372:                try {
3373:                    providedStringFieldImp(pc, getFMD(field), currentValue);
3374:                } catch (Exception e) {
3375:                    handleException(e);
3376:                }
3377:            }
3378:
3379:            public void providedStringFieldImp(PersistenceCapable pc,
3380:                    FieldMetaData fmd, String currentValue) {
3381:                try {
3382:                    state.setStringField(fmd.stateFieldNo, currentValue);
3383:                    setBeforeState(fmd, currentValue);
3384:                } catch (Exception e) {
3385:                    handleException(e);
3386:                }
3387:            }
3388:
3389:            public void providedObjectField(PersistenceCapable pc, int field,
3390:                    Object currentValue) {
3391:                providedObjectFieldImp(pc, getFMD(field), currentValue);
3392:            }
3393:
3394:            public void providedObjectFieldImp(PersistenceCapable pc,
3395:                    FieldMetaData fmd, Object currentValue) {
3396:                try {
3397:                    state.setObjectField(fmd.stateFieldNo, currentValue);
3398:                    setBeforeState(fmd, currentValue);
3399:                } catch (Exception e) {
3400:                    handleException(e);
3401:                }
3402:            }
3403:
3404:            //===================================replacingXXXFields============================
3405:
3406:            public boolean replacingBooleanField(final PersistenceCapable pc,
3407:                    final int field) {
3408:                return replacingBooleanFieldImp(pc, getFMD(field));
3409:            }
3410:
3411:            public boolean replacingBooleanFieldImp(
3412:                    final PersistenceCapable pc, FieldMetaData fmd) {
3413:                try {
3414:                    setLoaded(fmd);
3415:                    return state.getBooleanField(fmd.stateFieldNo);
3416:                } catch (Exception e) {
3417:                    handleException(e);
3418:                }
3419:                return false;
3420:            }
3421:
3422:            public char replacingCharField(final PersistenceCapable pc,
3423:                    final int field) {
3424:                return replacingCharFieldImp(pc, getFMD(field));
3425:            }
3426:
3427:            public char replacingCharFieldImp(final PersistenceCapable pc,
3428:                    final FieldMetaData fmd) {
3429:                try {
3430:                    setLoaded(fmd);
3431:                    return state.getCharField(fmd.stateFieldNo);
3432:                } catch (Exception e) {
3433:                    handleException(e);
3434:                }
3435:                return 0;
3436:            }
3437:
3438:            public byte replacingByteField(final PersistenceCapable pc,
3439:                    final int field) {
3440:                return replacingByteFieldImp(pc, getFMD(field));
3441:            }
3442:
3443:            public byte replacingByteFieldImp(final PersistenceCapable pc,
3444:                    final FieldMetaData fmd) {
3445:                try {
3446:                    setLoaded(fmd);
3447:                    return state.getByteField(fmd.stateFieldNo);
3448:                } catch (Exception e) {
3449:                    handleException(e);
3450:                }
3451:                return 0;
3452:            }
3453:
3454:            public short replacingShortField(final PersistenceCapable pc,
3455:                    final int field) {
3456:                return replacingShortFieldImp(pc, getFMD(field));
3457:            }
3458:
3459:            public short replacingShortFieldImp(final PersistenceCapable pc,
3460:                    final FieldMetaData fmd) {
3461:                try {
3462:                    setLoaded(fmd);
3463:                    return state.getShortField(fmd.stateFieldNo);
3464:                } catch (Exception e) {
3465:                    handleException(e);
3466:                }
3467:                return 0;
3468:            }
3469:
3470:            public int replacingIntField(final PersistenceCapable pc,
3471:                    final int field) {
3472:                return replacingIntFieldImp(pc, getFMD(field));
3473:            }
3474:
3475:            public int replacingIntFieldImp(final PersistenceCapable pc,
3476:                    final FieldMetaData fmd) {
3477:                try {
3478:                    setLoaded(fmd);
3479:                    return state.getIntField(fmd.stateFieldNo);
3480:                } catch (Exception e) {
3481:                    handleException(e);
3482:                }
3483:                return 0;
3484:            }
3485:
3486:            public float replacingFloatField(final PersistenceCapable pc,
3487:                    final int field) {
3488:                return replacingFloatFieldImp(pc, getFMD(field));
3489:            }
3490:
3491:            public float replacingFloatFieldImp(final PersistenceCapable pc,
3492:                    final FieldMetaData fmd) {
3493:                try {
3494:                    setLoaded(fmd);
3495:                    return state.getFloatField(fmd.stateFieldNo);
3496:                } catch (Exception e) {
3497:                    handleException(e);
3498:                }
3499:                return 0;
3500:            }
3501:
3502:            public double replacingDoubleField(final PersistenceCapable pc,
3503:                    final int field) {
3504:                return replacingDoubleFieldImp(pc, getFMD(field));
3505:            }
3506:
3507:            public double replacingDoubleFieldImp(final PersistenceCapable pc,
3508:                    final FieldMetaData fmd) {
3509:                try {
3510:                    setLoaded(fmd);
3511:                    return state.getDoubleField(fmd.stateFieldNo);
3512:                } catch (Exception e) {
3513:                    handleException(e);
3514:                }
3515:                return 0;
3516:            }
3517:
3518:            public long replacingLongField(final PersistenceCapable pc,
3519:                    final int field) {
3520:                return replacingLongFieldImp(pc, getFMD(field));
3521:            }
3522:
3523:            public long replacingLongFieldImp(final PersistenceCapable pc,
3524:                    final FieldMetaData fmd) {
3525:                try {
3526:                    setLoaded(fmd);
3527:                    return state.getLongField(fmd.stateFieldNo);
3528:                } catch (Exception e) {
3529:                    handleException(e);
3530:                }
3531:                return 0;
3532:            }
3533:
3534:            public String replacingStringField(final PersistenceCapable pc,
3535:                    final int field) {
3536:                return replacingStringFieldImp(pc, getFMD(field));
3537:            }
3538:
3539:            public String replacingStringFieldImp(final PersistenceCapable pc,
3540:                    FieldMetaData fmd) {
3541:                try {
3542:                    setLoaded(fmd);
3543:                    return state.getStringField(fmd.stateFieldNo);
3544:                } catch (Exception e) {
3545:                    handleException(e);
3546:                }
3547:                return null;
3548:            }
3549:
3550:            public Object replacingObjectField(final PersistenceCapable pc,
3551:                    final int field) {
3552:                return replacingObjectFieldImp(pc, getFMD(field));
3553:            }
3554:
3555:            public Object replacingObjectFieldImp(final PersistenceCapable pc,
3556:                    final FieldMetaData fmd) {
3557:                try {
3558:                    if (stateM == STATE_TRANSIENT) {
3559:                        return state.getInternalObjectField(fmd.stateFieldNo);
3560:                    } else {
3561:                        setLoaded(fmd);
3562:                        return state.getObjectField(fmd.stateFieldNo, this .pc,
3563:                                getPm(), oid);
3564:                    }
3565:                } catch (Exception e) {
3566:                    handleException(e);
3567:                }
3568:                return null;
3569:            }
3570:
3571:            private void setBeforeState(FieldMetaData fmd, long oldValue) {
3572:                if (!doBeforeState(fmd))
3573:                    return;
3574:                if (!beforeState.containsField(fmd.stateFieldNo)) {
3575:                    beforeState.setLongField(fmd.stateFieldNo, oldValue);
3576:                }
3577:            }
3578:
3579:            private boolean doBeforeState(FieldMetaData fmd) {
3580:                if (!getPm().doBeforeState(isTransientManaged(),
3581:                        fmd.category == MDStatics.CATEGORY_TRANSACTIONAL)) {
3582:                    return false;
3583:                }
3584:                if (beforeState == null) {
3585:                    beforeState = createStateImp();
3586:                }
3587:                return true;
3588:            }
3589:
3590:            private void setBeforeState(FieldMetaData fmd, int oldValue) {
3591:                if (!doBeforeState(fmd))
3592:                    return;
3593:                if (!beforeState.containsField(fmd.stateFieldNo)) {
3594:                    beforeState.setIntField(fmd.stateFieldNo, oldValue);
3595:                }
3596:            }
3597:
3598:            private void setBeforeState(FieldMetaData fmd, double currentValue) {
3599:                if (!doBeforeState(fmd))
3600:                    return;
3601:                if (!beforeState.containsField(fmd.stateFieldNo)) {
3602:                    beforeState.setDoubleField(fmd.stateFieldNo, currentValue);
3603:                }
3604:            }
3605:
3606:            private void setBeforeState(FieldMetaData fmd, String newValue) {
3607:                if (!doBeforeState(fmd))
3608:                    return;
3609:                if (!beforeState.containsField(fmd.stateFieldNo)) {
3610:                    beforeState.setStringField(fmd.stateFieldNo, newValue);
3611:                }
3612:            }
3613:
3614:            private void setBeforeState(FieldMetaData fmd, Object newValue) {
3615:                /**
3616:                 * Only mutable fields of PNew instance values kept for rollback
3617:                 * Other states fields are refetched from db.
3618:                 */
3619:                if (!isNew()
3620:                        && fmd.category != MDStatics.CATEGORY_TRANSACTIONAL)
3621:                    return;
3622:                if (!doBeforeState(fmd))
3623:                    return;
3624:                if (!beforeState.containsField(fmd.stateFieldNo)) {
3625:                    beforeState.setObjectField(fmd.stateFieldNo, newValue);
3626:                }
3627:            }
3628:
3629:            private void setBeforeState(FieldMetaData fmd, char currentValue) {
3630:                if (!doBeforeState(fmd))
3631:                    return;
3632:                if (!beforeState.containsField(fmd.stateFieldNo)) {
3633:                    beforeState.setCharField(fmd.stateFieldNo, currentValue);
3634:                }
3635:            }
3636:
3637:            private void setBeforeState(FieldMetaData fmd, byte currentValue) {
3638:                if (!doBeforeState(fmd))
3639:                    return;
3640:                if (!beforeState.containsField(fmd.stateFieldNo)) {
3641:                    beforeState.setByteField(fmd.stateFieldNo, currentValue);
3642:                }
3643:            }
3644:
3645:            public void setBeforeState(FieldMetaData fmd, boolean currentValue) {
3646:                if (!doBeforeState(fmd))
3647:                    return;
3648:                if (!beforeState.containsField(fmd.stateFieldNo)) {
3649:                    beforeState.setBooleanField(fmd.stateFieldNo, currentValue);
3650:                }
3651:            }
3652:
3653:            private void setBeforeState(FieldMetaData fmd, short currentValue) {
3654:                if (!doBeforeState(fmd))
3655:                    return;
3656:                if (!beforeState.containsField(fmd.stateFieldNo)) {
3657:                    beforeState.setShortField(fmd.stateFieldNo, currentValue);
3658:                }
3659:            }
3660:
3661:            private void setBeforeState(FieldMetaData fmd, float currentValue) {
3662:                if (!doBeforeState(fmd))
3663:                    return;
3664:                if (!beforeState.containsField(fmd.stateFieldNo)) {
3665:                    beforeState.setFloatField(fmd.stateFieldNo, currentValue);
3666:                }
3667:            }
3668:
3669:            public final void handleException(Exception x) {
3670:                if (BindingSupportImpl.getInstance().isOwnException(x)) {
3671:                    throw (RuntimeException) x;
3672:                } else {
3673:                    throw BindingSupportImpl.getInstance().internal(
3674:                            x.getMessage(), x);
3675:                }
3676:            }
3677:
3678:            public boolean isInDirtyList(PCStateMan head) {
3679:                return head == this  || next != null || prev != null;
3680:            }
3681:
3682:            public Object getOptimisticLockingValue() {
3683:                if (oid.isNew())
3684:                    return null;
3685:                getPm().checkNonTxRead();
3686:                loadRequiredFetchGroup();
3687:                return state.getOptimisticLockingValue();
3688:            }
3689:
3690:            public void firePostStore(LifecycleListenerManager listeners) {
3691:                // pc may be null if the instance has been deleted
3692:                if (pc != null) {
3693:                    listeners.firePostStore(pc);
3694:                }
3695:            }
3696:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.