public Object attach()

in openjpa-kernel/src/main/java/org/apache/openjpa/kernel/DetachedStateManager.java [108:333]


    public Object attach(AttachManager manager, Object toAttach,
        ClassMetaData meta, PersistenceCapable into, OpenJPAStateManager owner,
        ValueMetaData ownerMeta, boolean explicit) {
        BrokerImpl broker = manager.getBroker();
        StateManagerImpl sm;
        if (_embedded) {
            if (_dirty.length () > 0)
                owner.dirty(ownerMeta.getFieldMetaData().getIndex());
            sm = (StateManagerImpl) broker.embed(_pc, _oid, owner, ownerMeta);
            ImplHelper.toPersistenceCapable(toAttach, broker.getConfiguration())
                .pcReplaceStateManager(this);
        } else {
            PCState state = (_dirty.length() > 0) ? PCState.PDIRTY
                : PCState.PCLEAN;
            sm = (StateManagerImpl) broker.copy(this, state);
        }
        PersistenceCapable pc = sm.getPersistenceCapable();
        manager.setAttachedCopy(toAttach, pc);

        manager.fireBeforeAttach(toAttach, meta);

        // pre-load for efficiency: current field values for restore, dependent
        // for delete
        FieldMetaData[] fields = sm.getMetaData().getFields();
        int restore = broker.getRestoreState();

        boolean postLoadOnMerge = broker.getPostLoadOnMerge();
        if (_dirty.length() > 0 || postLoadOnMerge) {
            BitSet load = new BitSet(fields.length);
            if (postLoadOnMerge && broker.getLifecycleEventManager().hasLoadListeners(pc, meta)) {
                // load all fields
                // this will automatically lead to invoking the PostLoad lifecycle event
                // when the last field got set
                // @see StateManagerImpl#postLoad(String, FetchConfiguration)
                load.set(0, fields.length);
            }
            else {
                for (int i = 0; i < fields.length; i++) {
                    if (!_dirty.get(i))
                        continue;

                    switch (fields[i].getDeclaredTypeCode()) {
                        case JavaTypes.ARRAY:
                        case JavaTypes.COLLECTION:
                            if (restore == RestoreState.RESTORE_ALL
                                || fields[i].getElement().getCascadeDelete()
                                == ValueMetaData.CASCADE_AUTO)
                                load.set(i);
                            break;
                        case JavaTypes.MAP:
                            if (restore == RestoreState.RESTORE_ALL
                                || fields[i].getElement().getCascadeDelete()
                                == ValueMetaData.CASCADE_AUTO
                                || fields[i].getKey().getCascadeDelete()
                                == ValueMetaData.CASCADE_AUTO)
                                load.set(i);
                            break;
                        default:
                            if (restore != RestoreState.RESTORE_NONE
                                || fields[i].getCascadeDelete()
                                == ValueMetaData.CASCADE_AUTO)
                                load.set(i);
                    }
                }
            }

            if (!postLoadOnMerge) {
                // prevent PostLoad callbacks even for the load operation
                sm.setPostLoadCallback(false);
            }
            FetchConfiguration fc = broker.getFetchConfiguration();
            sm.loadFields(load, fc, fc.getWriteLockLevel(), null);
        }
        Object origVersion = sm.getVersion();
        sm.setVersion(_version);

        BitSet loaded = sm.getLoaded();
        int set = StateManager.SET_ATTACH;
        sm.setPostLoadCallback(false);
        for (int i = 0; i < fields.length; i++) {
            if (!_loaded.get(i))
                continue;
            // don't reload already loaded non-mutable objects
            if (!_dirty.get(i) && loaded.get(i) && ignoreLoaded(fields[i]))
                continue;

            provideField(i);
            switch (fields[i].getDeclaredTypeCode()) {
                case JavaTypes.BOOLEAN:
                    if (_dirty.get(i))
                        sm.settingBooleanField(pc, i,
                            (loaded.get(i)) && sm.fetchBooleanField(i),
                            longval == 1, set);
                    else
                        sm.storeBooleanField(i, longval == 1);
                    break;
                case JavaTypes.BYTE:
                    if (_dirty.get(i))
                        sm.settingByteField(pc, i, (!loaded.get(i)) ? (byte) 0
                            : sm.fetchByteField(i), (byte) longval, set);
                    else
                        sm.storeByteField(i, (byte) longval);
                    break;
                case JavaTypes.CHAR:
                    if (_dirty.get(i))
                        sm.settingCharField(pc, i, (!loaded.get(i)) ? (char) 0
                            : sm.fetchCharField(i), (char) longval, set);
                    else
                        sm.storeCharField(i, (char) longval);
                    break;
                case JavaTypes.INT:
                    if (_dirty.get(i))
                        sm.settingIntField(pc, i, (!loaded.get(i)) ? 0
                            : sm.fetchIntField(i), (int) longval, set);
                    else
                        sm.storeIntField(i, (int) longval);
                    break;
                case JavaTypes.LONG:
                    if (_dirty.get(i))
                        sm.settingLongField(pc, i, (!loaded.get(i)) ? 0L
                            : sm.fetchLongField(i), longval, set);
                    else
                        sm.storeLongField(i, longval);
                    break;
                case JavaTypes.SHORT:
                    if (_dirty.get(i))
                        sm.settingShortField(pc, i,
                            (!loaded.get(i)) ? (short) 0 : sm.fetchShortField(i), (short) longval, set);
                    else
                        sm.storeShortField(i, (short) longval);
                    break;
                case JavaTypes.FLOAT:
                    if (_dirty.get(i))
                        sm.settingFloatField(pc, i, (!loaded.get(i)) ? 0F
                            : sm.fetchFloatField(i), (float) dblval, set);
                    else
                        sm.storeFloatField(i, (float) dblval);
                    break;
                case JavaTypes.DOUBLE:
                    if (_dirty.get(i))
                        sm.settingDoubleField(pc, i, (!loaded.get(i)) ? 0D
                            : sm.fetchDoubleField(i), dblval, set);
                    else
                        sm.storeDoubleField(i, dblval);
                    break;
                case JavaTypes.STRING:
                    if (_dirty.get(i))
                        sm.settingStringField(pc, i, (!loaded.get(i)) ? null
                            : sm.fetchStringField(i), (String) objval, set);
                    else
                        sm.storeStringField(i, (String) objval);
                    objval = null;
                    break;
                case JavaTypes.PC:
                case JavaTypes.PC_UNTYPED:
                    if (fields[i].getCascadeAttach() == ValueMetaData
                        .CASCADE_NONE) {
                        // Use the attached copy of the object, if available
                        PersistenceCapable cpy = manager.getAttachedCopy(objval);
                        if (cpy != null) {
                            objval = cpy;
                        } else {
                        	objval = getReference(manager, objval, sm, fields[i]);
                        }
                    }
                    else {
                        PersistenceCapable toPC = null;
                        if (objval != null && fields[i].isEmbeddedPC())
                            toPC = ImplHelper.toPersistenceCapable(objval,
                                broker.getConfiguration());
                        objval = manager.attach(objval, toPC, sm, fields[i],
                            false);
                    }
                    if (_dirty.get(i))
                        sm.settingObjectField(pc, i, (!loaded.get(i)) ? null
                            : sm.fetchObjectField(i), objval, set);
                    else
                        sm.storeObjectField(i, objval);
                    objval = null;
                    break;
                case JavaTypes.COLLECTION:
                    Collection coll = (Collection) objval;
                    objval = null;
                    if (coll != null)
                        coll = attachCollection(manager, coll, sm, fields[i]);
                    if (_dirty.get(i))
                        sm.settingObjectField(pc, i, (!loaded.get(i)) ? null
                            : sm.fetchObjectField(i), coll, set);
                    else
                        sm.storeObjectField(i, coll);
                    break;
                case JavaTypes.MAP:
                    Map map = (Map) objval;
                    objval = null;
                    if (map != null)
                        map = attachMap(manager, map, sm, fields[i]);
                    if (_dirty.get(i))
                        sm.settingObjectField(pc, i, (!loaded.get(i)) ? null
                            : sm.fetchObjectField(i), map, set);
                    else
                        sm.storeObjectField(i, map);
                    break;
                default:
                    if (_dirty.get(i))
                        sm.settingObjectField(pc, i, (!loaded.get(i)) ? null
                            : sm.fetchObjectField(i), objval, set);
                    else
                        sm.storeObjectField(i, objval);
                    objval = null;
            }
        }
        sm.setPostLoadCallback(true);
        pc.pcReplaceStateManager(sm);

        // if we were clean at least make sure a version check is done to
        // prevent using old state
        if (!sm.isVersionCheckRequired() && broker.isActive()
            && _version != origVersion && (origVersion == null
            || broker.getStoreManager().compareVersion(sm, _version,
            origVersion) != StoreManager.VERSION_SAME)) {
            broker.transactional(sm.getManagedInstance(), false,
                manager.getBehavior());
        }

        return sm.getManagedInstance();
    }