Search in sources :

Example 11 with CayenneMapEntry

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;
}
Also used : ObjRelationship(org.apache.cayenne.map.ObjRelationship) ObjAttribute(org.apache.cayenne.map.ObjAttribute) ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) ASTDbPath(org.apache.cayenne.exp.parser.ASTDbPath) DbAttribute(org.apache.cayenne.map.DbAttribute) CayenneRuntimeException(org.apache.cayenne.CayenneRuntimeException) EntityResult(org.apache.cayenne.map.EntityResult) AttributeProperty(org.apache.cayenne.reflect.AttributeProperty) ToOneProperty(org.apache.cayenne.reflect.ToOneProperty) CayenneMapEntry(org.apache.cayenne.util.CayenneMapEntry) ObjEntity(org.apache.cayenne.map.ObjEntity) ToManyProperty(org.apache.cayenne.reflect.ToManyProperty) DbEntity(org.apache.cayenne.map.DbEntity) Expression(org.apache.cayenne.exp.Expression) DbRelationship(org.apache.cayenne.map.DbRelationship) DbJoin(org.apache.cayenne.map.DbJoin) PropertyVisitor(org.apache.cayenne.reflect.PropertyVisitor) HashSet(java.util.HashSet)

Example 12 with CayenneMapEntry

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;
}
Also used : CayenneMapEntry(org.apache.cayenne.util.CayenneMapEntry) ObjRelationship(org.apache.cayenne.map.ObjRelationship) Expression(org.apache.cayenne.exp.Expression) CayenneRuntimeException(org.apache.cayenne.CayenneRuntimeException)

Example 13 with CayenneMapEntry

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);
}
Also used : CayenneMapEntry(org.apache.cayenne.util.CayenneMapEntry) DbEntity(org.apache.cayenne.map.DbEntity) DbRelationship(org.apache.cayenne.map.DbRelationship) LinkedList(java.util.LinkedList)

Example 14 with CayenneMapEntry

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;
}
Also used : CayenneMapEntry(org.apache.cayenne.util.CayenneMapEntry)

Example 15 with CayenneMapEntry

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);
}
Also used : CayenneMapEntry(org.apache.cayenne.util.CayenneMapEntry) Expression(org.apache.cayenne.exp.Expression) Test(org.junit.Test)

Aggregations

CayenneMapEntry (org.apache.cayenne.util.CayenneMapEntry)19 DbEntity (org.apache.cayenne.map.DbEntity)6 DbRelationship (org.apache.cayenne.map.DbRelationship)6 ObjEntity (org.apache.cayenne.map.ObjEntity)6 Expression (org.apache.cayenne.exp.Expression)5 DbAttribute (org.apache.cayenne.map.DbAttribute)5 CayenneRuntimeException (org.apache.cayenne.CayenneRuntimeException)4 ASTDbPath (org.apache.cayenne.exp.parser.ASTDbPath)3 Entity (org.apache.cayenne.map.Entity)3 ObjAttribute (org.apache.cayenne.map.ObjAttribute)3 ObjRelationship (org.apache.cayenne.map.ObjRelationship)3 HashSet (java.util.HashSet)2 ExpressionException (org.apache.cayenne.exp.ExpressionException)2 DbJoin (org.apache.cayenne.map.DbJoin)2 AttributeProperty (org.apache.cayenne.reflect.AttributeProperty)2 ClassDescriptor (org.apache.cayenne.reflect.ClassDescriptor)2 PropertyVisitor (org.apache.cayenne.reflect.PropertyVisitor)2 ToManyProperty (org.apache.cayenne.reflect.ToManyProperty)2 ToOneProperty (org.apache.cayenne.reflect.ToOneProperty)2 Test (org.junit.Test)2