use of org.apache.cayenne.Persistent in project cayenne by apache.
the class ObjectDiff method isNoop.
/**
* Checks whether at least a single property is modified.
*/
@Override
public boolean isNoop() {
// if we have no baseline to compare with, assume that there are changes
if (snapshot == null) {
return false;
}
if (flatIds != null && !flatIds.isEmpty()) {
return false;
}
if (phantomFks != null && !phantomFks.isEmpty()) {
return false;
}
int state = object.getPersistenceState();
if (state == PersistenceState.NEW || state == PersistenceState.DELETED) {
return false;
}
// check phantom mods
final boolean[] modFound = new boolean[1];
getClassDescriptor().visitProperties(new PropertyVisitor() {
@Override
public boolean visitAttribute(AttributeProperty property) {
Object oldValue = snapshot.get(property.getName());
Object newValue = property.readProperty(object);
if (!Util.nullSafeEquals(oldValue, newValue)) {
modFound[0] = true;
}
return !modFound[0];
}
@Override
public boolean visitToMany(ToManyProperty property) {
// flattened changes
return true;
}
@Override
public boolean visitToOne(ToOneProperty property) {
if (arcSnapshot == null) {
return true;
}
Object newValue = property.readPropertyDirectly(object);
if (newValue instanceof Fault) {
return true;
}
Object oldValue = arcSnapshot.get(property.getName());
if (!Util.nullSafeEquals(oldValue, newValue != null ? ((Persistent) newValue).getObjectId() : null)) {
modFound[0] = true;
}
return !modFound[0];
}
});
return !modFound[0];
}
use of org.apache.cayenne.Persistent in project cayenne by apache.
the class ObjectResolver method objectFromDataRow.
Persistent objectFromDataRow(DataRow row, ObjectId anId, ClassDescriptor classDescriptor) {
// details
if (anId == null) {
return null;
}
// this will create a HOLLOW object if it is not registered yet
Persistent object = context.findOrCreateObject(anId);
// deal with object state
int state = object.getPersistenceState();
switch(state) {
case PersistenceState.COMMITTED:
case PersistenceState.MODIFIED:
case PersistenceState.DELETED:
// process the above only if refresh is requested...
if (refreshObjects) {
DataRowUtils.mergeObjectWithSnapshot(context, classDescriptor, object, row);
if (object instanceof DataObject) {
((DataObject) object).setSnapshotVersion(row.getVersion());
}
}
break;
case PersistenceState.HOLLOW:
if (!refreshObjects) {
DataRow cachedRow = cache.getCachedSnapshot(anId);
if (cachedRow != null) {
row = cachedRow;
}
}
DataRowUtils.mergeObjectWithSnapshot(context, classDescriptor, object, row);
if (object instanceof DataObject) {
((DataObject) object).setSnapshotVersion(row.getVersion());
}
break;
default:
break;
}
return object;
}
use of org.apache.cayenne.Persistent in project cayenne by apache.
the class ObjectStore method objectsRolledBack.
/**
* Reverts changes to all stored uncomitted objects.
*
* @since 1.1
*/
public synchronized void objectsRolledBack() {
Iterator<Persistent> it = getObjectIterator();
// collect candidates
while (it.hasNext()) {
Persistent object = it.next();
int objectState = object.getPersistenceState();
switch(objectState) {
case PersistenceState.NEW:
it.remove();
object.setObjectContext(null);
object.setObjectId(null);
object.setPersistenceState(PersistenceState.TRANSIENT);
break;
case PersistenceState.DELETED:
// rolling the object back will set the state to committed
case PersistenceState.MODIFIED:
// this will clean any modifications and defer refresh from snapshot
// till the next object accessor is called
object.setPersistenceState(PersistenceState.HOLLOW);
break;
default:
// Transient, committed and hollow need no handling
break;
}
}
// reset changes ... using new HashMap to allow event listeners to analyze the
// original changes map after the rollback
this.changes = new HashMap<>();
}
use of org.apache.cayenne.Persistent in project cayenne by apache.
the class ObjectStore method registerDiff.
/**
* Registers object change.
*
* @since 1.2
*/
synchronized ObjectDiff registerDiff(Object nodeId, NodeDiff diff) {
if (diff != null) {
diff.setDiffId(++currentDiffId);
}
ObjectDiff objectDiff = changes.get(nodeId);
if (objectDiff == null) {
Persistent object = objectMap.get(nodeId);
if (object == null) {
throw new CayenneRuntimeException("No object is registered in context with Id %s", nodeId);
}
if (object.getPersistenceState() == PersistenceState.COMMITTED) {
object.setPersistenceState(PersistenceState.MODIFIED);
// replacement yet, so we still need to handle them...
if (object instanceof DataObject) {
DataObject dataObject = (DataObject) object;
DataRow snapshot = getCachedSnapshot((ObjectId) nodeId);
if (snapshot != null && snapshot.getVersion() != dataObject.getSnapshotVersion()) {
DataContextDelegate delegate = context.nonNullDelegate();
if (delegate.shouldMergeChanges(dataObject, snapshot)) {
ClassDescriptor descriptor = context.getEntityResolver().getClassDescriptor(((ObjectId) nodeId).getEntityName());
DataRowUtils.forceMergeWithSnapshot(context, descriptor, dataObject, snapshot);
dataObject.setSnapshotVersion(snapshot.getVersion());
delegate.finishedMergeChanges(dataObject);
}
}
}
}
objectDiff = new ObjectDiff(object);
objectDiff.setDiffId(++currentDiffId);
changes.put(nodeId, objectDiff);
}
if (diff != null) {
objectDiff.addDiff(diff, this);
}
return objectDiff;
}
use of org.apache.cayenne.Persistent in project cayenne by apache.
the class DefaultSelectTranslator method appendOverriddenColumns.
/**
* If query contains explicit column list, use only them
*/
<T> List<ColumnDescriptor> appendOverriddenColumns(List<ColumnDescriptor> columns, SelectQuery<T> query) {
groupByColumns = new HashMap<>();
QualifierTranslator qualifierTranslator = adapter.getQualifierTranslator(this);
AccumulatingBindingListener bindingListener = new AccumulatingBindingListener();
final String[] joinTableAliasForProperty = { null };
// capture last alias for joined table, will use it to resolve object columns
joinListener = () -> joinTableAliasForProperty[0] = getCurrentAlias();
setAddBindingListener(bindingListener);
for (Property<?> property : query.getColumns()) {
joinTableAliasForProperty[0] = null;
int expressionType = property.getExpression().getType();
// forbid direct selection of toMany relationships columns
if (property.getType() != null && (expressionType == Expression.OBJ_PATH || expressionType == Expression.DB_PATH) && (Collection.class.isAssignableFrom(property.getType()) || Map.class.isAssignableFrom(property.getType()))) {
throw new CayenneRuntimeException("Can't directly select toMany relationship columns. " + "Either select it with aggregate functions like count() or with flat() function to select full related objects.");
}
// evaluate ObjPath with Persistent type as toOne relations and use it as full object
boolean objectProperty = expressionType == Expression.FULL_OBJECT || (property.getType() != null && expressionType == Expression.OBJ_PATH && Persistent.class.isAssignableFrom(property.getType()));
// Qualifier Translator in case of Object Columns have side effect -
// it will create required joins, that we catch with listener above.
// And we force created join alias for all columns of Object we select.
qualifierTranslator.setQualifier(property.getExpression());
qualifierTranslator.setForceJoinForRelations(objectProperty);
StringBuilder builder = qualifierTranslator.appendPart(new StringBuilder());
if (objectProperty) {
// If we want full object, use appendQueryColumns method, to fully process class descriptor
List<ColumnDescriptor> classColumns = new ArrayList<>();
ObjEntity entity = entityResolver.getObjEntity(property.getType());
if (getQueryMetadata().getPageSize() > 0) {
appendIdColumns(classColumns, entity);
} else {
ClassDescriptor classDescriptor = entityResolver.getClassDescriptor(entity.getName());
appendQueryColumns(classColumns, query, classDescriptor, joinTableAliasForProperty[0]);
}
for (ColumnDescriptor descriptor : classColumns) {
columns.add(descriptor);
groupByColumns.put(descriptor, Collections.<DbAttributeBinding>emptyList());
}
} else {
// This property will go as scalar value
String alias = property.getAlias();
if (alias != null) {
builder.append(" AS ").append(alias);
}
int type = getJdbcTypeForProperty(property);
ColumnDescriptor descriptor;
if (property.getType() != null) {
descriptor = new ColumnDescriptor(builder.toString(), type, property.getType().getCanonicalName());
} else {
descriptor = new ColumnDescriptor(builder.toString(), type);
}
descriptor.setDataRowKey(alias);
descriptor.setIsExpression(true);
columns.add(descriptor);
if (isAggregate(property)) {
haveAggregate = true;
} else {
groupByColumns.put(descriptor, bindingListener.getBindings());
}
bindingListener.reset();
}
}
setAddBindingListener(null);
qualifierTranslator.setForceJoinForRelations(false);
joinListener = null;
return columns;
}
Aggregations