Search in sources :

Example 6 with PrefetchTreeNode

use of org.apache.cayenne.query.PrefetchTreeNode in project cayenne by apache.

the class ObjectDetachOperation method detach.

/**
 * "Detaches" an object from its context by creating an unattached copy. The copy is
 * created using target descriptor of this operation that may be different from the
 * object descriptor passed to this method.
 */
public Object detach(Object object, ClassDescriptor descriptor, final PrefetchTreeNode prefetchTree) {
    if (!(object instanceof Persistent)) {
        throw new CayenneRuntimeException("Expected Persistent, got: %s", object);
    }
    final Persistent source = (Persistent) object;
    ObjectId id = source.getObjectId();
    // sanity check
    if (id == null) {
        throw new CayenneRuntimeException("Server returned an object without an id: %s", source);
    }
    Object seenTarget = seen.get(id);
    if (seenTarget != null) {
        return seenTarget;
    }
    descriptor = descriptor.getSubclassDescriptor(source.getClass());
    // presumably id's entity name should be of the right subclass.
    final ClassDescriptor targetDescriptor = targetResolver.getClassDescriptor(id.getEntityName());
    final Persistent target = (Persistent) targetDescriptor.createObject();
    target.setObjectId(id);
    seen.put(id, target);
    descriptor.visitProperties(new PropertyVisitor() {

        private void fillReverseRelationship(Object destinationTarget, ArcProperty property) {
            ArcProperty clientProperty = (ArcProperty) targetDescriptor.getProperty(property.getName());
            if (clientProperty != null) {
                ArcProperty clientReverse = clientProperty.getComplimentaryReverseArc();
                if (clientReverse instanceof ToOneProperty) {
                    clientReverse.writeProperty(destinationTarget, null, target);
                }
            }
        }

        public boolean visitToOne(ToOneProperty property) {
            if (prefetchTree != null) {
                PrefetchTreeNode child = prefetchTree.getNode(property.getName());
                if (child != null) {
                    Object destinationSource = property.readProperty(source);
                    Object destinationTarget = destinationSource != null ? detach(destinationSource, property.getTargetDescriptor(), child) : null;
                    if (destinationTarget != null) {
                        fillReverseRelationship(destinationTarget, property);
                    }
                    ToOneProperty targetProperty = (ToOneProperty) targetDescriptor.getProperty(property.getName());
                    Object oldTarget = targetProperty.isFault(target) ? null : targetProperty.readProperty(target);
                    targetProperty.writeProperty(target, oldTarget, destinationTarget);
                }
            }
            return true;
        }

        public boolean visitToMany(ToManyProperty property) {
            if (prefetchTree != null) {
                PrefetchTreeNode child = prefetchTree.getNode(property.getName());
                if (child != null) {
                    Object value = property.readProperty(source);
                    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 ? detach(destinationSource, property.getTargetDescriptor(), child) : null;
                            if (destinationTarget != null) {
                                fillReverseRelationship(destinationTarget, property);
                            }
                            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 ? detach(destinationSource, property.getTargetDescriptor(), child) : null;
                            if (destinationTarget != null) {
                                fillReverseRelationship(destinationTarget, property);
                            }
                            targetCollection.add(destinationTarget);
                        }
                        targetValue = targetCollection;
                    }
                    ToManyProperty targetProperty = (ToManyProperty) targetDescriptor.getProperty(property.getName());
                    targetProperty.writeProperty(target, null, targetValue);
                }
            }
            return true;
        }

        public boolean visitAttribute(AttributeProperty property) {
            PropertyDescriptor targetProperty = targetDescriptor.getProperty(property.getName());
            if (!property.getAttribute().isLazy()) {
                targetProperty.writeProperty(target, null, property.readProperty(source));
            } else {
                targetProperty.writeProperty(target, null, new AttributeFault(property));
            }
            return true;
        }
    });
    return target;
}
Also used : ObjectId(org.apache.cayenne.ObjectId) HashMap(java.util.HashMap) CayenneRuntimeException(org.apache.cayenne.CayenneRuntimeException) ArrayList(java.util.ArrayList) Persistent(org.apache.cayenne.Persistent) Entry(java.util.Map.Entry) AttributeFault(org.apache.cayenne.access.AttributeFault) PrefetchTreeNode(org.apache.cayenne.query.PrefetchTreeNode) Collection(java.util.Collection) Map(java.util.Map) HashMap(java.util.HashMap)

Example 7 with PrefetchTreeNode

use of org.apache.cayenne.query.PrefetchTreeNode 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();
            if (!property.getAttribute().isLazy()) {
                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);
}
Also used : ArcProperty(org.apache.cayenne.reflect.ArcProperty) ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) ObjAttribute(org.apache.cayenne.map.ObjAttribute) ColumnDescriptor(org.apache.cayenne.access.jdbc.ColumnDescriptor) DbAttribute(org.apache.cayenne.map.DbAttribute) TreeMap(java.util.TreeMap) AttributeProperty(org.apache.cayenne.reflect.AttributeProperty) ToOneProperty(org.apache.cayenne.reflect.ToOneProperty) ToManyProperty(org.apache.cayenne.reflect.ToManyProperty) Expression(org.apache.cayenne.exp.Expression) PrefetchTreeNode(org.apache.cayenne.query.PrefetchTreeNode) DbRelationship(org.apache.cayenne.map.DbRelationship) DbJoin(org.apache.cayenne.map.DbJoin) ASTPath(org.apache.cayenne.exp.parser.ASTPath) PropertyVisitor(org.apache.cayenne.reflect.PropertyVisitor)

Example 8 with PrefetchTreeNode

use of org.apache.cayenne.query.PrefetchTreeNode in project cayenne by apache.

the class SelectQueryDescriptor method encodeAsXML.

@Override
public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
    encoder.start("query").attribute("name", getName()).attribute("type", type);
    String rootString = null;
    String rootType = null;
    if (root instanceof String) {
        rootType = QueryDescriptor.OBJ_ENTITY_ROOT;
        rootString = root.toString();
    } else if (root instanceof ObjEntity) {
        rootType = QueryDescriptor.OBJ_ENTITY_ROOT;
        rootString = ((ObjEntity) root).getName();
    } else if (root instanceof DbEntity) {
        rootType = QueryDescriptor.DB_ENTITY_ROOT;
        rootString = ((DbEntity) root).getName();
    } else if (root instanceof Procedure) {
        rootType = QueryDescriptor.PROCEDURE_ROOT;
        rootString = ((Procedure) root).getName();
    } else if (root instanceof Class<?>) {
        rootType = QueryDescriptor.JAVA_CLASS_ROOT;
        rootString = ((Class<?>) root).getName();
    }
    if (rootType != null) {
        encoder.attribute("root", rootType).attribute("root-name", rootString);
    }
    // print properties
    encodeProperties(encoder);
    // encode qualifier
    if (qualifier != null) {
        encoder.start("qualifier").nested(qualifier, delegate).end();
    }
    // encode orderings
    encoder.nested(orderings, delegate);
    PrefetchTreeNode prefetchTree = new PrefetchTreeNode();
    for (String prefetchPath : prefetchesMap.keySet()) {
        PrefetchTreeNode node = prefetchTree.addPath(prefetchPath);
        node.setSemantics(prefetchesMap.get(prefetchPath));
        node.setPhantom(false);
    }
    encoder.nested(prefetchTree, delegate);
    delegate.visitQuery(this);
    encoder.end();
}
Also used : PrefetchTreeNode(org.apache.cayenne.query.PrefetchTreeNode)

Example 9 with PrefetchTreeNode

use of org.apache.cayenne.query.PrefetchTreeNode in project cayenne by apache.

the class SQLTemplateDescriptor method encodeAsXML.

@Override
public void encodeAsXML(XMLEncoder encoder, ConfigurationNodeVisitor delegate) {
    encoder.start("query").attribute("name", getName()).attribute("type", type);
    String rootString = null;
    String rootType = null;
    if (root instanceof String) {
        rootType = QueryDescriptor.OBJ_ENTITY_ROOT;
        rootString = root.toString();
    } else if (root instanceof ObjEntity) {
        rootType = QueryDescriptor.OBJ_ENTITY_ROOT;
        rootString = ((ObjEntity) root).getName();
    } else if (root instanceof DbEntity) {
        rootType = QueryDescriptor.DB_ENTITY_ROOT;
        rootString = ((DbEntity) root).getName();
    } else if (root instanceof Procedure) {
        rootType = QueryDescriptor.PROCEDURE_ROOT;
        rootString = ((Procedure) root).getName();
    } else if (root instanceof Class<?>) {
        rootType = QueryDescriptor.JAVA_CLASS_ROOT;
        rootString = ((Class<?>) root).getName();
    } else if (root instanceof DataMap) {
        rootType = QueryDescriptor.DATA_MAP_ROOT;
        rootString = ((DataMap) root).getName();
    }
    if (rootType != null) {
        encoder.attribute("root", rootType).attribute("root-name", rootString);
    }
    // print properties
    encodeProperties(encoder);
    // encode default SQL
    if (sql != null) {
        encoder.start("sql").cdata(sql, true).end();
    }
    // encode adapter SQL
    if (adapterSql != null && !adapterSql.isEmpty()) {
        // sorting entries by adapter name
        TreeSet<String> keys = new TreeSet<>(adapterSql.keySet());
        for (String key : keys) {
            String value = adapterSql.get(key);
            if (key != null && value != null) {
                String sql = value.trim();
                if (sql.length() > 0) {
                    encoder.start("sql").attribute("adapter-class", key).cdata(sql, true).end();
                }
            }
        }
    }
    PrefetchTreeNode prefetchTree = new PrefetchTreeNode();
    for (Map.Entry<String, Integer> entry : prefetchesMap.entrySet()) {
        PrefetchTreeNode node = prefetchTree.addPath(entry.getKey());
        node.setSemantics(entry.getValue());
        node.setPhantom(false);
    }
    encoder.nested(prefetchTree, delegate);
    delegate.visitQuery(this);
    encoder.end();
}
Also used : TreeSet(java.util.TreeSet) PrefetchTreeNode(org.apache.cayenne.query.PrefetchTreeNode) Map(java.util.Map) HashMap(java.util.HashMap)

Example 10 with PrefetchTreeNode

use of org.apache.cayenne.query.PrefetchTreeNode in project cayenne by apache.

the class PrefetchProcessorTreeBuilderIT method testBuildTreeNoPrefetches.

@Test
public void testBuildTreeNoPrefetches() {
    final ClassDescriptor descriptor = resolver.getClassDescriptor("Artist");
    List<DataRow> dataRows = new ArrayList<>();
    dataRows.add(new DataRow(4));
    dataRows.add(new DataRow(4));
    QueryMetadata metadata = new MockQueryMetadata() {

        @Override
        public ClassDescriptor getClassDescriptor() {
            return descriptor;
        }

        @Override
        public ObjEntity getObjEntity() {
            return descriptor.getEntity();
        }

        @Override
        public DbEntity getDbEntity() {
            return getObjEntity().getDbEntity();
        }

        @Override
        public DataMap getDataMap() {
            return getObjEntity().getDataMap();
        }

        @Override
        public boolean isRefreshingObjects() {
            return true;
        }

        @Override
        public boolean isResolvingInherited() {
            return true;
        }
    };
    PrefetchTreeNode tree = new PrefetchTreeNode();
    HierarchicalObjectResolver resolver = new HierarchicalObjectResolver(context, metadata);
    PrefetchProcessorTreeBuilder builder = new PrefetchProcessorTreeBuilder(resolver, dataRows, new HashMap<>());
    PrefetchProcessorNode processingTree = builder.buildTree(tree);
    assertTrue(processingTree.getChildren().isEmpty());
    assertFalse(processingTree.isPhantom());
    assertFalse(processingTree.isPartitionedByParent());
    assertTrue(processingTree.isDisjointPrefetch());
    assertSame(dataRows, processingTree.getDataRows());
    assertSame(descriptor.getEntity(), processingTree.getResolver().getEntity());
    assertNull(processingTree.getIncoming());
}
Also used : MockQueryMetadata(org.apache.cayenne.query.MockQueryMetadata) QueryMetadata(org.apache.cayenne.query.QueryMetadata) ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) MockQueryMetadata(org.apache.cayenne.query.MockQueryMetadata) PrefetchTreeNode(org.apache.cayenne.query.PrefetchTreeNode) ArrayList(java.util.ArrayList) DataRow(org.apache.cayenne.DataRow) Test(org.junit.Test)

Aggregations

PrefetchTreeNode (org.apache.cayenne.query.PrefetchTreeNode)12 ClassDescriptor (org.apache.cayenne.reflect.ClassDescriptor)7 ArrayList (java.util.ArrayList)4 HashMap (java.util.HashMap)4 CayenneRuntimeException (org.apache.cayenne.CayenneRuntimeException)4 Expression (org.apache.cayenne.exp.Expression)4 DbRelationship (org.apache.cayenne.map.DbRelationship)4 ObjEntity (org.apache.cayenne.map.ObjEntity)4 DbAttribute (org.apache.cayenne.map.DbAttribute)3 DbEntity (org.apache.cayenne.map.DbEntity)3 ObjRelationship (org.apache.cayenne.map.ObjRelationship)3 QueryMetadata (org.apache.cayenne.query.QueryMetadata)3 ArcProperty (org.apache.cayenne.reflect.ArcProperty)3 Map (java.util.Map)2 DataRow (org.apache.cayenne.DataRow)2 EJBQLExpression (org.apache.cayenne.ejbql.EJBQLExpression)2 ASTDbPath (org.apache.cayenne.exp.parser.ASTDbPath)2 DbJoin (org.apache.cayenne.map.DbJoin)2 ObjAttribute (org.apache.cayenne.map.ObjAttribute)2 MockQueryMetadata (org.apache.cayenne.query.MockQueryMetadata)2