use of org.apache.cayenne.reflect.ToManyProperty 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(new ObjectId(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);
Collection<Map.Entry> collection = (value instanceof Map) ? ((Map) value).entrySet() : (Collection) value;
Iterator<Map.Entry> it = collection.iterator();
while (it.hasNext()) {
Object target = it.next();
if (target instanceof Persistent) {
Persistent targetDO = (Persistent) target;
// make sure it is registered
registerNewObject(targetDO);
getObjectStore().arcCreated(persistent.getObjectId(), targetDO.getObjectId(), property.getName());
}
}
}
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(), property.getName());
}
return true;
}
public boolean visitAttribute(AttributeProperty property) {
return true;
}
});
}
use of org.apache.cayenne.reflect.ToManyProperty in project cayenne by apache.
the class DataRowUtils method refreshObjectWithSnapshot.
/**
* Replaces all object attribute values with snapshot values. Sets object state to
* COMMITTED, unless the snapshot is partial in which case the state is set to HOLLOW
*/
static void refreshObjectWithSnapshot(ClassDescriptor descriptor, final Persistent object, final DataRow snapshot, final boolean invalidateToManyRelationships) {
final boolean[] isPartialSnapshot = new boolean[1];
descriptor.visitProperties(new PropertyVisitor() {
public boolean visitAttribute(AttributeProperty property) {
ObjAttribute attr = property.getAttribute();
String dbAttrPath = attr.getDbAttributePath();
Object value = snapshot.get(dbAttrPath);
property.writePropertyDirectly(object, null, value);
// checking for the null value first
if (value == null && !snapshot.containsKey(dbAttrPath)) {
isPartialSnapshot[0] = true;
}
return true;
}
public boolean visitToMany(ToManyProperty property) {
// snapshot
if (invalidateToManyRelationships) {
property.invalidate(object);
}
return true;
}
public boolean visitToOne(ToOneProperty property) {
property.invalidate(object);
return true;
}
});
object.setPersistenceState(isPartialSnapshot[0] ? PersistenceState.HOLLOW : PersistenceState.COMMITTED);
}
use of org.apache.cayenne.reflect.ToManyProperty 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();
String arcId = arcDiff.getArcId().toString();
ArcProperty property = (ArcProperty) getClassDescriptor().getProperty(arcId);
if (property == null && arcId.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
String arc = ASTDbPath.DB_PREFIX + property.getComplimentaryReverseDbRelationshipPath();
ArcOperation complimentartyOp = new ArcOperation(targetId, arcDiff.getNodeId(), arc, arcDiff.isDelete());
parent.registerDiff(targetId, complimentartyOp);
}
} else if (property instanceof ToOneProperty) {
if (currentArcSnapshot == null) {
currentArcSnapshot = new HashMap<>();
}
currentArcSnapshot.put(arcId, 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);
}
}
use of org.apache.cayenne.reflect.ToManyProperty in project cayenne by apache.
the class PrefetchProcessorJointNode method buildRowMapping.
/**
* Configures row columns mapping for this node entity.
*/
private void buildRowMapping() {
final Map<String, ColumnDescriptor> targetSource = new TreeMap<>();
// build a DB path .. find parent node that terminates the joint group...
PrefetchTreeNode jointRoot = this;
while (jointRoot.getParent() != null && !jointRoot.isDisjointPrefetch() && !jointRoot.isDisjointByIdPrefetch()) {
jointRoot = jointRoot.getParent();
}
final String prefix;
if (jointRoot != this) {
Expression objectPath = ExpressionFactory.exp(getPath(jointRoot));
ASTPath translated = (ASTPath) ((PrefetchProcessorNode) jointRoot).getResolver().getEntity().translateToDbPath(objectPath);
// make sure we do not include "db:" prefix
prefix = translated.getOperand(0) + ".";
} else {
prefix = "";
}
if (getParent() != null && !getParent().isPhantom() && getIncoming() != null && !getIncoming().getRelationship().isFlattened()) {
DbRelationship r = getIncoming().getRelationship().getDbRelationships().get(0);
for (final DbJoin join : r.getJoins()) {
appendColumn(targetSource, join.getTargetName(), prefix + join.getTargetName());
}
}
ClassDescriptor descriptor = resolver.getDescriptor();
descriptor.visitAllProperties(new PropertyVisitor() {
public boolean visitAttribute(AttributeProperty property) {
String target = property.getAttribute().getDbAttributePath();
appendColumn(targetSource, target, prefix + target);
return true;
}
public boolean visitToMany(ToManyProperty property) {
return visitRelationship(property);
}
public boolean visitToOne(ToOneProperty property) {
return visitRelationship(property);
}
private boolean visitRelationship(ArcProperty arc) {
DbRelationship dbRel = arc.getRelationship().getDbRelationships().get(0);
for (DbAttribute attribute : dbRel.getSourceAttributes()) {
String target = attribute.getName();
appendColumn(targetSource, target, prefix + target);
}
return true;
}
});
// append id columns ... (some may have been appended already via relationships)
for (String pkName : descriptor.getEntity().getPrimaryKeyNames()) {
appendColumn(targetSource, pkName, prefix + pkName);
}
// append inheritance discriminator columns...
for (ObjAttribute column : descriptor.getDiscriminatorColumns()) {
String target = column.getDbAttributePath();
appendColumn(targetSource, target, prefix + target);
}
int size = targetSource.size();
this.rowCapacity = (int) Math.ceil(size / 0.75);
this.columns = new ColumnDescriptor[size];
targetSource.values().toArray(columns);
}
use of org.apache.cayenne.reflect.ToManyProperty in project cayenne by apache.
the class EJBQLIdentifierColumnsTranslator method visitIdentifier.
@Override
public boolean visitIdentifier(EJBQLExpression expression) {
Map<String, String> xfields = null;
if (context.isAppendingResultColumns()) {
xfields = context.nextEntityResult().getFields();
}
// assign whatever we have to a final ivar so that it can be accessed
// within
// the inner class
final Map<String, String> fields = xfields;
final String idVar = expression.getText();
// append all table columns ... the trick is to follow the algorithm for
// describing the fields in the expression compiler, so that we could
// assign
// columns labels from FieldResults in the order we encounter them
// here...
// TODO: andrus 2008/02/17 - this is a bit of a hack, think of a better
// solution
ClassDescriptor descriptor = context.getEntityDescriptor(idVar);
PropertyVisitor visitor = new PropertyVisitor() {
public boolean visitAttribute(AttributeProperty property) {
ObjAttribute oa = property.getAttribute();
Iterator<?> dbPathIterator = oa.getDbPathIterator();
EJBQLJoinAppender joinAppender = null;
String marker = null;
EJBQLTableId lhsId = new EJBQLTableId(idVar);
while (dbPathIterator.hasNext()) {
Object pathPart = dbPathIterator.next();
if (pathPart == null) {
throw new CayenneRuntimeException("ObjAttribute has no component: %s", oa.getName());
} else if (pathPart instanceof DbRelationship) {
if (marker == null) {
marker = EJBQLJoinAppender.makeJoinTailMarker(idVar);
joinAppender = context.getTranslatorFactory().getJoinAppender(context);
}
DbRelationship dr = (DbRelationship) pathPart;
EJBQLTableId rhsId = new EJBQLTableId(lhsId, dr.getName());
joinAppender.appendOuterJoin(marker, lhsId, rhsId);
lhsId = rhsId;
} else if (pathPart instanceof DbAttribute) {
appendColumn(idVar, oa, (DbAttribute) pathPart, fields, oa.getType());
}
}
return true;
}
public boolean visitToMany(ToManyProperty property) {
visitRelationship(property);
return true;
}
public boolean visitToOne(ToOneProperty property) {
visitRelationship(property);
return true;
}
private void visitRelationship(ArcProperty property) {
ObjRelationship rel = property.getRelationship();
DbRelationship dbRel = rel.getDbRelationships().get(0);
for (DbJoin join : dbRel.getJoins()) {
DbAttribute src = join.getSource();
appendColumn(idVar, null, src, fields);
}
}
};
// EJBQL queries are polymorphic by definition - there is no distinction
// between
// inheritance/no-inheritance fetch
descriptor.visitAllProperties(visitor);
// append id columns ... (some may have been appended already via
// relationships)
DbEntity table = descriptor.getEntity().getDbEntity();
for (DbAttribute pk : table.getPrimaryKeys()) {
appendColumn(idVar, null, pk, fields);
}
// append inheritance discriminator columns...
for (ObjAttribute column : descriptor.getDiscriminatorColumns()) {
appendColumn(idVar, column, column.getDbAttribute(), fields);
}
addPrefetchedColumnsIfAny(idVar);
return false;
}
Aggregations