use of org.apache.cayenne.reflect.PropertyVisitor in project cayenne by apache.
the class SelectQueryMetadata method buildEntityResultForColumn.
/**
* Collect metadata for column that will be unwrapped to full entity in the final SQL
* (possibly including joint prefetch).
* This information will be used to correctly create Persistent object back from raw result.
*
* This method is actually repeating logic of
* {@link org.apache.cayenne.access.translator.select.DefaultSelectTranslator#appendQueryColumns}.
* Here we don't care about intermediate joins and few other things so it's shorter.
* Logic of these methods should be unified and simplified, possibly to a single source of metadata,
* generated only once and used everywhere.
*
* @param query original query
* @param column full object column
* @param resolver entity resolver to get ObjEntity and ClassDescriptor
* @return Entity result
*/
private EntityResult buildEntityResultForColumn(SelectQuery<?> query, Property<?> column, EntityResolver resolver) {
final EntityResult result = new EntityResult(column.getType());
// Collecting visitor for ObjAttributes and toOne relationships
PropertyVisitor visitor = new PropertyVisitor() {
public boolean visitAttribute(AttributeProperty property) {
ObjAttribute oa = property.getAttribute();
Iterator<CayenneMapEntry> dbPathIterator = oa.getDbPathIterator();
while (dbPathIterator.hasNext()) {
CayenneMapEntry pathPart = dbPathIterator.next();
if (pathPart instanceof DbAttribute) {
result.addDbField(pathPart.getName(), pathPart.getName());
}
}
return true;
}
public boolean visitToMany(ToManyProperty property) {
return true;
}
public boolean visitToOne(ToOneProperty property) {
DbRelationship dbRel = property.getRelationship().getDbRelationships().get(0);
List<DbJoin> joins = dbRel.getJoins();
for (DbJoin join : joins) {
if (!join.getSource().isPrimaryKey()) {
result.addDbField(join.getSource().getName(), join.getSource().getName());
}
}
return true;
}
};
ObjEntity oe = resolver.getObjEntity(column.getType());
DbEntity table = oe.getDbEntity();
// Additionally collect PKs
for (DbAttribute dba : table.getPrimaryKeys()) {
result.addDbField(dba.getName(), dba.getName());
}
ClassDescriptor descriptor = resolver.getClassDescriptor(oe.getName());
descriptor.visitAllProperties(visitor);
// Collection columns for joint prefetch
if (query.getPrefetchTree() != null) {
for (PrefetchTreeNode prefetch : query.getPrefetchTree().adjacentJointNodes()) {
// for each prefetch add columns from the target entity
Expression prefetchExp = ExpressionFactory.exp(prefetch.getPath());
ASTDbPath dbPrefetch = (ASTDbPath) oe.translateToDbPath(prefetchExp);
DbRelationship r = findRelationByPath(table, dbPrefetch);
if (r == null) {
throw new CayenneRuntimeException("Invalid joint prefetch '%s' for entity: %s", prefetch, oe.getName());
}
// go via target OE to make sure that Java types are mapped correctly...
ObjRelationship targetRel = (ObjRelationship) prefetchExp.evaluate(oe);
ObjEntity targetEntity = targetRel.getTargetEntity();
prefetch.setEntityName(targetRel.getSourceEntity().getName());
String labelPrefix = dbPrefetch.getPath();
Set<String> seenNames = new HashSet<>();
for (ObjAttribute oa : targetEntity.getAttributes()) {
Iterator<CayenneMapEntry> dbPathIterator = oa.getDbPathIterator();
while (dbPathIterator.hasNext()) {
Object pathPart = dbPathIterator.next();
if (pathPart instanceof DbAttribute) {
DbAttribute attribute = (DbAttribute) pathPart;
if (seenNames.add(attribute.getName())) {
result.addDbField(labelPrefix + '.' + attribute.getName(), labelPrefix + '.' + attribute.getName());
}
}
}
}
// append remaining target attributes such as keys
DbEntity targetDbEntity = r.getTargetEntity();
for (DbAttribute attribute : targetDbEntity.getAttributes()) {
if (seenNames.add(attribute.getName())) {
result.addDbField(labelPrefix + '.' + attribute.getName(), labelPrefix + '.' + attribute.getName());
}
}
}
}
return result;
}
use of org.apache.cayenne.reflect.PropertyVisitor in project cayenne by apache.
the class DeepMergeOperation method merge.
private <T extends Persistent> T merge(final T peerInParentContext, ClassDescriptor descriptor, final Map<ObjectId, Persistent> seen) {
ObjectId id = peerInParentContext.getObjectId();
// sanity check
if (id == null) {
throw new CayenneRuntimeException("Server returned an object without an id: %s", peerInParentContext);
}
Persistent seenTarget = seen.get(id);
if (seenTarget != null) {
return (T) seenTarget;
}
final T target = shallowMergeOperation.merge(peerInParentContext);
seen.put(id, target);
descriptor = descriptor.getSubclassDescriptor(peerInParentContext.getClass());
descriptor.visitProperties(new PropertyVisitor() {
public boolean visitToOne(ToOneProperty property) {
if (!property.isFault(peerInParentContext)) {
Persistent destinationSource = (Persistent) property.readProperty(peerInParentContext);
Object destinationTarget = destinationSource != null ? merge(destinationSource, property.getTargetDescriptor(), seen) : null;
Object oldTarget = property.isFault(target) ? null : property.readProperty(target);
property.writePropertyDirectly(target, oldTarget, destinationTarget);
}
return true;
}
public boolean visitToMany(ToManyProperty property) {
if (!property.isFault(peerInParentContext)) {
Object value = property.readProperty(peerInParentContext);
Object targetValue;
if (property instanceof ToManyMapProperty) {
Map<?, ?> map = (Map) value;
Map targetMap = new HashMap();
for (Entry entry : map.entrySet()) {
Object destinationSource = entry.getValue();
Object destinationTarget = destinationSource != null ? merge((Persistent) destinationSource, property.getTargetDescriptor(), seen) : null;
targetMap.put(entry.getKey(), destinationTarget);
}
targetValue = targetMap;
} else {
Collection collection = (Collection) value;
Collection targetCollection = new ArrayList(collection.size());
for (Object destinationSource : collection) {
Object destinationTarget = destinationSource != null ? merge((Persistent) destinationSource, property.getTargetDescriptor(), seen) : null;
targetCollection.add(destinationTarget);
}
targetValue = targetCollection;
}
property.writePropertyDirectly(target, null, targetValue);
}
return true;
}
public boolean visitAttribute(AttributeProperty property) {
return true;
}
});
return target;
}
use of org.apache.cayenne.reflect.PropertyVisitor in project cayenne by apache.
the class Util method unsetReverse.
static void unsetReverse(final Persistent sourceObject, String propertyName, final Persistent targetObject) {
ArcProperty property = (ArcProperty) Cayenne.getClassDescriptor(sourceObject).getProperty(propertyName);
ArcProperty reverseArc = property.getComplimentaryReverseArc();
if (reverseArc != null) {
reverseArc.visit(new PropertyVisitor() {
public boolean visitToMany(ToManyProperty property) {
property.removeTargetDirectly(targetObject, sourceObject);
return false;
}
public boolean visitToOne(ToOneProperty property) {
property.setTarget(targetObject, null, false);
return false;
}
public boolean visitAttribute(AttributeProperty property) {
return false;
}
});
sourceObject.getObjectContext().getGraphManager().arcDeleted(targetObject.getObjectId(), sourceObject.getObjectId(), reverseArc.getName());
markAsDirty(targetObject);
}
}
use of org.apache.cayenne.reflect.PropertyVisitor in project cayenne by apache.
the class DataObjectDescriptorFactoryIT method testVisitProperties_IterationOrder.
@Test
public void testVisitProperties_IterationOrder() {
DataObjectDescriptorFactory factory = new DataObjectDescriptorFactory(resolver.getClassDescriptorMap(), new SingletonFaultFactory());
for (ObjEntity e : resolver.getObjEntities()) {
ClassDescriptor descriptor = factory.getDescriptor(e.getName());
final PropertyDescriptor[] lastProcessed = new PropertyDescriptor[1];
PropertyVisitor visitor = new PropertyVisitor() {
public boolean visitToOne(ToOneProperty property) {
assertPropertiesAreInOrder(lastProcessed[0], property);
lastProcessed[0] = property;
return true;
}
public boolean visitToMany(ToManyProperty property) {
assertPropertiesAreInOrder(lastProcessed[0], property);
lastProcessed[0] = property;
return true;
}
public boolean visitAttribute(AttributeProperty property) {
assertPropertiesAreInOrder(lastProcessed[0], property);
lastProcessed[0] = property;
return true;
}
};
descriptor.visitProperties(visitor);
}
}
use of org.apache.cayenne.reflect.PropertyVisitor in project cayenne by apache.
the class DataObjectDescriptorFactory_InheritanceMapsIT method testVisitProperties_IterationOrder.
@Test
public void testVisitProperties_IterationOrder() {
DataObjectDescriptorFactory factory = new DataObjectDescriptorFactory(resolver.getClassDescriptorMap(), new SingletonFaultFactory());
for (ObjEntity e : resolver.getObjEntities()) {
ClassDescriptor descriptor = factory.getDescriptor(e.getName());
final PropertyDescriptor[] lastProcessed = new PropertyDescriptor[1];
PropertyVisitor visitor = new PropertyVisitor() {
public boolean visitToOne(ToOneProperty property) {
DataObjectDescriptorFactoryIT.assertPropertiesAreInOrder(lastProcessed[0], property);
lastProcessed[0] = property;
return true;
}
public boolean visitToMany(ToManyProperty property) {
DataObjectDescriptorFactoryIT.assertPropertiesAreInOrder(lastProcessed[0], property);
lastProcessed[0] = property;
return true;
}
public boolean visitAttribute(AttributeProperty property) {
DataObjectDescriptorFactoryIT.assertPropertiesAreInOrder(lastProcessed[0], property);
lastProcessed[0] = property;
return true;
}
};
descriptor.visitProperties(visitor);
}
}
Aggregations