Search in sources :

Example 6 with PropertyDescriptor

use of org.apache.cayenne.reflect.PropertyDescriptor 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());
            targetProperty.writeProperty(target, null, property.readProperty(source));
            return true;
        }
    });
    return target;
}
Also used : ArcProperty(org.apache.cayenne.reflect.ArcProperty) ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) PropertyDescriptor(org.apache.cayenne.reflect.PropertyDescriptor) ObjectId(org.apache.cayenne.ObjectId) HashMap(java.util.HashMap) CayenneRuntimeException(org.apache.cayenne.CayenneRuntimeException) ArrayList(java.util.ArrayList) ToManyMapProperty(org.apache.cayenne.reflect.ToManyMapProperty) Persistent(org.apache.cayenne.Persistent) AttributeProperty(org.apache.cayenne.reflect.AttributeProperty) ToOneProperty(org.apache.cayenne.reflect.ToOneProperty) Entry(java.util.Map.Entry) ToManyProperty(org.apache.cayenne.reflect.ToManyProperty) PrefetchTreeNode(org.apache.cayenne.query.PrefetchTreeNode) Collection(java.util.Collection) HashMap(java.util.HashMap) Map(java.util.Map) PropertyVisitor(org.apache.cayenne.reflect.PropertyVisitor)

Example 7 with PropertyDescriptor

use of org.apache.cayenne.reflect.PropertyDescriptor in project cayenne by apache.

the class ChildDiffLoader method arcDeleted.

public void arcDeleted(Object nodeId, final Object targetNodeId, Object arcId) {
    final Persistent source = findObject(nodeId);
    // changing their relationships
    if (source == null) {
        return;
    }
    ClassDescriptor descriptor = context.getEntityResolver().getClassDescriptor(((ObjectId) nodeId).getEntityName());
    PropertyDescriptor property = descriptor.getProperty(arcId.toString());
    setExternalChange(Boolean.TRUE);
    try {
        property.visit(new PropertyVisitor() {

            public boolean visitAttribute(AttributeProperty property) {
                return false;
            }

            public boolean visitToMany(ToManyProperty property) {
                // connect reverse arc if the relationship is marked as
                // "runtime"
                ArcProperty reverseArc = property.getComplimentaryReverseArc();
                boolean autoConnectReverse = reverseArc != null && reverseArc.getRelationship().isRuntime();
                Persistent target = findObject(targetNodeId);
                if (target == null) {
                    // this is usually the case when a NEW object was
                    // deleted and then
                    // its
                    // relationships were manipulated; so try to locate the
                    // object in
                    // the
                    // collection ...
                    // the performance of this is rather dubious of
                    // course...
                    target = findObjectInCollection(targetNodeId, property.readProperty(source));
                }
                if (target == null) {
                // ignore?
                } else {
                    property.removeTarget(source, target, autoConnectReverse);
                }
                return false;
            }

            public boolean visitToOne(ToOneProperty property) {
                property.setTarget(source, null, false);
                return false;
            }
        });
    } finally {
        setExternalChange(Boolean.FALSE);
    }
}
Also used : ArcProperty(org.apache.cayenne.reflect.ArcProperty) ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) PropertyDescriptor(org.apache.cayenne.reflect.PropertyDescriptor) ToManyProperty(org.apache.cayenne.reflect.ToManyProperty) Persistent(org.apache.cayenne.Persistent) AttributeProperty(org.apache.cayenne.reflect.AttributeProperty) PropertyVisitor(org.apache.cayenne.reflect.PropertyVisitor) ToOneProperty(org.apache.cayenne.reflect.ToOneProperty)

Example 8 with PropertyDescriptor

use of org.apache.cayenne.reflect.PropertyDescriptor in project cayenne by apache.

the class ValueHolderDescriptorFactory method createToOneProperty.

@Override
protected void createToOneProperty(PersistentDescriptor descriptor, ObjRelationship relationship) {
    ClassDescriptor targetDescriptor = descriptorMap.getDescriptor(relationship.getTargetEntityName());
    String reverseName = relationship.getReverseRelationshipName();
    Accessor accessor = createAccessor(descriptor, relationship.getName(), ValueHolder.class);
    PropertyDescriptor property = new ValueHolderProperty(descriptor, targetDescriptor, accessor, reverseName);
    descriptor.addDeclaredProperty(property);
}
Also used : ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) PropertyDescriptor(org.apache.cayenne.reflect.PropertyDescriptor) Accessor(org.apache.cayenne.reflect.Accessor)

Example 9 with PropertyDescriptor

use of org.apache.cayenne.reflect.PropertyDescriptor in project cayenne by apache.

the class Compiler method compile.

CompiledExpression compile(String source, EJBQLExpression parsed) {
    parsed.visit(new CompilationVisitor());
    Map<EJBQLPath, Integer> pathsInSelect = new HashMap<>();
    for (int i = 0; i < parsed.getChildrenCount(); i++) {
        if (parsed.getChild(i) instanceof EJBQLSelectClause) {
            EJBQLExpression parsedTemp = parsed.getChild(i);
            boolean stop = false;
            while (parsedTemp.getChildrenCount() > 0 && !stop) {
                EJBQLExpression newParsedTemp = null;
                for (int j = 0; j < parsedTemp.getChildrenCount(); j++) {
                    if (parsedTemp.getChild(j) instanceof EJBQLSelectExpression) {
                        for (int k = 0; k < parsedTemp.getChild(j).getChildrenCount(); k++) {
                            if (parsedTemp.getChild(j).getChild(k) instanceof EJBQLPath) {
                                pathsInSelect.put((EJBQLPath) parsedTemp.getChild(j).getChild(k), j);
                            }
                        }
                    } else {
                        if (parsedTemp.getChild(j).getChildrenCount() == 0) {
                            stop = true;
                        } else {
                            newParsedTemp = parsedTemp.getChild(j);
                        }
                    }
                }
                if (!stop && newParsedTemp != null) {
                    parsedTemp = newParsedTemp;
                } else {
                    stop = true;
                }
            }
        }
    }
    // postprocess paths, now that all id vars are resolved
    if (paths != null) {
        for (EJBQLPath path : paths) {
            String id = normalizeIdPath(path.getId());
            ClassDescriptor descriptor = descriptorsById.get(id);
            if (descriptor == null) {
                throw new EJBQLException("Unmapped id variable: " + id);
            }
            StringBuilder buffer = new StringBuilder(id);
            ObjRelationship incoming = null;
            String pathRelationshipString = "";
            for (int i = 1; i < path.getChildrenCount(); i++) {
                String pathChunk = path.getChild(i).getText();
                if (pathChunk.endsWith(Entity.OUTER_JOIN_INDICATOR)) {
                    pathChunk = pathChunk.substring(0, pathChunk.length() - 1);
                }
                buffer.append('.').append(pathChunk);
                PropertyDescriptor property = descriptor.getProperty(pathChunk);
                if (property instanceof ArcProperty) {
                    incoming = ((ArcProperty) property).getRelationship();
                    descriptor = ((ArcProperty) property).getTargetDescriptor();
                    pathRelationshipString = buffer.substring(0, buffer.length());
                    descriptorsById.put(pathRelationshipString, descriptor);
                    incomingById.put(pathRelationshipString, incoming);
                }
            }
            if (pathsInSelect.size() > 0 && incoming != null && pathRelationshipString.length() > 0 && pathRelationshipString.equals(buffer.toString())) {
                EJBQLIdentifier ident = new EJBQLIdentifier(0);
                ident.text = pathRelationshipString;
                Integer integer = pathsInSelect.get(path);
                if (integer != null) {
                    resultComponents.remove(integer.intValue());
                    resultComponents.add(integer, ident);
                    rootId = pathRelationshipString;
                }
            }
        }
    }
    CompiledExpression compiled = new CompiledExpression();
    compiled.setExpression(parsed);
    compiled.setSource(source);
    compiled.setRootId(rootId);
    compiled.setDescriptorsById(descriptorsById);
    compiled.setIncomingById(incomingById);
    compiled.setPrefetchTree(prefetchTree);
    if (resultComponents != null) {
        SQLResult mapping = new SQLResult();
        for (int i = 0; i < resultComponents.size(); i++) {
            Object nextMapping = resultComponents.get(i);
            if (nextMapping instanceof String) {
                mapping.addColumnResult((String) nextMapping);
            } else if (nextMapping instanceof EJBQLExpression) {
                EntityResult compileEntityResult = compileEntityResult((EJBQLExpression) nextMapping, i);
                if (prefetchTree != null) {
                    for (PrefetchTreeNode prefetch : prefetchTree.getChildren()) {
                        if (((EJBQLExpression) nextMapping).getText().equals(prefetch.getEjbqlPathEntityId())) {
                            EJBQLIdentifier ident = new EJBQLIdentifier(0);
                            ident.text = prefetch.getEjbqlPathEntityId() + "." + prefetch.getPath();
                            compileEntityResult = compileEntityResultWithPrefetch(compileEntityResult, ident);
                        }
                    }
                }
                mapping.addEntityResult(compileEntityResult);
            }
        }
        compiled.setResult(mapping);
    }
    return compiled;
}
Also used : ObjRelationship(org.apache.cayenne.map.ObjRelationship) ArcProperty(org.apache.cayenne.reflect.ArcProperty) ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) PropertyDescriptor(org.apache.cayenne.reflect.PropertyDescriptor) HashMap(java.util.HashMap) EJBQLException(org.apache.cayenne.ejbql.EJBQLException) EntityResult(org.apache.cayenne.map.EntityResult) EJBQLCompiledExpression(org.apache.cayenne.ejbql.EJBQLCompiledExpression) SQLResult(org.apache.cayenne.map.SQLResult) PrefetchTreeNode(org.apache.cayenne.query.PrefetchTreeNode) EJBQLExpression(org.apache.cayenne.ejbql.EJBQLExpression)

Example 10 with PropertyDescriptor

use of org.apache.cayenne.reflect.PropertyDescriptor in project cayenne by apache.

the class ValueHolderDescriptorFactory method createToManyMapProperty.

@Override
protected void createToManyMapProperty(PersistentDescriptor descriptor, ObjRelationship relationship) {
    ClassDescriptor targetDescriptor = descriptorMap.getDescriptor(relationship.getTargetEntityName());
    String reverseName = relationship.getReverseRelationshipName();
    Accessor accessor = createAccessor(descriptor, relationship.getName(), Map.class);
    Accessor mapKeyAccessor = createMapKeyAccessor(relationship, targetDescriptor);
    PropertyDescriptor property = new ValueHolderMapProperty(descriptor, targetDescriptor, accessor, reverseName, mapKeyAccessor);
    descriptor.addDeclaredProperty(property);
}
Also used : ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) PropertyDescriptor(org.apache.cayenne.reflect.PropertyDescriptor) Accessor(org.apache.cayenne.reflect.Accessor)

Aggregations

PropertyDescriptor (org.apache.cayenne.reflect.PropertyDescriptor)16 ClassDescriptor (org.apache.cayenne.reflect.ClassDescriptor)14 AttributeProperty (org.apache.cayenne.reflect.AttributeProperty)9 PropertyVisitor (org.apache.cayenne.reflect.PropertyVisitor)8 ToManyProperty (org.apache.cayenne.reflect.ToManyProperty)8 ToOneProperty (org.apache.cayenne.reflect.ToOneProperty)8 ArcProperty (org.apache.cayenne.reflect.ArcProperty)5 Persistent (org.apache.cayenne.Persistent)4 ObjEntity (org.apache.cayenne.map.ObjEntity)4 Test (org.junit.Test)4 SingletonFaultFactory (org.apache.cayenne.reflect.SingletonFaultFactory)3 ArrayList (java.util.ArrayList)2 HashMap (java.util.HashMap)2 Map (java.util.Map)2 ObjectId (org.apache.cayenne.ObjectId)2 EJBQLException (org.apache.cayenne.ejbql.EJBQLException)2 EntityResolver (org.apache.cayenne.map.EntityResolver)2 ObjRelationship (org.apache.cayenne.map.ObjRelationship)2 PrefetchTreeNode (org.apache.cayenne.query.PrefetchTreeNode)2 Accessor (org.apache.cayenne.reflect.Accessor)2