Search in sources :

Example 6 with AttributeProperty

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

the class CayenneContextChildDiffLoader method arcDeleted.

@Override
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());
    final Persistent[] target = new Persistent[1];
    target[0] = findObject(targetNodeId);
    property.visit(new PropertyVisitor() {

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

        public boolean visitToMany(ToManyProperty property) {
            if (target[0] == 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[0] = findObjectInCollection(targetNodeId, property.readProperty(source));
            }
            if (target[0] != null) {
                property.removeTargetDirectly(source, target[0]);
            }
            return false;
        }

        public boolean visitToOne(ToOneProperty property) {
            property.setTarget(source, null, false);
            return false;
        }
    });
    context.propertyChanged(source, (String) arcId, target[0], null);
}
Also used : ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) PropertyDescriptor(org.apache.cayenne.reflect.PropertyDescriptor) ToManyProperty(org.apache.cayenne.reflect.ToManyProperty) AttributeProperty(org.apache.cayenne.reflect.AttributeProperty) PropertyVisitor(org.apache.cayenne.reflect.PropertyVisitor) ToOneProperty(org.apache.cayenne.reflect.ToOneProperty)

Example 7 with AttributeProperty

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

the class BaseContext method prepareForAccess.

@Override
public void prepareForAccess(Persistent object, String property, boolean lazyFaulting) {
    if (object.getPersistenceState() == PersistenceState.HOLLOW) {
        ObjectId oid = object.getObjectId();
        List<?> objects = performQuery(new ObjectIdQuery(oid, false, ObjectIdQuery.CACHE));
        if (objects.size() == 0) {
            throw new FaultFailureException("Error resolving fault, no matching row exists in the database for ObjectId: " + oid);
        } else if (objects.size() > 1) {
            throw new FaultFailureException("Error resolving fault, more than one row exists in the database for ObjectId: " + oid);
        }
    // 5/28/2013 - Commented out this block to allow for modifying
    // objects in the postLoad callback
    // sanity check...
    // if (object.getPersistenceState() != PersistenceState.COMMITTED) {
    // 
    // String state =
    // PersistenceState.persistenceStateName(object.getPersistenceState());
    // 
    // // TODO: andrus 4/13/2006, modified and deleted states are
    // // possible due to
    // // a race condition, should we handle them here?
    // throw new
    // FaultFailureException("Error resolving fault for ObjectId: " +
    // oid + " and state (" + state
    // +
    // "). Possible cause - matching row is missing from the database.");
    // }
    }
    // resolve relationship fault
    if (lazyFaulting && property != null) {
        ClassDescriptor classDescriptor = getEntityResolver().getClassDescriptor(object.getObjectId().getEntityName());
        PropertyDescriptor propertyDescriptor = classDescriptor.getProperty(property);
        // be used.
        if (propertyDescriptor == null) {
            final StringBuilder errorMessage = new StringBuilder();
            errorMessage.append(String.format("Property '%s' is not declared for entity '%s'.", property, object.getObjectId().getEntityName()));
            errorMessage.append(" Declared properties are: ");
            // Grab each of the declared properties.
            final List<String> properties = new ArrayList<>();
            classDescriptor.visitProperties(new PropertyVisitor() {

                @Override
                public boolean visitAttribute(final AttributeProperty property) {
                    properties.add(property.getName());
                    return true;
                }

                @Override
                public boolean visitToOne(final ToOneProperty property) {
                    properties.add(property.getName());
                    return true;
                }

                @Override
                public boolean visitToMany(final ToManyProperty property) {
                    properties.add(property.getName());
                    return true;
                }
            });
            // Now add the declared property names to the error message.
            boolean first = true;
            for (String declaredProperty : properties) {
                if (first) {
                    errorMessage.append(String.format("'%s'", declaredProperty));
                    first = false;
                } else {
                    errorMessage.append(String.format(", '%s'", declaredProperty));
                }
            }
            errorMessage.append(".");
            throw new CayenneRuntimeException(errorMessage.toString());
        }
        // this should trigger fault resolving
        propertyDescriptor.readProperty(object);
    }
}
Also used : ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) PropertyDescriptor(org.apache.cayenne.reflect.PropertyDescriptor) ArrayList(java.util.ArrayList) AttributeProperty(org.apache.cayenne.reflect.AttributeProperty) ToOneProperty(org.apache.cayenne.reflect.ToOneProperty) ToManyProperty(org.apache.cayenne.reflect.ToManyProperty) ObjectIdQuery(org.apache.cayenne.query.ObjectIdQuery) PropertyVisitor(org.apache.cayenne.reflect.PropertyVisitor)

Example 8 with AttributeProperty

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

the class DeletedDiffProcessor method nodeRemoved.

@Override
public void nodeRemoved(Object nodeId) {
    ObjectId id = (ObjectId) nodeId;
    final MutableObjectChange objectChangeSet = changeSet.getOrCreate(id, ObjectChangeType.DELETE);
    // TODO: rewrite with SelectById query after Cayenne upgrade
    ObjectIdQuery query = new ObjectIdQuery(id, true, ObjectIdQuery.CACHE);
    QueryResponse result = channel.onQuery(null, query);
    @SuppressWarnings("unchecked") List<DataRow> rows = result.firstList();
    if (rows.isEmpty()) {
        LOGGER.warn("No DB snapshot for object to be deleted, no changes will be recorded. ID: " + id);
        return;
    }
    final DataRow row = rows.get(0);
    ClassDescriptor descriptor = channel.getEntityResolver().getClassDescriptor(id.getEntityName());
    final CommitLogEntity entity = entityFactory.getEntity(id);
    descriptor.visitProperties(new PropertyVisitor() {

        @Override
        public boolean visitAttribute(AttributeProperty property) {
            if (!entity.isIncluded(property.getName())) {
                return true;
            }
            Object value;
            if (entity.isConfidential(property.getName())) {
                value = Confidential.getInstance();
            } else {
                String key = property.getAttribute().getDbAttributeName();
                value = row.get(key);
            }
            if (value != null) {
                objectChangeSet.attributeChanged(property.getName(), value, null);
            }
            return true;
        }

        @Override
        public boolean visitToOne(ToOneProperty property) {
            // TODO record FK changes?
            return true;
        }

        @Override
        public boolean visitToMany(ToManyProperty property) {
            return true;
        }
    });
}
Also used : MutableObjectChange(org.apache.cayenne.commitlog.model.MutableObjectChange) CommitLogEntity(org.apache.cayenne.commitlog.meta.CommitLogEntity) ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) ObjectId(org.apache.cayenne.ObjectId) AttributeProperty(org.apache.cayenne.reflect.AttributeProperty) DataRow(org.apache.cayenne.DataRow) ToOneProperty(org.apache.cayenne.reflect.ToOneProperty) ToManyProperty(org.apache.cayenne.reflect.ToManyProperty) QueryResponse(org.apache.cayenne.QueryResponse) ObjectIdQuery(org.apache.cayenne.query.ObjectIdQuery) PropertyVisitor(org.apache.cayenne.reflect.PropertyVisitor)

Example 9 with AttributeProperty

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

the class DataObjectDescriptorFactoryIT method testVisitDeclaredProperties_IterationOrder.

@Test
public void testVisitDeclaredProperties_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.visitDeclaredProperties(visitor);
    }
}
Also used : ObjEntity(org.apache.cayenne.map.ObjEntity) SingletonFaultFactory(org.apache.cayenne.reflect.SingletonFaultFactory) ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) PropertyDescriptor(org.apache.cayenne.reflect.PropertyDescriptor) ToManyProperty(org.apache.cayenne.reflect.ToManyProperty) AttributeProperty(org.apache.cayenne.reflect.AttributeProperty) PropertyVisitor(org.apache.cayenne.reflect.PropertyVisitor) ToOneProperty(org.apache.cayenne.reflect.ToOneProperty) Test(org.junit.Test)

Example 10 with AttributeProperty

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

the class DefaultSelectTranslator method appendQueryColumns.

/**
 * Appends columns needed for object SelectQuery to the provided columns
 * list.
 */
<T> List<ColumnDescriptor> appendQueryColumns(final List<ColumnDescriptor> columns, SelectQuery<T> query, ClassDescriptor descriptor, final String tableAlias) {
    final Set<ColumnTracker> attributes = new HashSet<>();
    // fetched attributes include attributes that are either:
    // 
    // * class properties
    // * PK
    // * FK used in relationship
    // * joined prefetch PK
    ObjEntity oe = descriptor.getEntity();
    PropertyVisitor visitor = new PropertyVisitor() {

        public boolean visitAttribute(AttributeProperty property) {
            ObjAttribute oa = property.getAttribute();
            resetJoinStack();
            Iterator<CayenneMapEntry> dbPathIterator = oa.getDbPathIterator();
            while (dbPathIterator.hasNext()) {
                Object pathPart = dbPathIterator.next();
                if (pathPart == null) {
                    throw new CayenneRuntimeException("ObjAttribute has no component: %s", oa.getName());
                } else if (pathPart instanceof DbRelationship) {
                    DbRelationship rel = (DbRelationship) pathPart;
                    dbRelationshipAdded(rel, JoinType.LEFT_OUTER, null);
                } else if (pathPart instanceof DbAttribute) {
                    DbAttribute dbAttr = (DbAttribute) pathPart;
                    appendColumn(columns, oa, dbAttr, attributes, null, tableAlias);
                }
            }
            return true;
        }

        public boolean visitToMany(ToManyProperty property) {
            visitRelationship(property);
            return true;
        }

        public boolean visitToOne(ToOneProperty property) {
            visitRelationship(property);
            return true;
        }

        private void visitRelationship(ArcProperty property) {
            resetJoinStack();
            ObjRelationship rel = property.getRelationship();
            DbRelationship dbRel = rel.getDbRelationships().get(0);
            List<DbJoin> joins = dbRel.getJoins();
            for (DbJoin join : joins) {
                DbAttribute src = join.getSource();
                appendColumn(columns, null, src, attributes, null, tableAlias);
            }
        }
    };
    descriptor.visitAllProperties(visitor);
    // stack should be reset, because all root table attributes go with "t0"
    // table alias
    resetJoinStack();
    // add remaining needed attrs from DbEntity
    DbEntity table = oe.getDbEntity();
    for (DbAttribute dba : table.getPrimaryKeys()) {
        appendColumn(columns, null, dba, attributes, null, tableAlias);
    }
    if (query instanceof PrefetchSelectQuery) {
        // for each relationship path add PK of the target entity...
        for (String path : ((PrefetchSelectQuery) query).getResultPaths()) {
            ASTDbPath pathExp = (ASTDbPath) oe.translateToDbPath(ExpressionFactory.exp(path));
            // add joins and find terminating element
            resetJoinStack();
            PathComponent<DbAttribute, DbRelationship> lastComponent = null;
            for (PathComponent<DbAttribute, DbRelationship> component : table.resolvePath(pathExp, getPathAliases())) {
                if (component.getRelationship() != null) {
                    // do not invoke dbRelationshipAdded(), invoke
                    // pushJoin() instead. This is to prevent
                    // 'forcingDistinct' flipping to true, that will result
                    // in unneeded extra processing and sometimes in invalid
                    // results (see CAY-1979). Distinctness of each row is
                    // guaranteed by the prefetch query semantics - we
                    // include target ID in the result columns
                    getJoinStack().pushJoin(component.getRelationship(), component.getJoinType(), null);
                }
                lastComponent = component;
            }
            // process terminating element
            if (lastComponent != null) {
                DbRelationship relationship = lastComponent.getRelationship();
                if (relationship != null) {
                    String labelPrefix = pathExp.getPath();
                    DbEntity targetEntity = relationship.getTargetEntity();
                    for (DbAttribute pk : targetEntity.getPrimaryKeys()) {
                        // note that we my select a source attribute, but
                        // label it as
                        // target for simplified snapshot processing
                        appendColumn(columns, null, pk, attributes, labelPrefix + '.' + pk.getName());
                    }
                }
            }
        }
    }
    // handle joint prefetches directly attached to this query...
    if (query.getPrefetchTree() != null) {
        // perform some sort of union or sub-queries.
        for (PrefetchTreeNode prefetch : query.getPrefetchTree().getChildren()) {
            prefetch.setEntityName(oe.getName());
        }
        for (PrefetchTreeNode prefetch : query.getPrefetchTree().adjacentJointNodes()) {
            // for each prefetch add all joins plus columns from the target
            // entity
            Expression prefetchExp = ExpressionFactory.exp(prefetch.getPath());
            ASTDbPath dbPrefetch = (ASTDbPath) oe.translateToDbPath(prefetchExp);
            resetJoinStack();
            DbRelationship r = null;
            for (PathComponent<DbAttribute, DbRelationship> component : table.resolvePath(dbPrefetch, getPathAliases())) {
                r = component.getRelationship();
                dbRelationshipAdded(r, JoinType.LEFT_OUTER, null);
            }
            if (r == null) {
                throw new CayenneRuntimeException("Invalid joint prefetch '%s' for entity: %s", prefetch, oe.getName());
            }
            // add columns from the target entity, including those that are matched
            // against the FK of the source entity.
            // This is needed to determine whether optional relationships are null
            // go via target OE to make sure that Java types are mapped correctly...
            ObjRelationship targetRel = (ObjRelationship) prefetchExp.evaluate(oe);
            ObjEntity targetEntity = targetRel.getTargetEntity();
            String labelPrefix = dbPrefetch.getPath();
            PropertyVisitor prefetchVisitor = new PropertyVisitor() {

                public boolean visitAttribute(AttributeProperty property) {
                    ObjAttribute oa = property.getAttribute();
                    Iterator<CayenneMapEntry> dbPathIterator = oa.getDbPathIterator();
                    while (dbPathIterator.hasNext()) {
                        Object pathPart = dbPathIterator.next();
                        if (pathPart == null) {
                            throw new CayenneRuntimeException("ObjAttribute has no component: %s", oa.getName());
                        } else if (pathPart instanceof DbRelationship) {
                            DbRelationship rel = (DbRelationship) pathPart;
                            dbRelationshipAdded(rel, JoinType.INNER, null);
                        } else if (pathPart instanceof DbAttribute) {
                            DbAttribute dbAttr = (DbAttribute) pathPart;
                            appendColumn(columns, oa, dbAttr, attributes, labelPrefix + '.' + dbAttr.getName());
                        }
                    }
                    return true;
                }

                public boolean visitToMany(ToManyProperty property) {
                    return true;
                }

                public boolean visitToOne(ToOneProperty property) {
                    return true;
                }
            };
            ClassDescriptor prefetchClassDescriptor = entityResolver.getClassDescriptor(targetEntity.getName());
            prefetchClassDescriptor.visitAllProperties(prefetchVisitor);
            // append remaining target attributes such as keys
            DbEntity targetDbEntity = r.getTargetEntity();
            for (DbAttribute attribute : targetDbEntity.getAttributes()) {
                appendColumn(columns, null, attribute, attributes, labelPrefix + '.' + attribute.getName());
            }
        }
    }
    return columns;
}
Also used : ArcProperty(org.apache.cayenne.reflect.ArcProperty) ObjAttribute(org.apache.cayenne.map.ObjAttribute) ASTDbPath(org.apache.cayenne.exp.parser.ASTDbPath) ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) CayenneRuntimeException(org.apache.cayenne.CayenneRuntimeException) DbAttribute(org.apache.cayenne.map.DbAttribute) ToOneProperty(org.apache.cayenne.reflect.ToOneProperty) CayenneMapEntry(org.apache.cayenne.util.CayenneMapEntry) DbEntity(org.apache.cayenne.map.DbEntity) PrefetchTreeNode(org.apache.cayenne.query.PrefetchTreeNode) HashSet(java.util.HashSet) ObjRelationship(org.apache.cayenne.map.ObjRelationship) AttributeProperty(org.apache.cayenne.reflect.AttributeProperty) PrefetchSelectQuery(org.apache.cayenne.query.PrefetchSelectQuery) ObjEntity(org.apache.cayenne.map.ObjEntity) ToManyProperty(org.apache.cayenne.reflect.ToManyProperty) Expression(org.apache.cayenne.exp.Expression) DbRelationship(org.apache.cayenne.map.DbRelationship) DbJoin(org.apache.cayenne.map.DbJoin) PropertyVisitor(org.apache.cayenne.reflect.PropertyVisitor)

Aggregations

AttributeProperty (org.apache.cayenne.reflect.AttributeProperty)30 PropertyVisitor (org.apache.cayenne.reflect.PropertyVisitor)28 ToManyProperty (org.apache.cayenne.reflect.ToManyProperty)28 ToOneProperty (org.apache.cayenne.reflect.ToOneProperty)28 ClassDescriptor (org.apache.cayenne.reflect.ClassDescriptor)23 ArcProperty (org.apache.cayenne.reflect.ArcProperty)11 Persistent (org.apache.cayenne.Persistent)10 PropertyDescriptor (org.apache.cayenne.reflect.PropertyDescriptor)9 ObjectId (org.apache.cayenne.ObjectId)8 DbRelationship (org.apache.cayenne.map.DbRelationship)8 ObjAttribute (org.apache.cayenne.map.ObjAttribute)8 ObjRelationship (org.apache.cayenne.map.ObjRelationship)8 CayenneRuntimeException (org.apache.cayenne.CayenneRuntimeException)7 DbJoin (org.apache.cayenne.map.DbJoin)7 ObjEntity (org.apache.cayenne.map.ObjEntity)7 Map (java.util.Map)6 DbAttribute (org.apache.cayenne.map.DbAttribute)6 ArrayList (java.util.ArrayList)4 HashSet (java.util.HashSet)4 DataObject (org.apache.cayenne.DataObject)4