/** * Returns an unmodifiable Map of persistent id values, essentially a * primary key map. For temporary id returns replacement id, if it was * already created. Otherwise returns an empty map. */ public Map<String, Object> getIdSnapshot() { if (isTemporary()) { return (replacementIdMap == null) ? Collections.<String, Object>emptyMap() : Collections.unmodifiableMap(replacementIdMap); } if (singleKey != null) { return Collections.singletonMap(singleKey, singleValue); } return objectIdKeys != null ? Collections.unmodifiableMap(objectIdKeys) : Collections.<String, Object>emptyMap(); }
/** * Returns an unmodifiable Map of persistent id values, essentailly a primary key map. * For temporary id returns replacement id, if it was already created. Otherwise * returns an empty map. */ public Map getIdSnapshot() { if (isTemporary()) { return (replacementIdMap == null) ? Collections.EMPTY_MAP : Collections .unmodifiableMap(replacementIdMap); } if(singleKey != null) { return Collections.singletonMap(singleKey, singleValue); } return objectIdKeys != null ? Collections.unmodifiableMap(objectIdKeys) : Collections.EMPTY_MAP; }
@Override public Object value(Object root, String name) { ObjectId id = ((Persistent) root).getObjectId(); if (id.isTemporary()) { // for now supporting only permanent IDs throw new IllegalArgumentException("Can't read from temporary ObjectId: " + id); } return id.getIdSnapshot().get(name); }
public Object getValue(Object object) throws PropertyException { if (object instanceof Persistent) { ObjectId id = ((Persistent) object).getObjectId(); if (id.isTemporary()) { return id; } Map<?, ?> map = id.getIdSnapshot(); if (map.size() == 1) { Map.Entry<?, ?> pkEntry = map.entrySet().iterator().next(); return pkEntry.getValue(); } return id; } else { throw new IllegalArgumentException("Object must be Persistent: " + object); } }
private static void checkObjectId(ObjectId id) { if (id.isTemporary() && !id.isReplacementIdAttached()) { throw new CayenneRuntimeException("Can't build a query for temporary id: %s", id); } }
/** * @since 4.0 */ @Override public void appendAsEJBQL(List<Object> parameterAccumulator, Appendable out, String rootId) throws IOException { // TODO: see CAY-1111 // Persistent processing is a hack for a rather special case of a single // column PK // object.. full implementation pending... // // cay1796 : change check for Persistent object by check for ObjectId Object scalar = value; if(scalar instanceof ObjectId) { ObjectId temp = (ObjectId)value; if (!temp.isTemporary() && temp.getIdSnapshot().size() == 1) { scalar = temp.getIdSnapshot().values().iterator().next(); } } SimpleNode.encodeScalarAsEJBQL(parameterAccumulator, out, scalar); }
/** * @since 1.2 */ public void setObjectId(ObjectId id) { if (id == null) { throw new CayenneRuntimeException( "Null ObjectId, probably an attempt to use TRANSIENT object as a query parameter."); } else if (id.isTemporary()) { throw new CayenneRuntimeException( "Temporary id, probably an attempt to use NEW object as a query parameter."); } else { values = id.getIdSnapshot(); } }
/** * Returns a consistent String representation of the ObjectId */ public String toStringId(ObjectId id) { // deal with temp that have attached replacement ID as permanent IDs... // AuditableFilter, etc. all rely on the ability to find the temp object // after the transaction end // TODO: support encoding format for temp+replacement if (id.isTemporary() && !id.isReplacementIdAttached()) { return toTempIdString(id); } else { return toPermIdString(id); } }
/** * @since 1.2 */ public void setObjectId(ObjectId id) { if (id == null) { throw new CayenneRuntimeException( "Null ObjectId, probably an attempt to use TRANSIENT object as a query parameter."); } else if (id.isTemporary()) { throw new CayenneRuntimeException( "Temporary id, probably an attempt to use NEW object as a query parameter."); } else { values = id.getIdSnapshot(); } }
@Override public void arcDeleted(Object nodeId, Object targetNodeId, Object arcId) { ObjEntity entity = resolver.getObjEntity(((ObjectId) nodeId).getEntityName()); ObjRelationship relationship = entity.getRelationship(arcId.toString()); if (relationship.isSourceIndependentFromTargetChange()) { // do not record temporary id mods... ObjectId nodeObjectId = (ObjectId) nodeId; if (!nodeObjectId.isTemporary()) { indirectModifications.add(nodeObjectId); } if (relationship.isFlattened()) { if (relationship.isReadOnly()) { throw new CayenneRuntimeException("Cannot unset the read-only flattened relationship %s" , relationship.getName()); } // Register this combination (so we can remove it later if an insert occurs before commit) FlattenedArcKey key = new FlattenedArcKey((ObjectId) nodeId, (ObjectId) targetNodeId, relationship); // If this combination has already been inserted, simply "uninsert" it also do not delete it twice if (!flattenedInserts.remove(key)) { flattenedDeletes.add(key); } } } }
public void arcCreated(Object nodeId, Object targetNodeId, Object arcId) { ObjEntity entity = resolver.getObjEntity(((ObjectId) nodeId).getEntityName()); ObjRelationship relationship = (ObjRelationship) entity.getRelationship(arcId .toString()); if (relationship.isSourceIndependentFromTargetChange()) { if (!((ObjectId) nodeId).isTemporary()) { indirectModifications.add(nodeId); } if (relationship.isFlattened()) { if (relationship.isReadOnly()) { throw new CayenneRuntimeException( "Cannot set the read-only flattened relationship " + relationship.getName()); } // Register this combination (so we can remove it later if an insert // occurs before commit) FlattenedArcKey key = new FlattenedArcKey( (ObjectId) nodeId, (ObjectId) targetNodeId, relationship); // If this combination has already been deleted, simply undelete it. if (!flattenedDeletes.remove(key)) { flattenedInserts.add(key); } } } }
@Override public void arcCreated(Object nodeId, Object targetNodeId, Object arcId) { ObjEntity entity = resolver.getObjEntity(((ObjectId) nodeId).getEntityName()); ObjRelationship relationship = entity.getRelationship(arcId.toString()); if (relationship.isSourceIndependentFromTargetChange()) { ObjectId nodeObjectId = (ObjectId) nodeId; if (!nodeObjectId.isTemporary()) { indirectModifications.add(nodeObjectId); } if (relationship.isFlattened()) { if (relationship.isReadOnly()) { throw new CayenneRuntimeException("Cannot set the read-only flattened relationship '%s' in ObjEntity '%s'." , relationship.getName(), relationship.getSourceEntity().getName()); } // Register this combination (so we can remove it later if an insert occurs before commit) FlattenedArcKey key = new FlattenedArcKey((ObjectId) nodeId, (ObjectId) targetNodeId, relationship); // If this combination has already been deleted, simply undelete it. if (!flattenedDeletes.remove(key)) { flattenedInserts.add(key); } } } }
protected Object findReflexiveMaster(Persistent object, ObjRelationship toOneRel, String targetEntityName) { DbRelationship finalRel = toOneRel.getDbRelationships().get(0); ObjectContext context = object.getObjectContext(); // find committed snapshot - so we can't fetch from the context as it // will return // dirty snapshot; must go down the stack instead // how do we handle this for NEW objects correctly? For now bail from // the method if (object.getObjectId().isTemporary()) { return null; } ObjectIdQuery query = new ObjectIdQuery(object.getObjectId(), true, ObjectIdQuery.CACHE); QueryResponse response = context.getChannel().onQuery(null, query); List<?> result = response.firstList(); if (result == null || result.size() == 0) { return null; } DataRow snapshot = (DataRow) result.get(0); ObjectId id = snapshot.createTargetObjectId(targetEntityName, finalRel); // not using 'localObject', looking up in context instead, as within the // sorter // we only care about objects participating in transaction, so no need // to create // hollow objects return (id != null) ? context.getGraphManager().getNode(id) : null; }
@Override protected Query createReplacementQuery(EntityResolver resolver) { if (objectId == null) { throw new CayenneRuntimeException("Can't resolve query - objectId is null."); } if (objectId.isTemporary() && !objectId.isReplacementIdAttached()) { throw new CayenneRuntimeException("Can't build a query for temporary id: %s", objectId); } SelectQuery<Object> query = new SelectQuery<>(objectId.getEntityName(), ExpressionFactory .matchAllDbExp(objectId.getIdSnapshot(), Expression.EQUAL_TO)); // if we got to the point of fetch, always force refresh.... query.setFetchingDataRows(fetchingDataRows); return query; }
static Map extractObjectId(Persistent dataObject) { if (dataObject == null) { throw new IllegalArgumentException("Null DataObject"); } ObjectId id = dataObject.getObjectId(); if (!id.isTemporary()) { return id.getIdSnapshot(); } // replacement ID is more tricky... do some sanity check... if (id.isReplacementIdAttached()) { DbEntity entity = dataObject .getObjectContext() .getEntityResolver() .lookupDbEntity(dataObject); if (entity != null && entity.isFullReplacementIdAttached(id)) { return id.getReplacementIdMap(); } } throw new CayenneRuntimeException("Can't get primary key from temporary id."); }
@Override protected Query createReplacementQuery(EntityResolver resolver) { if (objectId.isTemporary() && !objectId.isReplacementIdAttached()) { throw new CayenneRuntimeException("Can't build a query for relationship '%s' for temporary id: %s" , relationshipName, objectId); } ObjRelationship relationship = getRelationship(resolver); // build executable select... Expression qualifier = ExpressionFactory.matchDbExp(relationship .getReverseDbRelationshipPath(), objectId); SelectQuery<Object> query = new SelectQuery<Object>( (ObjEntity) relationship.getTargetEntity(), qualifier); query.setStatementFetchSize(statementFetchSize); return query; }
static Map<String, Object> extractObjectId(Persistent dataObject) { if (dataObject == null) { throw new IllegalArgumentException("Null DataObject"); } ObjectId id = dataObject.getObjectId(); if (!id.isTemporary()) { return id.getIdSnapshot(); } // replacement ID is more tricky... do some sanity check... if (id.isReplacementIdAttached()) { ObjEntity objEntity = dataObject.getObjectContext().getEntityResolver().getObjEntity(dataObject); if (objEntity != null) { DbEntity entity = objEntity.getDbEntity(); if (entity != null && entity.isFullReplacementIdAttached(id)) { return id.getReplacementIdMap(); } } } throw new CayenneRuntimeException("Can't get primary key from temporary id."); }
protected Query createReplacementQuery(EntityResolver resolver) { if (objectId.isTemporary() && !objectId.isReplacementIdAttached()) { throw new CayenneRuntimeException("Can't build a query for relationship '" + relationshipName + "' for temporary id: " + objectId); } ObjRelationship relationship = getRelationship(resolver); // build executable select... Expression qualifier = ExpressionFactory.matchDbExp(relationship .getReverseDbRelationshipPath(), objectId); SelectQuery query = new SelectQuery( (ObjEntity) relationship.getTargetEntity(), qualifier); query.setRefreshingObjects(refreshing); return query; }
protected Query createReplacementQuery(EntityResolver resolver) { if (objectId == null) { throw new CayenneRuntimeException("Can't resolve query - objectId is null."); } if (objectId.isTemporary() && !objectId.isReplacementIdAttached()) { throw new CayenneRuntimeException("Can't build a query for temporary id: " + objectId); } SelectQuery query = new SelectQuery(objectId.getEntityName(), ExpressionFactory .matchAllDbExp(objectId.getIdSnapshot(), Expression.EQUAL_TO)); // if we got to the point of fetch, always force refresh.... query.setRefreshingObjects(true); query.setFetchingDataRows(fetchingDataRows); return query; }
/** * Checks if an object has its to-one relationship target modified in memory. */ static boolean isToOneTargetModified( ArcProperty property, Persistent object, ObjectDiff diff) { if (object.getPersistenceState() != PersistenceState.MODIFIED || diff == null) { return false; } if (property.isFault(object)) { return false; } Persistent toOneTarget = (Persistent) property.readPropertyDirectly(object); ObjectId currentId = (toOneTarget != null) ? toOneTarget.getObjectId() : null; // if ObjectId is temporary, target is definitely modified... // this would cover NEW objects (what are the other cases of temp id??) if (currentId != null && currentId.isTemporary()) { return true; } if (!diff.containsArcSnapshot(property.getName())) { return false; } ObjectId targetId = diff.getArcSnapshotValue(property.getName()); return !Util.nullSafeEquals(currentId, targetId); }