Search in sources :

Example 86 with AbstractMemberMetaData

use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-core by datanucleus.

the class CopyKeyFieldsFromObjectId method execute.

/**
 * Method to add the contents of the class method.
 */
public void execute() {
    visitor.visitCode();
    ClassMetaData cmd = enhancer.getClassMetaData();
    if (cmd.getIdentityType() == IdentityType.APPLICATION) {
        // application identity
        if (!cmd.isInstantiable()) {
            // Application identity but mapped-superclass with no PK defined, so just "return"
            Label startLabel = new Label();
            visitor.visitLabel(startLabel);
            visitor.visitInsn(Opcodes.RETURN);
            Label endLabel = new Label();
            visitor.visitLabel(endLabel);
            visitor.visitLocalVariable("this", getClassEnhancer().getClassDescriptor(), null, startLabel, endLabel, 0);
            visitor.visitLocalVariable(argNames[0], getNamer().getObjectIdFieldConsumerDescriptor(), null, startLabel, endLabel, 1);
            visitor.visitLocalVariable(argNames[1], EnhanceUtils.CD_Object, null, startLabel, endLabel, 2);
            visitor.visitMaxs(0, 3);
        } else {
            int[] pkFieldNums = cmd.getPKMemberPositions();
            String objectIdClass = cmd.getObjectidClass();
            String ACN_objectIdClass = objectIdClass.replace('.', '/');
            if (IdentityUtils.isSingleFieldIdentityClass(objectIdClass)) {
                // SingleFieldIdentity
                Label startLabel = new Label();
                visitor.visitLabel(startLabel);
                // if (fc == null) throw new IllegalArgumentException("...");
                visitor.visitVarInsn(Opcodes.ALOAD, 1);
                Label l1 = new Label();
                visitor.visitJumpInsn(Opcodes.IFNONNULL, l1);
                visitor.visitTypeInsn(Opcodes.NEW, "java/lang/IllegalArgumentException");
                visitor.visitInsn(Opcodes.DUP);
                visitor.visitLdcInsn("ObjectIdFieldConsumer is null");
                visitor.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/IllegalArgumentException", "<init>", "(Ljava/lang/String;)V");
                visitor.visitInsn(Opcodes.ATHROW);
                // if (!(oid instanceof LongIdentity)) throw new ClassCastException("...");
                visitor.visitLabel(l1);
                visitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
                visitor.visitVarInsn(Opcodes.ALOAD, 2);
                visitor.visitTypeInsn(Opcodes.INSTANCEOF, ACN_objectIdClass);
                Label l5 = new Label();
                visitor.visitJumpInsn(Opcodes.IFNE, l5);
                visitor.visitTypeInsn(Opcodes.NEW, "java/lang/ClassCastException");
                visitor.visitInsn(Opcodes.DUP);
                visitor.visitLdcInsn("oid is not instanceof " + objectIdClass);
                visitor.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/ClassCastException", "<init>", "(Ljava/lang/String;)V");
                visitor.visitInsn(Opcodes.ATHROW);
                // XXXIdentity o = (XXXIdentity) oid;
                visitor.visitLabel(l5);
                visitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
                visitor.visitVarInsn(Opcodes.ALOAD, 2);
                visitor.visitTypeInsn(Opcodes.CHECKCAST, ACN_objectIdClass);
                visitor.visitVarInsn(Opcodes.ASTORE, 3);
                // fc.storeXXXField(1, o.getKey());
                Label l9 = new Label();
                visitor.visitLabel(l9);
                visitor.visitVarInsn(Opcodes.ALOAD, 1);
                EnhanceUtils.addBIPUSHToMethod(visitor, pkFieldNums[0]);
                AbstractMemberMetaData fmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(pkFieldNums[0]);
                Class primitiveType = ClassUtils.getPrimitiveTypeForType(fmd.getType());
                if (primitiveType != null) {
                    // The PK field is a primitive wrapper so create wrapper from getKey()
                    String ACN_fieldType = fmd.getTypeName().replace('.', '/');
                    String getKeyReturnDesc = Type.getDescriptor(primitiveType);
                    visitor.visitVarInsn(Opcodes.ALOAD, 3);
                    visitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, ACN_objectIdClass, "getKey", "()" + getKeyReturnDesc);
                    visitor.visitMethodInsn(Opcodes.INVOKESTATIC, ACN_fieldType, "valueOf", "(" + getKeyReturnDesc + ")L" + ACN_fieldType + ";");
                    visitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, getNamer().getObjectIdFieldConsumerAsmClassName(), "storeObjectField", "(I" + EnhanceUtils.CD_Object + ")V");
                } else {
                    // PK field isn't a primitive wrapper
                    visitor.visitVarInsn(Opcodes.ALOAD, 3);
                    visitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, ACN_objectIdClass, "getKey", "()" + getNamer().getTypeDescriptorForSingleFieldIdentityGetKey(objectIdClass));
                    visitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, getNamer().getObjectIdFieldConsumerAsmClassName(), "store" + getNamer().getTypeNameForUseWithSingleFieldIdentity(objectIdClass) + "Field", "(I" + getNamer().getTypeDescriptorForSingleFieldIdentityGetKey(objectIdClass) + ")V");
                }
                visitor.visitInsn(Opcodes.RETURN);
                Label endLabel = new Label();
                visitor.visitLabel(endLabel);
                visitor.visitLocalVariable("this", getClassEnhancer().getClassDescriptor(), null, startLabel, endLabel, 0);
                visitor.visitLocalVariable(argNames[0], getNamer().getObjectIdFieldConsumerDescriptor(), null, startLabel, endLabel, 1);
                visitor.visitLocalVariable(argNames[1], EnhanceUtils.CD_Object, null, startLabel, endLabel, 2);
                visitor.visitLocalVariable("o", getNamer().getSingleFieldIdentityDescriptor(objectIdClass), null, l9, endLabel, 3);
                visitor.visitMaxs(3, 4);
            } else {
                // User-provided app identity, and compound identity
                // Put try-catch around the field setting (for reflection cases)
                Label l0 = new Label();
                Label l1 = new Label();
                Label l2 = new Label();
                visitor.visitTryCatchBlock(l0, l1, l2, "java/lang/Exception");
                Label startLabel = new Label();
                visitor.visitLabel(startLabel);
                visitor.visitVarInsn(Opcodes.ALOAD, 1);
                Label l4 = new Label();
                visitor.visitJumpInsn(Opcodes.IFNONNULL, l4);
                visitor.visitTypeInsn(Opcodes.NEW, "java/lang/IllegalArgumentException");
                visitor.visitInsn(Opcodes.DUP);
                visitor.visitLdcInsn("ObjectIdFieldConsumer is null");
                visitor.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/IllegalArgumentException", "<init>", "(Ljava/lang/String;)V");
                visitor.visitInsn(Opcodes.ATHROW);
                visitor.visitLabel(l4);
                visitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
                visitor.visitVarInsn(Opcodes.ALOAD, 2);
                visitor.visitTypeInsn(Opcodes.INSTANCEOF, ACN_objectIdClass);
                Label l5 = new Label();
                visitor.visitJumpInsn(Opcodes.IFNE, l5);
                visitor.visitTypeInsn(Opcodes.NEW, "java/lang/ClassCastException");
                visitor.visitInsn(Opcodes.DUP);
                visitor.visitLdcInsn("oid is not instanceof " + objectIdClass);
                visitor.visitMethodInsn(Opcodes.INVOKESPECIAL, "java/lang/ClassCastException", "<init>", "(Ljava/lang/String;)V");
                visitor.visitInsn(Opcodes.ATHROW);
                visitor.visitLabel(l5);
                visitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
                visitor.visitVarInsn(Opcodes.ALOAD, 2);
                visitor.visitTypeInsn(Opcodes.CHECKCAST, ACN_objectIdClass);
                visitor.visitVarInsn(Opcodes.ASTORE, 3);
                visitor.visitLabel(l0);
                // Copy the PK members using the appropriate method for each field/property
                Label reflectionFieldStart = null;
                for (int i = 0; i < pkFieldNums.length; i++) {
                    AbstractMemberMetaData fmd = enhancer.getClassMetaData().getMetaDataForManagedMemberAtAbsolutePosition(pkFieldNums[i]);
                    String fieldTypeDesc = Type.getDescriptor(fmd.getType());
                    String typeMethodName = EnhanceUtils.getTypeNameForPersistableMethod(fmd.getType());
                    int pkFieldModifiers = ClassUtils.getModifiersForFieldOfClass(enhancer.getClassLoaderResolver(), objectIdClass, fmd.getName());
                    // Check if the PK field type is a PC (CompoundIdentity)
                    AbstractClassMetaData acmd = enhancer.getMetaDataManager().getMetaDataForClass(fmd.getType(), enhancer.getClassLoaderResolver());
                    if (acmd != null && acmd.getIdentityType() != IdentityType.NONDURABLE) {
                        // CompoundIdentity, this field of the PK is a PC
                        visitor.visitVarInsn(Opcodes.ALOAD, 1);
                        EnhanceUtils.addBIPUSHToMethod(visitor, fmd.getFieldId());
                        visitor.visitVarInsn(Opcodes.ALOAD, 0);
                        visitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, getClassEnhancer().getASMClassName(), getNamer().getGetExecutionContextMethodName(), "()L" + getNamer().getExecutionContextAsmClassName() + ";");
                        visitor.visitVarInsn(Opcodes.ALOAD, 3);
                        // TODO Cater for property, or private field cases
                        visitor.visitFieldInsn(Opcodes.GETFIELD, ACN_objectIdClass, fmd.getName(), "L" + acmd.getObjectidClass().replace('.', '/') + ";");
                        visitor.visitInsn(Opcodes.ICONST_0);
                        visitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, getNamer().getExecutionContextAsmClassName(), "findObject", "(Ljava/lang/Object;Z)Ljava/lang/Object;");
                        visitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, getNamer().getObjectIdFieldConsumerAsmClassName(), "storeObjectField", "(ILjava/lang/Object;)V");
                    } else {
                        // Standard application-identity
                        if (fmd instanceof PropertyMetaData) {
                            // Field in PK is property, hence use getXXX in PK
                            visitor.visitVarInsn(Opcodes.ALOAD, 1);
                            EnhanceUtils.addBIPUSHToMethod(visitor, fmd.getFieldId());
                            visitor.visitVarInsn(Opcodes.ALOAD, 3);
                            visitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, ACN_objectIdClass, ClassUtils.getJavaBeanGetterName(fmd.getName(), fmd.getTypeName().equals("boolean")), "()" + Type.getDescriptor(fmd.getType()));
                            visitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, getNamer().getObjectIdFieldConsumerAsmClassName(), "store" + typeMethodName + "Field", "(I" + EnhanceUtils.getTypeDescriptorForEnhanceMethod(fmd.getType()) + ")V");
                        } else if (Modifier.isPublic(pkFieldModifiers)) {
                            // Field in PK is public so access directly
                            visitor.visitVarInsn(Opcodes.ALOAD, 1);
                            EnhanceUtils.addBIPUSHToMethod(visitor, fmd.getFieldId());
                            visitor.visitVarInsn(Opcodes.ALOAD, 3);
                            visitor.visitFieldInsn(Opcodes.GETFIELD, ACN_objectIdClass, fmd.getName(), fieldTypeDesc);
                            visitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, getNamer().getObjectIdFieldConsumerAsmClassName(), "store" + typeMethodName + "Field", "(I" + EnhanceUtils.getTypeDescriptorForEnhanceMethod(fmd.getType()) + ")V");
                        } else {
                            // Field in PK is protected/private so use reflection, generating
                            // "Field field = o.getClass().getDeclaredField("pmIDFloat");"
                            // "field.setAccessible(true);"
                            // "fc.storeObjectField(1, field.get(o));"
                            visitor.visitVarInsn(Opcodes.ALOAD, 3);
                            visitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "getClass", "()Ljava/lang/Class;");
                            visitor.visitLdcInsn(fmd.getName());
                            visitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Class", "getDeclaredField", "(Ljava/lang/String;)Ljava/lang/reflect/Field;");
                            visitor.visitVarInsn(Opcodes.ASTORE, 4);
                            if (reflectionFieldStart == null) {
                                reflectionFieldStart = new Label();
                                visitor.visitLabel(reflectionFieldStart);
                            }
                            visitor.visitVarInsn(Opcodes.ALOAD, 4);
                            visitor.visitInsn(Opcodes.ICONST_1);
                            visitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Field", "setAccessible", "(Z)V");
                            visitor.visitVarInsn(Opcodes.ALOAD, 1);
                            EnhanceUtils.addBIPUSHToMethod(visitor, fmd.getFieldId());
                            visitor.visitVarInsn(Opcodes.ALOAD, 4);
                            visitor.visitVarInsn(Opcodes.ALOAD, 3);
                            if (fmd.getTypeName().equals("boolean")) {
                                visitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Field", "getBoolean", "(Ljava/lang/Object;)Z");
                            } else if (fmd.getTypeName().equals("byte")) {
                                visitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Field", "getByte", "(Ljava/lang/Object;)B");
                            } else if (fmd.getTypeName().equals("char")) {
                                visitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Field", "getChar", "(Ljava/lang/Object;)C");
                            } else if (fmd.getTypeName().equals("double")) {
                                visitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Field", "getDouble", "(Ljava/lang/Object;)D");
                            } else if (fmd.getTypeName().equals("float")) {
                                visitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Field", "getFloat", "(Ljava/lang/Object;)F");
                            } else if (fmd.getTypeName().equals("int")) {
                                visitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Field", "getInt", "(Ljava/lang/Object;)I");
                            } else if (fmd.getTypeName().equals("long")) {
                                visitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Field", "getLong", "(Ljava/lang/Object;)L");
                            } else if (fmd.getTypeName().equals("short")) {
                                visitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Field", "getShort", "(Ljava/lang/Object;)S");
                            } else if (fmd.getTypeName().equals("java.lang.String")) {
                                visitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Field", "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
                                visitor.visitTypeInsn(Opcodes.CHECKCAST, "java/lang/String");
                            } else {
                                visitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/reflect/Field", "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
                            }
                            visitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, getNamer().getObjectIdFieldConsumerAsmClassName(), "store" + typeMethodName + "Field", "(I" + EnhanceUtils.getTypeDescriptorForEnhanceMethod(fmd.getType()) + ")V");
                        }
                    }
                }
                // catch of the try-catch
                visitor.visitLabel(l1);
                Label l20 = new Label();
                visitor.visitJumpInsn(Opcodes.GOTO, l20);
                visitor.visitLabel(l2);
                visitor.visitFrame(Opcodes.F_FULL, 4, new Object[] { getClassEnhancer().getASMClassName(), getClassEnhancer().getNamer().getObjectIdFieldConsumerAsmClassName(), "java/lang/Object", ACN_objectIdClass }, 1, new Object[] { "java/lang/Exception" });
                visitor.visitVarInsn(Opcodes.ASTORE, 4);
                visitor.visitLabel(l20);
                visitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
                visitor.visitInsn(Opcodes.RETURN);
                Label endLabel = new Label();
                visitor.visitLabel(endLabel);
                visitor.visitLocalVariable("this", getClassEnhancer().getClassDescriptor(), null, startLabel, endLabel, 0);
                visitor.visitLocalVariable(argNames[0], getNamer().getObjectIdFieldConsumerDescriptor(), null, startLabel, endLabel, 1);
                visitor.visitLocalVariable(argNames[1], EnhanceUtils.CD_Object, null, startLabel, endLabel, 2);
                visitor.visitLocalVariable("o", "L" + ACN_objectIdClass + ";", null, l0, endLabel, 3);
                if (reflectionFieldStart != null) {
                    visitor.visitLocalVariable("field", "Ljava/lang/reflect/Field;", null, reflectionFieldStart, l2, 4);
                    visitor.visitMaxs(4, 5);
                } else {
                    visitor.visitMaxs(4, 4);
                }
            }
        }
    } else {
        // datastore/nondurable identity
        Label startLabel = new Label();
        visitor.visitLabel(startLabel);
        visitor.visitInsn(Opcodes.RETURN);
        Label endLabel = new Label();
        visitor.visitLabel(endLabel);
        visitor.visitLocalVariable("this", getClassEnhancer().getClassDescriptor(), null, startLabel, endLabel, 0);
        visitor.visitLocalVariable(argNames[0], "L" + getNamer().getObjectIdFieldConsumerAsmClassName() + ";", null, startLabel, endLabel, 1);
        visitor.visitLocalVariable(argNames[1], EnhanceUtils.CD_Object, null, startLabel, endLabel, 2);
        visitor.visitMaxs(0, 3);
    }
    visitor.visitEnd();
}
Also used : Label(org.datanucleus.enhancer.asm.Label) PropertyMetaData(org.datanucleus.metadata.PropertyMetaData) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData) ClassMetaData(org.datanucleus.metadata.ClassMetaData) AbstractClassMetaData(org.datanucleus.metadata.AbstractClassMetaData)

Example 87 with AbstractMemberMetaData

use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-core by datanucleus.

the class RelationshipManagerImpl method process.

/* (non-Javadoc)
     * @see org.datanucleus.state.RelationshipManager#process()
     */
public void process() {
    Iterator iter = fieldChanges.entrySet().iterator();
    while (iter.hasNext()) {
        Map.Entry<Integer, List<RelationChange>> entry = (Map.Entry) iter.next();
        int fieldNumber = entry.getKey().intValue();
        List<RelationChange> changes = entry.getValue();
        AbstractMemberMetaData mmd = ownerOP.getClassMetaData().getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber);
        ClassLoaderResolver clr = ec.getClassLoaderResolver();
        RelationType relationType = mmd.getRelationType(clr);
        if (relationType == RelationType.ONE_TO_ONE_BI) {
            // 1-1 bidirectional
            processOneToOneBidirectionalRelation(mmd, clr, ec, changes);
        } else if (relationType == RelationType.MANY_TO_ONE_BI) {
            // N-1 bidirectional
            processManyToOneBidirectionalRelation(mmd, clr, ec, changes);
        } else if (relationType == RelationType.ONE_TO_MANY_BI) {
            // 1-N bidirectional
            processOneToManyBidirectionalRelation(mmd, clr, ec, changes);
        } else if (relationType == RelationType.MANY_TO_MANY_BI) {
            // M-N bidirectional
            processManyToManyBidirectionalRelation(mmd, clr, ec, changes);
        }
    }
}
Also used : RelationType(org.datanucleus.metadata.RelationType) Iterator(java.util.Iterator) ClassLoaderResolver(org.datanucleus.ClassLoaderResolver) ArrayList(java.util.ArrayList) List(java.util.List) HashMap(java.util.HashMap) Map(java.util.Map) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 88 with AbstractMemberMetaData

use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-core by datanucleus.

the class RelationshipManagerImpl method processManyToOneBidirectionalRelation.

/**
 * Method to process all N-1 bidirectional fields.
 * Processes the case where we had an N-1 field set at this side previously to some value and now to
 * some other value.That is, this object was in some collection/map originally, and now should be in some
 * other collection/map. So in terms of an example this object "a" was in collection "b1.as" before and is
 * now in "b2.as". The following changes are likely to be necessary
 * <ul>
 * <li>b1.getAs().remove(a) - remove it from b1.as if still present</li>
 * <li>b2.getAs().add(a) - add it to b1.as if not present</li>
 * </ul>
 * @param mmd MetaData for the field
 * @param clr ClassLoader resolver
 * @param ec ExecutionContext
 * @param changes List of changes to the collection
 */
protected void processManyToOneBidirectionalRelation(AbstractMemberMetaData mmd, ClassLoaderResolver clr, ExecutionContext ec, List<RelationChange> changes) {
    for (RelationChange change : changes) {
        if (change.type == ChangeType.CHANGE_OBJECT) {
            Object oldValue = change.oldValue;
            // TODO Use change.value
            Object newValue = ownerOP.provideField(mmd.getAbsoluteFieldNumber());
            if (oldValue != null) {
                // Has been removed from a Collection/Map
                AbstractMemberMetaData relatedMmd = mmd.getRelatedMemberMetaDataForObject(clr, pc, oldValue);
                ObjectProvider oldOP = ec.findObjectProvider(oldValue);
                if (oldOP != null && relatedMmd != null && oldOP.getLoadedFields()[relatedMmd.getAbsoluteFieldNumber()]) {
                    if (oldOP.isFieldLoaded(relatedMmd.getAbsoluteFieldNumber())) {
                        Object oldContainerValue = oldOP.provideField(relatedMmd.getAbsoluteFieldNumber());
                        if (oldContainerValue instanceof Collection) {
                            Collection oldColl = (Collection) oldContainerValue;
                            if (oldColl.contains(pc)) {
                                if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
                                    NucleusLogger.PERSISTENCE.debug(Localiser.msg("013006", StringUtils.toJVMIDString(pc), mmd.getFullFieldName(), relatedMmd.getFullFieldName(), StringUtils.toJVMIDString(oldValue)));
                                }
                                if (oldColl instanceof SCOCollection) {
                                    // Avoid any cascade deletes that could have been fired by this action
                                    ((SCOCollection) oldColl).remove(pc, false);
                                } else {
                                    oldColl.remove(pc);
                                }
                            }
                        }
                    }
                } else {
                    if (oldOP != null) {
                        ec.removeObjectFromLevel2Cache(oldOP.getInternalObjectId());
                    }
                }
            }
            if (newValue != null) {
                // Add new value to the Collection
                AbstractMemberMetaData relatedMmd = mmd.getRelatedMemberMetaDataForObject(clr, pc, newValue);
                ObjectProvider newOP = ec.findObjectProvider(newValue);
                if (newOP != null && relatedMmd != null && newOP.getLoadedFields()[relatedMmd.getAbsoluteFieldNumber()]) {
                    Object newContainerValue = newOP.provideField(relatedMmd.getAbsoluteFieldNumber());
                    if (newContainerValue instanceof Collection) {
                        Collection newColl = (Collection) newContainerValue;
                        if (!newColl.contains(pc)) {
                            if (NucleusLogger.PERSISTENCE.isDebugEnabled()) {
                                NucleusLogger.PERSISTENCE.debug(Localiser.msg("013007", StringUtils.toJVMIDString(pc), mmd.getFullFieldName(), relatedMmd.getFullFieldName(), StringUtils.toJVMIDString(newValue)));
                            }
                            newColl.add(pc);
                        }
                    }
                } else {
                    // Relation field not loaded so evict it from the L2 cache to avoid loading old field values
                    ec.removeObjectFromLevel2Cache(ec.getApiAdapter().getIdForObject(newValue));
                }
            }
        }
    }
}
Also used : Collection(java.util.Collection) SCOCollection(org.datanucleus.store.types.SCOCollection) SCOCollection(org.datanucleus.store.types.SCOCollection) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 89 with AbstractMemberMetaData

use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-core by datanucleus.

the class RelationshipManagerImpl method relationRemove.

/* (non-Javadoc)
     * @see org.datanucleus.state.RelationshipManager#relationRemove(int, java.lang.Object)
     */
public void relationRemove(int fieldNumber, Object val) {
    if (ec.isManagingRelations()) {
        return;
    }
    AbstractMemberMetaData mmd = ownerOP.getClassMetaData().getMetaDataForManagedMemberAtAbsolutePosition(fieldNumber);
    RelationType relationType = mmd.getRelationType(ec.getClassLoaderResolver());
    if (relationType != RelationType.ONE_TO_MANY_BI && relationType != RelationType.MANY_TO_MANY_BI) {
        return;
    }
    Integer fieldKey = Integer.valueOf(fieldNumber);
    List<RelationChange> changeList = fieldChanges.get(fieldKey);
    if (changeList == null) {
        changeList = new ArrayList();
        fieldChanges.put(fieldKey, changeList);
    }
    ec.removeObjectFromLevel2Cache(ec.getApiAdapter().getIdForObject(val));
    changeList.add(new RelationChange(ChangeType.REMOVE_OBJECT, val));
}
Also used : RelationType(org.datanucleus.metadata.RelationType) ArrayList(java.util.ArrayList) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Example 90 with AbstractMemberMetaData

use of org.datanucleus.metadata.AbstractMemberMetaData in project datanucleus-core by datanucleus.

the class RelationshipManagerImpl method processManyToManyBidirectionalRelation.

/**
 * Method to process all M-N bidirectional fields.
 * @param mmd MetaData for the field
 * @param clr ClassLoader resolver
 * @param ec ExecutionContext
 * @param changes List of changes to the collection
 */
protected void processManyToManyBidirectionalRelation(AbstractMemberMetaData mmd, ClassLoaderResolver clr, ExecutionContext ec, List<RelationChange> changes) {
    for (RelationChange change : changes) {
        if (change.type != ChangeType.ADD_OBJECT && change.type != ChangeType.REMOVE_OBJECT) {
            continue;
        }
        ObjectProvider op = ec.findObjectProvider(change.value);
        if (op == null && ec.getApiAdapter().isDetached(change.value)) {
            // Provided value was detached, so get its attached equivalent
            Object attached = ec.getAttachedObjectForId(ec.getApiAdapter().getIdForObject(change.value));
            if (attached != null) {
                op = ec.findObjectProvider(attached);
            }
        }
        if (op != null) {
            if (change.type == ChangeType.ADD_OBJECT) {
                // make sure the element has the owner in its collection
                AbstractMemberMetaData relatedMmd = mmd.getRelatedMemberMetaData(clr)[0];
                ec.removeObjectFromLevel2Cache(op.getInternalObjectId());
                ec.removeObjectFromLevel2Cache(ownerOP.getInternalObjectId());
                if (ownerOP.isFieldLoaded(mmd.getAbsoluteFieldNumber()) && !ownerOP.getLifecycleState().isDeleted) {
                    Collection currentVal = (Collection) ownerOP.provideField(mmd.getAbsoluteFieldNumber());
                    if (currentVal != null && !currentVal.contains(op.getObject())) {
                        currentVal.add(op.getObject());
                    }
                }
                if (op.isFieldLoaded(relatedMmd.getAbsoluteFieldNumber())) {
                    Collection currentVal = (Collection) op.provideField(relatedMmd.getAbsoluteFieldNumber());
                    if (currentVal != null && !currentVal.contains(ownerOP.getObject())) {
                        currentVal.add(ownerOP.getObject());
                    }
                }
            } else if (change.type == ChangeType.REMOVE_OBJECT) {
                // make sure the element removes the owner from its collection
                AbstractMemberMetaData relatedMmd = mmd.getRelatedMemberMetaData(clr)[0];
                ec.removeObjectFromLevel2Cache(op.getInternalObjectId());
                ec.removeObjectFromLevel2Cache(ownerOP.getInternalObjectId());
                if (ownerOP.isFieldLoaded(mmd.getAbsoluteFieldNumber()) && !ownerOP.getLifecycleState().isDeleted) {
                    Collection currentVal = (Collection) ownerOP.provideField(mmd.getAbsoluteFieldNumber());
                    if (!op.getLifecycleState().isDeleted && currentVal != null && currentVal.contains(op.getObject())) {
                        currentVal.remove(op.getObject());
                    } else {
                        // element is deleted so can't call remove since it may try to read fields from it
                        // so just unload the collection in the owner forcing it to be reloaded from the DB
                        ownerOP.unloadField(mmd.getName());
                    }
                }
                if (op.isFieldLoaded(relatedMmd.getAbsoluteFieldNumber()) && !op.getLifecycleState().isDeleted) {
                    Collection currentVal = (Collection) op.provideField(relatedMmd.getAbsoluteFieldNumber());
                    if (currentVal != null && currentVal.contains(ownerOP.getObject())) {
                        currentVal.remove(ownerOP.getObject());
                    }
                }
            }
        }
    }
}
Also used : Collection(java.util.Collection) SCOCollection(org.datanucleus.store.types.SCOCollection) AbstractMemberMetaData(org.datanucleus.metadata.AbstractMemberMetaData)

Aggregations

AbstractMemberMetaData (org.datanucleus.metadata.AbstractMemberMetaData)267 AbstractClassMetaData (org.datanucleus.metadata.AbstractClassMetaData)89 ClassLoaderResolver (org.datanucleus.ClassLoaderResolver)84 JavaTypeMapping (org.datanucleus.store.rdbms.mapping.java.JavaTypeMapping)82 DatastoreClass (org.datanucleus.store.rdbms.table.DatastoreClass)59 ClassMetaData (org.datanucleus.metadata.ClassMetaData)55 NucleusUserException (org.datanucleus.exceptions.NucleusUserException)50 NucleusException (org.datanucleus.exceptions.NucleusException)41 MetaDataManager (org.datanucleus.metadata.MetaDataManager)40 RDBMSStoreManager (org.datanucleus.store.rdbms.RDBMSStoreManager)38 SQLExpression (org.datanucleus.store.rdbms.sql.expression.SQLExpression)35 RelationType (org.datanucleus.metadata.RelationType)33 NucleusContext (org.datanucleus.NucleusContext)32 PersistenceNucleusContextImpl (org.datanucleus.PersistenceNucleusContextImpl)32 JPAMetaDataManager (org.datanucleus.api.jpa.metadata.JPAMetaDataManager)29 SQLExpressionFactory (org.datanucleus.store.rdbms.sql.expression.SQLExpressionFactory)28 ColumnMetaData (org.datanucleus.metadata.ColumnMetaData)27 ExecutionContext (org.datanucleus.ExecutionContext)26 ObjectProvider (org.datanucleus.state.ObjectProvider)25 ArrayList (java.util.ArrayList)24