Search in sources :

Example 11 with ClassDescriptor

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

the class DataContext method registerNewObject.

/**
 * Registers a transient object with the context, recursively registering
 * all transient persistent objects attached to this object via
 * relationships.
 * <p>
 * <i>Note that since 3.0 this method takes Object as an argument instead of
 * a {@link DataObject}.</i>
 *
 * @param object
 *            new object that needs to be made persistent.
 */
@Override
public void registerNewObject(Object object) {
    if (object == null) {
        throw new NullPointerException("Can't register null object.");
    }
    ObjEntity entity = getEntityResolver().getObjEntity((Persistent) object);
    if (entity == null) {
        throw new IllegalArgumentException("Can't find ObjEntity for Persistent class: " + object.getClass().getName() + ", class is likely not mapped.");
    }
    final Persistent persistent = (Persistent) object;
    // sanity check - maybe already registered
    if (persistent.getObjectId() != null) {
        if (persistent.getObjectContext() == this) {
            // already registered, just ignore
            return;
        } else if (persistent.getObjectContext() != null) {
            throw new IllegalStateException("Persistent is already registered with another DataContext. " + "Try using 'localObjects()' instead.");
        }
    } else {
        persistent.setObjectId(ObjectId.of(entity.getName()));
    }
    ClassDescriptor descriptor = getEntityResolver().getClassDescriptor(entity.getName());
    if (descriptor == null) {
        throw new IllegalArgumentException("Invalid entity name: " + entity.getName());
    }
    injectInitialValue(object);
    // now we need to find all arc changes, inject missing value holders and
    // pull in
    // all transient connected objects
    descriptor.visitProperties(new PropertyVisitor() {

        public boolean visitToMany(ToManyProperty property) {
            property.injectValueHolder(persistent);
            if (!property.isFault(persistent)) {
                Object value = property.readProperty(persistent);
                @SuppressWarnings("unchecked") Collection<Map.Entry> collection = (value instanceof Map) ? ((Map) value).entrySet() : (Collection) value;
                for (Object target : collection) {
                    if (target instanceof Persistent) {
                        Persistent targetDO = (Persistent) target;
                        // make sure it is registered
                        registerNewObject(targetDO);
                        getObjectStore().arcCreated(persistent.getObjectId(), targetDO.getObjectId(), new ArcId(property));
                    }
                }
            }
            return true;
        }

        public boolean visitToOne(ToOneProperty property) {
            Object target = property.readPropertyDirectly(persistent);
            if (target instanceof Persistent) {
                Persistent targetDO = (Persistent) target;
                // make sure it is registered
                registerNewObject(targetDO);
                getObjectStore().arcCreated(persistent.getObjectId(), targetDO.getObjectId(), new ArcId(property));
            }
            return true;
        }

        public boolean visitAttribute(AttributeProperty property) {
            return true;
        }
    });
}
Also used : ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) ArcId(org.apache.cayenne.graph.ArcId) Persistent(org.apache.cayenne.Persistent) AttributeProperty(org.apache.cayenne.reflect.AttributeProperty) ToOneProperty(org.apache.cayenne.reflect.ToOneProperty) ObjEntity(org.apache.cayenne.map.ObjEntity) ToManyProperty(org.apache.cayenne.reflect.ToManyProperty) Collection(java.util.Collection) DataObject(org.apache.cayenne.DataObject) Map(java.util.Map) PropertyVisitor(org.apache.cayenne.reflect.PropertyVisitor)

Example 12 with ClassDescriptor

use of org.apache.cayenne.reflect.ClassDescriptor 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 13 with ClassDescriptor

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

the class BaseContext method localObject.

/**
 * @since 3.1
 */
@Override
public <T extends Persistent> T localObject(T objectFromAnotherContext) {
    if (objectFromAnotherContext == null) {
        throw new NullPointerException("Null object argument");
    }
    ObjectId id = objectFromAnotherContext.getObjectId();
    // first look for the ID in the local GraphManager
    synchronized (getGraphManager()) {
        @SuppressWarnings("unchecked") T localObject = (T) getGraphManager().getNode(id);
        if (localObject != null) {
            return localObject;
        }
        // create a hollow object, optimistically assuming that the ID we got from
        // 'objectFromAnotherContext' is a valid ID either in the parent context or in the DB.
        // This essentially defers possible FaultFailureExceptions.
        ClassDescriptor descriptor = getEntityResolver().getClassDescriptor(id.getEntityName());
        @SuppressWarnings("unchecked") T persistent = (T) descriptor.createObject();
        persistent.setObjectContext(this);
        persistent.setObjectId(id);
        persistent.setPersistenceState(PersistenceState.HOLLOW);
        getGraphManager().registerNode(id, persistent);
        return persistent;
    }
}
Also used : ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor)

Example 14 with ClassDescriptor

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

the class PrefetchNodeStage method processJoint.

private void processJoint(TranslatorContext context) {
    QueryMetadata queryMetadata = context.getMetadata();
    PrefetchTreeNode prefetch = queryMetadata.getPrefetchTree();
    if (prefetch == null) {
        return;
    }
    ObjEntity objEntity = queryMetadata.getObjEntity();
    boolean warnPrefetchWithLimit = false;
    for (PrefetchTreeNode node : prefetch.adjacentJointNodes()) {
        Expression prefetchExp = ExpressionFactory.exp(node.getPath());
        ASTDbPath dbPrefetch = (ASTDbPath) objEntity.translateToDbPath(prefetchExp);
        final String dbPath = dbPrefetch.getPath();
        DbEntity dbEntity = objEntity.getDbEntity();
        PathComponents components = new PathComponents(dbPath);
        StringBuilder fullPath = new StringBuilder();
        for (String c : components.getAll()) {
            DbRelationship rel = dbEntity.getRelationship(c);
            if (rel == null) {
                throw new CayenneRuntimeException("Unable to resolve path %s for entity %s", dbPath, objEntity.getName());
            }
            if (fullPath.length() > 0) {
                fullPath.append('.');
            }
            context.getTableTree().addJoinTable("p:" + fullPath.append(c).toString(), rel, JoinType.LEFT_OUTER);
            dbEntity = rel.getTargetEntity();
        }
        ObjRelationship targetRel = (ObjRelationship) prefetchExp.evaluate(objEntity);
        ClassDescriptor prefetchClassDescriptor = context.getResolver().getClassDescriptor(targetRel.getTargetEntityName());
        DescriptorColumnExtractor columnExtractor = new DescriptorColumnExtractor(context, prefetchClassDescriptor);
        columnExtractor.extract("p:" + dbPath);
        if (!warnPrefetchWithLimit && targetRel.isToMany() && (queryMetadata.getFetchLimit() > 0 || queryMetadata.getFetchOffset() > 0)) {
            warnPrefetchWithLimit = true;
        }
    }
    // warn about a potentially faulty joint prefetch + limit combination
    if (warnPrefetchWithLimit) {
        LOGGER.warn("The query uses both limit/offset and a joint prefetch, this most probably will lead to an incorrect result. " + "Either use disjointById prefetch or get a full result set.");
    }
}
Also used : ObjRelationship(org.apache.cayenne.map.ObjRelationship) QueryMetadata(org.apache.cayenne.query.QueryMetadata) ASTDbPath(org.apache.cayenne.exp.parser.ASTDbPath) ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) CayenneRuntimeException(org.apache.cayenne.CayenneRuntimeException) ObjEntity(org.apache.cayenne.map.ObjEntity) DbEntity(org.apache.cayenne.map.DbEntity) Expression(org.apache.cayenne.exp.Expression) PrefetchTreeNode(org.apache.cayenne.query.PrefetchTreeNode) DbRelationship(org.apache.cayenne.map.DbRelationship)

Example 15 with ClassDescriptor

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

the class QualifierTranslationStage method perform.

@Override
public void perform(TranslatorContext context) {
    QualifierTranslator translator = context.getQualifierTranslator();
    Expression expression = context.getQuery().getQualifier();
    // Attaching Obj entity's qualifier
    ObjEntity entity = context.getMetadata().getObjEntity();
    if (entity != null) {
        ClassDescriptor descriptor = context.getMetadata().getClassDescriptor();
        Expression entityQualifier = descriptor.getEntityInheritanceTree().qualifierForEntityAndSubclasses();
        if (entityQualifier != null) {
            expression = expression == null ? entityQualifier : expression.andExp(entityQualifier);
        }
    }
    Node qualifierNode = translator.translate(expression);
    context.setQualifierNode(qualifierNode);
}
Also used : ObjEntity(org.apache.cayenne.map.ObjEntity) ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) Expression(org.apache.cayenne.exp.Expression) Node(org.apache.cayenne.access.sqlbuilder.sqltree.Node) SimpleNode(org.apache.cayenne.exp.parser.SimpleNode)

Aggregations

ClassDescriptor (org.apache.cayenne.reflect.ClassDescriptor)90 AttributeProperty (org.apache.cayenne.reflect.AttributeProperty)25 PropertyVisitor (org.apache.cayenne.reflect.PropertyVisitor)23 ToManyProperty (org.apache.cayenne.reflect.ToManyProperty)23 ToOneProperty (org.apache.cayenne.reflect.ToOneProperty)23 ObjEntity (org.apache.cayenne.map.ObjEntity)22 ArcProperty (org.apache.cayenne.reflect.ArcProperty)21 Persistent (org.apache.cayenne.Persistent)20 CayenneRuntimeException (org.apache.cayenne.CayenneRuntimeException)16 PropertyDescriptor (org.apache.cayenne.reflect.PropertyDescriptor)15 DbRelationship (org.apache.cayenne.map.DbRelationship)14 ObjRelationship (org.apache.cayenne.map.ObjRelationship)13 DataRow (org.apache.cayenne.DataRow)12 ObjectId (org.apache.cayenne.ObjectId)12 Test (org.junit.Test)12 DbAttribute (org.apache.cayenne.map.DbAttribute)10 DataObject (org.apache.cayenne.DataObject)9 EJBQLException (org.apache.cayenne.ejbql.EJBQLException)9 DbJoin (org.apache.cayenne.map.DbJoin)9 ArrayList (java.util.ArrayList)8