use of org.apache.cayenne.util.CayenneMapEntry 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.util.CayenneMapEntry in project cayenne by apache.
the class SelectQueryPrefetchRouterAction method startDisjointPrefetch.
public boolean startDisjointPrefetch(PrefetchTreeNode node) {
// don't do anything to root
if (node == query.getPrefetchTree()) {
return true;
}
String prefetchPath = node.getPath();
// find last relationship
Iterator<CayenneMapEntry> it = classDescriptor.getEntity().resolvePathComponents(prefetchPath);
ObjRelationship relationship = null;
while (it.hasNext()) {
relationship = (ObjRelationship) it.next();
}
if (relationship == null) {
throw new CayenneRuntimeException("Invalid prefetch '%s' for entity '%s'", prefetchPath, classDescriptor.getEntity().getName());
}
// chain query and entity qualifiers
Expression queryQualifier = query.getQualifier();
Expression entityQualifier = classDescriptor.getEntityInheritanceTree().qualifierForEntityAndSubclasses();
if (entityQualifier != null) {
queryQualifier = (queryQualifier != null) ? queryQualifier.andExp(entityQualifier) : entityQualifier;
}
// create and configure PrefetchSelectQuery
PrefetchSelectQuery prefetchQuery = new PrefetchSelectQuery(prefetchPath, relationship);
prefetchQuery.setStatementFetchSize(query.getStatementFetchSize());
prefetchQuery.setQualifier(classDescriptor.getEntity().translateToRelatedEntity(queryQualifier, prefetchPath));
if (relationship.isSourceIndependentFromTargetChange()) {
// setup extra result columns to be able to relate result rows to the parent
// result objects.
prefetchQuery.addResultPath("db:" + relationship.getReverseDbRelationshipPath());
}
// pass prefetch subtree to enable joint prefetches...
prefetchQuery.setPrefetchTree(node);
// route...
prefetchQuery.route(router, resolver, null);
return true;
}
use of org.apache.cayenne.util.CayenneMapEntry in project cayenne by apache.
the class ASTDbPath method toMap_AttchedObject_MultiStepPath.
private Map<?, ?> toMap_AttchedObject_MultiStepPath(ObjectContext context, Persistent persistent) {
Iterator<CayenneMapEntry> pathComponents = Cayenne.getObjEntity(persistent).getDbEntity().resolvePathComponents(this);
LinkedList<DbRelationship> reversedPathComponents = new LinkedList<>();
while (pathComponents.hasNext()) {
CayenneMapEntry component = pathComponents.next();
if (component instanceof DbRelationship) {
DbRelationship rel = (DbRelationship) component;
DbRelationship reverseRelationship = rel.getReverseRelationship();
if (reverseRelationship == null) {
reverseRelationship = rel.createReverseRelationship();
}
reversedPathComponents.addFirst(reverseRelationship);
} else {
// an attribute can only occur at the end of the path
break;
}
}
DbEntity finalEntity = reversedPathComponents.get(0).getSourceEntity();
StringBuilder reversedPathStr = new StringBuilder();
for (int i = 0; i < reversedPathComponents.size(); i++) {
reversedPathStr.append(reversedPathComponents.get(i).getName());
if (i < reversedPathComponents.size() - 1) {
reversedPathStr.append('.');
}
}
return ObjectSelect.dbQuery(finalEntity.getName()).where(ExpressionFactory.matchDbExp(reversedPathStr.toString(), persistent)).selectOne(context);
}
use of org.apache.cayenne.util.CayenneMapEntry in project cayenne by apache.
the class ASTPath method evaluateEntityNode.
/**
* Helper method to evaluate path expression with Cayenne Entity.
*/
protected CayenneMapEntry evaluateEntityNode(Entity entity) {
Iterator<CayenneMapEntry> path = entity.resolvePathComponents(this);
CayenneMapEntry next = null;
while (path.hasNext()) {
next = path.next();
}
return next;
}
use of org.apache.cayenne.util.CayenneMapEntry in project cayenne by apache.
the class EntityIT method testResolveObjPath1.
@Test
public void testResolveObjPath1() {
Expression pathExpr = ExpressionFactory.expressionOfType(Expression.OBJ_PATH);
pathExpr.setOperand(0, "galleryName");
ObjEntity galleryEnt = runtime.getDataDomain().getEntityResolver().getObjEntity("Gallery");
Iterator<CayenneMapEntry> it = galleryEnt.resolvePathComponents(pathExpr);
// iterator must contain a single ObjAttribute
assertNotNull(it);
assertTrue(it.hasNext());
ObjAttribute next = (ObjAttribute) it.next();
assertNotNull(next);
assertFalse(it.hasNext());
assertSame(galleryEnt.getAttribute("galleryName"), next);
}
Aggregations