Search in sources :

Example 1 with ArcId

use of org.apache.cayenne.graph.ArcId in project cayenne by apache.

the class DataContext method registerNewObject.

/**
 * Registers a transient object with the context, recursively registering
 * all transient persistent objects attached to this object via
 * relationships.
 * <p>
 * <i>Note that since 3.0 this method takes Object as an argument instead of
 * a {@link DataObject}.</i>
 *
 * @param object
 *            new object that needs to be made persistent.
 */
@Override
public void registerNewObject(Object object) {
    if (object == null) {
        throw new NullPointerException("Can't register null object.");
    }
    ObjEntity entity = getEntityResolver().getObjEntity((Persistent) object);
    if (entity == null) {
        throw new IllegalArgumentException("Can't find ObjEntity for Persistent class: " + object.getClass().getName() + ", class is likely not mapped.");
    }
    final Persistent persistent = (Persistent) object;
    // sanity check - maybe already registered
    if (persistent.getObjectId() != null) {
        if (persistent.getObjectContext() == this) {
            // already registered, just ignore
            return;
        } else if (persistent.getObjectContext() != null) {
            throw new IllegalStateException("Persistent is already registered with another DataContext. " + "Try using 'localObjects()' instead.");
        }
    } else {
        persistent.setObjectId(ObjectId.of(entity.getName()));
    }
    ClassDescriptor descriptor = getEntityResolver().getClassDescriptor(entity.getName());
    if (descriptor == null) {
        throw new IllegalArgumentException("Invalid entity name: " + entity.getName());
    }
    injectInitialValue(object);
    // now we need to find all arc changes, inject missing value holders and
    // pull in
    // all transient connected objects
    descriptor.visitProperties(new PropertyVisitor() {

        public boolean visitToMany(ToManyProperty property) {
            property.injectValueHolder(persistent);
            if (!property.isFault(persistent)) {
                Object value = property.readProperty(persistent);
                @SuppressWarnings("unchecked") Collection<Map.Entry> collection = (value instanceof Map) ? ((Map) value).entrySet() : (Collection) value;
                for (Object target : collection) {
                    if (target instanceof Persistent) {
                        Persistent targetDO = (Persistent) target;
                        // make sure it is registered
                        registerNewObject(targetDO);
                        getObjectStore().arcCreated(persistent.getObjectId(), targetDO.getObjectId(), new ArcId(property));
                    }
                }
            }
            return true;
        }

        public boolean visitToOne(ToOneProperty property) {
            Object target = property.readPropertyDirectly(persistent);
            if (target instanceof Persistent) {
                Persistent targetDO = (Persistent) target;
                // make sure it is registered
                registerNewObject(targetDO);
                getObjectStore().arcCreated(persistent.getObjectId(), targetDO.getObjectId(), new ArcId(property));
            }
            return true;
        }

        public boolean visitAttribute(AttributeProperty property) {
            return true;
        }
    });
}
Also used : ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) ArcId(org.apache.cayenne.graph.ArcId) Persistent(org.apache.cayenne.Persistent) AttributeProperty(org.apache.cayenne.reflect.AttributeProperty) ToOneProperty(org.apache.cayenne.reflect.ToOneProperty) ObjEntity(org.apache.cayenne.map.ObjEntity) ToManyProperty(org.apache.cayenne.reflect.ToManyProperty) Collection(java.util.Collection) DataObject(org.apache.cayenne.DataObject) Map(java.util.Map) PropertyVisitor(org.apache.cayenne.reflect.PropertyVisitor)

Example 2 with ArcId

use of org.apache.cayenne.graph.ArcId in project cayenne by apache.

the class ObjectDiff method addDiff.

void addDiff(NodeDiff diff, ObjectStore parent) {
    boolean addDiff = true;
    if (diff instanceof ArcOperation) {
        ArcOperation arcDiff = (ArcOperation) diff;
        Object targetId = arcDiff.getTargetNodeId();
        ArcId arcId = arcDiff.getArcId();
        ArcProperty property = (ArcProperty) getClassDescriptor().getProperty(arcId.getForwardArc());
        if (property == null && arcId.getForwardArc().startsWith(ASTDbPath.DB_PREFIX)) {
            addPhantomFkDiff(arcDiff);
            addDiff = false;
        } else if (property instanceof ToManyProperty) {
            // record flattened op changes
            ObjRelationship relationship = property.getRelationship();
            if (relationship.isFlattened()) {
                if (flatIds == null) {
                    flatIds = new HashMap<>();
                }
                ArcOperation oldOp = flatIds.put(arcDiff, arcDiff);
                // "delete" cancels "create" and vice versa...
                if (oldOp != null && oldOp.isDelete() != arcDiff.isDelete()) {
                    addDiff = false;
                    flatIds.remove(arcDiff);
                    if (otherDiffs != null) {
                        otherDiffs.remove(oldOp);
                    }
                }
            } else if (property.getComplimentaryReverseArc() == null) {
                // register complimentary arc diff
                ArcId arc = arcId.getReverseId();
                // new ArcId(ASTDbPath.DB_PREFIX + property.getComplimentaryReverseDbRelationshipPath(), property.getName());
                ArcOperation complimentaryOp = new ArcOperation(targetId, arcDiff.getNodeId(), arc, arcDiff.isDelete());
                parent.registerDiff(targetId, complimentaryOp);
            }
        } else if (property instanceof ToOneProperty) {
            if (currentArcSnapshot == null) {
                currentArcSnapshot = new HashMap<>();
            }
            currentArcSnapshot.put(arcId.getForwardArc(), targetId);
        } else {
            String message = (property == null) ? "No property for arcId " + arcId : "Unrecognized property for arcId " + arcId + ": " + property;
            throw new CayenneRuntimeException(message);
        }
    }
    if (addDiff) {
        if (otherDiffs == null) {
            otherDiffs = new ArrayList<>(3);
        }
        otherDiffs.add(diff);
    }
}
Also used : ObjRelationship(org.apache.cayenne.map.ObjRelationship) ArcProperty(org.apache.cayenne.reflect.ArcProperty) ArcId(org.apache.cayenne.graph.ArcId) HashMap(java.util.HashMap) CayenneRuntimeException(org.apache.cayenne.CayenneRuntimeException) ToOneProperty(org.apache.cayenne.reflect.ToOneProperty) ToManyProperty(org.apache.cayenne.reflect.ToManyProperty)

Example 3 with ArcId

use of org.apache.cayenne.graph.ArcId in project cayenne by apache.

the class ObjectStore method postprocessAfterCommit.

/**
 * Internal unsynchronized method to process objects state after commit.
 *
 * @since 1.2
 */
public void postprocessAfterCommit(GraphDiff parentChanges) {
    // scan through changed objects, set persistence state to committed
    for (Object id : changes.keySet()) {
        Persistent object = objectMap.get(id);
        switch(object.getPersistenceState()) {
            case PersistenceState.DELETED:
                objectMap.remove(id);
                object.setObjectContext(null);
                object.setPersistenceState(PersistenceState.TRANSIENT);
                break;
            case PersistenceState.NEW:
            case PersistenceState.MODIFIED:
                object.setPersistenceState(PersistenceState.COMMITTED);
                break;
        }
    }
    // re-register changed object ids
    if (!parentChanges.isNoop()) {
        parentChanges.apply(new GraphChangeHandler() {

            @Override
            public void arcCreated(Object nodeId, Object targetNodeId, ArcId arcId) {
            }

            @Override
            public void arcDeleted(Object nodeId, Object targetNodeId, ArcId arcId) {
            }

            @Override
            public void nodeCreated(Object nodeId) {
            }

            @Override
            public void nodeIdChanged(Object nodeId, Object newId) {
                processIdChange(nodeId, newId);
            }

            @Override
            public void nodePropertyChanged(Object nodeId, String property, Object oldValue, Object newValue) {
            }

            @Override
            public void nodeRemoved(Object nodeId) {
            }
        });
    }
    // create new instance of changes map so that event listeners who stored the
    // original diff don't get affected
    this.changes = new HashMap<>();
}
Also used : ArcId(org.apache.cayenne.graph.ArcId) DataObject(org.apache.cayenne.DataObject) Persistent(org.apache.cayenne.Persistent) GraphChangeHandler(org.apache.cayenne.graph.GraphChangeHandler)

Example 4 with ArcId

use of org.apache.cayenne.graph.ArcId in project cayenne by apache.

the class NestedCayenneContextIT method testCommitChangesToParent.

@Test
public void testCommitChangesToParent() {
    clientContext.newObject(ClientMtTable1.class);
    clientContext.newObject(ClientMtTable1.class);
    clientContext.newObject(ClientMtTable1.class);
    clientContext.newObject(ClientMtTable1.class);
    clientContext.commitChanges();
    final ObjectContext child = runtime.newContext(clientContext);
    List<ClientMtTable1> objects = ObjectSelect.query(ClientMtTable1.class).select(child);
    assertEquals(4, objects.size());
    final ClientMtTable1 childNew = child.newObject(ClientMtTable1.class);
    childNew.setGlobalAttribute1("NNN");
    final ClientMtTable1 childModified = objects.get(0);
    childModified.setGlobalAttribute1("MMM");
    final ClientMtTable1 childCommitted = objects.get(1);
    final ClientMtTable1 childHollow = objects.get(3);
    child.invalidateObjects(childHollow);
    queryInterceptor.runWithQueriesBlocked(() -> {
        child.commitChangesToParent();
        // * all modified child objects must be in committed state now
        // * all modifications should be propagated to the parent
        // * no actual commit should occur.
        assertEquals(PersistenceState.COMMITTED, childNew.getPersistenceState());
        assertEquals(PersistenceState.COMMITTED, childModified.getPersistenceState());
        assertEquals(PersistenceState.COMMITTED, childCommitted.getPersistenceState());
        assertEquals(PersistenceState.HOLLOW, childHollow.getPersistenceState());
        ClientMtTable1 parentNew = (ClientMtTable1) clientContext.getGraphManager().getNode(childNew.getObjectId());
        final ClientMtTable1 parentModified = (ClientMtTable1) clientContext.getGraphManager().getNode(childModified.getObjectId());
        ClientMtTable1 parentCommitted = (ClientMtTable1) clientContext.getGraphManager().getNode(childCommitted.getObjectId());
        ClientMtTable1 parentHollow = (ClientMtTable1) clientContext.getGraphManager().getNode(childHollow.getObjectId());
        assertNotNull(parentNew);
        assertEquals(PersistenceState.NEW, parentNew.getPersistenceState());
        assertEquals("NNN", parentNew.getGlobalAttribute1());
        assertNotNull(parentModified);
        assertEquals(PersistenceState.MODIFIED, parentModified.getPersistenceState());
        assertEquals("MMM", parentModified.getGlobalAttribute1());
        assertNotNull(parentCommitted);
        assertEquals(PersistenceState.COMMITTED, parentCommitted.getPersistenceState());
        assertNotNull(parentHollow);
        // check that arc changes got recorded in the parent context
        GraphDiff diffs = clientContext.internalGraphManager().getDiffs();
        final int[] modifiedProperties = new int[1];
        diffs.apply(new GraphChangeHandler() {

            @Override
            public void arcCreated(Object nodeId, Object targetNodeId, ArcId arcId) {
            }

            @Override
            public void arcDeleted(Object nodeId, Object targetNodeId, ArcId arcId) {
            }

            @Override
            public void nodeCreated(Object nodeId) {
            }

            @Override
            public void nodeIdChanged(Object nodeId, Object newId) {
            }

            @Override
            public void nodePropertyChanged(Object nodeId, String property, Object oldValue, Object newValue) {
                if (nodeId.equals(parentModified.getObjectId())) {
                    modifiedProperties[0]++;
                }
            }

            @Override
            public void nodeRemoved(Object nodeId) {
            }
        });
        assertEquals(1, modifiedProperties[0]);
    });
}
Also used : ClientMtTable1(org.apache.cayenne.testdo.mt.ClientMtTable1) ArcId(org.apache.cayenne.graph.ArcId) GraphDiff(org.apache.cayenne.graph.GraphDiff) GraphChangeHandler(org.apache.cayenne.graph.GraphChangeHandler) Test(org.junit.Test)

Example 5 with ArcId

use of org.apache.cayenne.graph.ArcId in project cayenne by apache.

the class NestedCayenneContextIT method testNullifyToOne.

/**
 * A test case for CAY-698 bug.
 */
@Test
public void testNullifyToOne() {
    ClientMtTable1 a = clientContext.newObject(ClientMtTable1.class);
    ClientMtTable2 b = clientContext.newObject(ClientMtTable2.class);
    a.addToTable2Array(b);
    clientContext.commitChanges();
    ObjectContext child = runtime.newContext(clientContext);
    ObjectContext childPeer = runtime.newContext(clientContext);
    ClientMtTable2 childP1 = SelectById.query(ClientMtTable2.class, b.getObjectId()).selectOne(child);
    // trigger object creation in the peer nested DC
    Cayenne.objectForPK(childPeer, b.getObjectId());
    childP1.setTable1(null);
    queryInterceptor.runWithQueriesBlocked(() -> {
        child.commitChangesToParent();
        assertEquals(PersistenceState.COMMITTED, childP1.getPersistenceState());
        ClientMtTable2 parentP1 = (ClientMtTable2) clientContext.getGraphManager().getNode(childP1.getObjectId());
        assertNotNull(parentP1);
        assertEquals(PersistenceState.MODIFIED, parentP1.getPersistenceState());
        assertNull(parentP1.getTable1());
        // check that arc changes got recorded in the parent context
        GraphDiff diffs = clientContext.internalGraphManager().getDiffs();
        final int[] arcDiffs = new int[1];
        diffs.apply(new GraphChangeHandler() {

            @Override
            public void arcCreated(Object nodeId, Object targetNodeId, ArcId arcId) {
                arcDiffs[0]++;
            }

            @Override
            public void arcDeleted(Object nodeId, Object targetNodeId, ArcId arcId) {
                arcDiffs[0]--;
            }

            @Override
            public void nodeCreated(Object nodeId) {
            }

            @Override
            public void nodeIdChanged(Object nodeId, Object newId) {
            }

            @Override
            public void nodePropertyChanged(Object nodeId, String property, Object oldValue, Object newValue) {
            }

            @Override
            public void nodeRemoved(Object nodeId) {
            }
        });
        assertEquals(-2, arcDiffs[0]);
    });
}
Also used : ClientMtTable1(org.apache.cayenne.testdo.mt.ClientMtTable1) ClientMtTable2(org.apache.cayenne.testdo.mt.ClientMtTable2) ArcId(org.apache.cayenne.graph.ArcId) GraphDiff(org.apache.cayenne.graph.GraphDiff) GraphChangeHandler(org.apache.cayenne.graph.GraphChangeHandler) Test(org.junit.Test)

Aggregations

ArcId (org.apache.cayenne.graph.ArcId)10 GraphChangeHandler (org.apache.cayenne.graph.GraphChangeHandler)5 ToManyProperty (org.apache.cayenne.reflect.ToManyProperty)5 ToOneProperty (org.apache.cayenne.reflect.ToOneProperty)5 GraphDiff (org.apache.cayenne.graph.GraphDiff)4 ArcProperty (org.apache.cayenne.reflect.ArcProperty)4 AttributeProperty (org.apache.cayenne.reflect.AttributeProperty)4 PropertyVisitor (org.apache.cayenne.reflect.PropertyVisitor)4 Test (org.junit.Test)4 ClientMtTable1 (org.apache.cayenne.testdo.mt.ClientMtTable1)3 DataObject (org.apache.cayenne.DataObject)2 Persistent (org.apache.cayenne.Persistent)2 ObjRelationship (org.apache.cayenne.map.ObjRelationship)2 ClassDescriptor (org.apache.cayenne.reflect.ClassDescriptor)2 ClientMtTable2 (org.apache.cayenne.testdo.mt.ClientMtTable2)2 Collection (java.util.Collection)1 HashMap (java.util.HashMap)1 Map (java.util.Map)1 CayenneRuntimeException (org.apache.cayenne.CayenneRuntimeException)1 ObjEntity (org.apache.cayenne.map.ObjEntity)1