Search in sources :

Example 1 with ToManyProperty

use of org.apache.cayenne.reflect.ToManyProperty 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(new ObjectId(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);
                Collection<Map.Entry> collection = (value instanceof Map) ? ((Map) value).entrySet() : (Collection) value;
                Iterator<Map.Entry> it = collection.iterator();
                while (it.hasNext()) {
                    Object target = it.next();
                    if (target instanceof Persistent) {
                        Persistent targetDO = (Persistent) target;
                        // make sure it is registered
                        registerNewObject(targetDO);
                        getObjectStore().arcCreated(persistent.getObjectId(), targetDO.getObjectId(), property.getName());
                    }
                }
            }
            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(), property.getName());
            }
            return true;
        }

        public boolean visitAttribute(AttributeProperty property) {
            return true;
        }
    });
}
Also used : ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) ObjectId(org.apache.cayenne.ObjectId) 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) ResultIteratorIterator(org.apache.cayenne.util.ResultIteratorIterator) Iterator(java.util.Iterator) ResultIterator(org.apache.cayenne.ResultIterator) Collection(java.util.Collection) DataObject(org.apache.cayenne.DataObject) Map(java.util.Map) PropertyVisitor(org.apache.cayenne.reflect.PropertyVisitor)

Example 2 with ToManyProperty

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

the class DataRowUtils method refreshObjectWithSnapshot.

/**
 * Replaces all object attribute values with snapshot values. Sets object state to
 * COMMITTED, unless the snapshot is partial in which case the state is set to HOLLOW
 */
static void refreshObjectWithSnapshot(ClassDescriptor descriptor, final Persistent object, final DataRow snapshot, final boolean invalidateToManyRelationships) {
    final boolean[] isPartialSnapshot = new boolean[1];
    descriptor.visitProperties(new PropertyVisitor() {

        public boolean visitAttribute(AttributeProperty property) {
            ObjAttribute attr = property.getAttribute();
            String dbAttrPath = attr.getDbAttributePath();
            Object value = snapshot.get(dbAttrPath);
            property.writePropertyDirectly(object, null, value);
            // checking for the null value first
            if (value == null && !snapshot.containsKey(dbAttrPath)) {
                isPartialSnapshot[0] = true;
            }
            return true;
        }

        public boolean visitToMany(ToManyProperty property) {
            // snapshot
            if (invalidateToManyRelationships) {
                property.invalidate(object);
            }
            return true;
        }

        public boolean visitToOne(ToOneProperty property) {
            property.invalidate(object);
            return true;
        }
    });
    object.setPersistenceState(isPartialSnapshot[0] ? PersistenceState.HOLLOW : PersistenceState.COMMITTED);
}
Also used : ObjAttribute(org.apache.cayenne.map.ObjAttribute) 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 3 with ToManyProperty

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

the class ObjectDiff method addDiff.

void addDiff(NodeDiff diff, ObjectStore parent) {
    boolean addDiff = true;
    if (diff instanceof ArcOperation) {
        ArcOperation arcDiff = (ArcOperation) diff;
        Object targetId = arcDiff.getTargetNodeId();
        String arcId = arcDiff.getArcId().toString();
        ArcProperty property = (ArcProperty) getClassDescriptor().getProperty(arcId);
        if (property == null && arcId.startsWith(ASTDbPath.DB_PREFIX)) {
            addPhantomFkDiff(arcDiff);
            addDiff = false;
        } else if (property instanceof ToManyProperty) {
            // record flattened op changes
            ObjRelationship relationship = property.getRelationship();
            if (relationship.isFlattened()) {
                if (flatIds == null) {
                    flatIds = new HashMap<>();
                }
                ArcOperation oldOp = flatIds.put(arcDiff, arcDiff);
                // "delete" cancels "create" and vice versa...
                if (oldOp != null && oldOp.isDelete() != arcDiff.isDelete()) {
                    addDiff = false;
                    flatIds.remove(arcDiff);
                    if (otherDiffs != null) {
                        otherDiffs.remove(oldOp);
                    }
                }
            } else if (property.getComplimentaryReverseArc() == null) {
                // register complimentary arc diff
                String arc = ASTDbPath.DB_PREFIX + property.getComplimentaryReverseDbRelationshipPath();
                ArcOperation complimentartyOp = new ArcOperation(targetId, arcDiff.getNodeId(), arc, arcDiff.isDelete());
                parent.registerDiff(targetId, complimentartyOp);
            }
        } else if (property instanceof ToOneProperty) {
            if (currentArcSnapshot == null) {
                currentArcSnapshot = new HashMap<>();
            }
            currentArcSnapshot.put(arcId, targetId);
        } else {
            String message = (property == null) ? "No property for arcId " + arcId : "Unrecognized property for arcId " + arcId + ": " + property;
            throw new CayenneRuntimeException(message);
        }
    }
    if (addDiff) {
        if (otherDiffs == null) {
            otherDiffs = new ArrayList<>(3);
        }
        otherDiffs.add(diff);
    }
}
Also used : ObjRelationship(org.apache.cayenne.map.ObjRelationship) ArcProperty(org.apache.cayenne.reflect.ArcProperty) ToManyProperty(org.apache.cayenne.reflect.ToManyProperty) HashMap(java.util.HashMap) CayenneRuntimeException(org.apache.cayenne.CayenneRuntimeException) ToOneProperty(org.apache.cayenne.reflect.ToOneProperty)

Example 4 with ToManyProperty

use of org.apache.cayenne.reflect.ToManyProperty 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();
            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 5 with ToManyProperty

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

the class EJBQLIdentifierColumnsTranslator method visitIdentifier.

@Override
public boolean visitIdentifier(EJBQLExpression expression) {
    Map<String, String> xfields = null;
    if (context.isAppendingResultColumns()) {
        xfields = context.nextEntityResult().getFields();
    }
    // assign whatever we have to a final ivar so that it can be accessed
    // within
    // the inner class
    final Map<String, String> fields = xfields;
    final String idVar = expression.getText();
    // append all table columns ... the trick is to follow the algorithm for
    // describing the fields in the expression compiler, so that we could
    // assign
    // columns labels from FieldResults in the order we encounter them
    // here...
    // TODO: andrus 2008/02/17 - this is a bit of a hack, think of a better
    // solution
    ClassDescriptor descriptor = context.getEntityDescriptor(idVar);
    PropertyVisitor visitor = new PropertyVisitor() {

        public boolean visitAttribute(AttributeProperty property) {
            ObjAttribute oa = property.getAttribute();
            Iterator<?> dbPathIterator = oa.getDbPathIterator();
            EJBQLJoinAppender joinAppender = null;
            String marker = null;
            EJBQLTableId lhsId = new EJBQLTableId(idVar);
            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) {
                    if (marker == null) {
                        marker = EJBQLJoinAppender.makeJoinTailMarker(idVar);
                        joinAppender = context.getTranslatorFactory().getJoinAppender(context);
                    }
                    DbRelationship dr = (DbRelationship) pathPart;
                    EJBQLTableId rhsId = new EJBQLTableId(lhsId, dr.getName());
                    joinAppender.appendOuterJoin(marker, lhsId, rhsId);
                    lhsId = rhsId;
                } else if (pathPart instanceof DbAttribute) {
                    appendColumn(idVar, oa, (DbAttribute) pathPart, fields, oa.getType());
                }
            }
            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) {
            ObjRelationship rel = property.getRelationship();
            DbRelationship dbRel = rel.getDbRelationships().get(0);
            for (DbJoin join : dbRel.getJoins()) {
                DbAttribute src = join.getSource();
                appendColumn(idVar, null, src, fields);
            }
        }
    };
    // EJBQL queries are polymorphic by definition - there is no distinction
    // between
    // inheritance/no-inheritance fetch
    descriptor.visitAllProperties(visitor);
    // append id columns ... (some may have been appended already via
    // relationships)
    DbEntity table = descriptor.getEntity().getDbEntity();
    for (DbAttribute pk : table.getPrimaryKeys()) {
        appendColumn(idVar, null, pk, fields);
    }
    // append inheritance discriminator columns...
    for (ObjAttribute column : descriptor.getDiscriminatorColumns()) {
        appendColumn(idVar, column, column.getDbAttribute(), fields);
    }
    addPrefetchedColumnsIfAny(idVar);
    return false;
}
Also used : ObjRelationship(org.apache.cayenne.map.ObjRelationship) ArcProperty(org.apache.cayenne.reflect.ArcProperty) ClassDescriptor(org.apache.cayenne.reflect.ClassDescriptor) ObjAttribute(org.apache.cayenne.map.ObjAttribute) CayenneRuntimeException(org.apache.cayenne.CayenneRuntimeException) DbAttribute(org.apache.cayenne.map.DbAttribute) AttributeProperty(org.apache.cayenne.reflect.AttributeProperty) ToOneProperty(org.apache.cayenne.reflect.ToOneProperty) ToManyProperty(org.apache.cayenne.reflect.ToManyProperty) DbEntity(org.apache.cayenne.map.DbEntity) DbRelationship(org.apache.cayenne.map.DbRelationship) DbJoin(org.apache.cayenne.map.DbJoin) PropertyVisitor(org.apache.cayenne.reflect.PropertyVisitor)

Aggregations

ToManyProperty (org.apache.cayenne.reflect.ToManyProperty)31 ToOneProperty (org.apache.cayenne.reflect.ToOneProperty)29 AttributeProperty (org.apache.cayenne.reflect.AttributeProperty)28 PropertyVisitor (org.apache.cayenne.reflect.PropertyVisitor)28 ClassDescriptor (org.apache.cayenne.reflect.ClassDescriptor)21 ArcProperty (org.apache.cayenne.reflect.ArcProperty)13 ObjRelationship (org.apache.cayenne.map.ObjRelationship)9 Persistent (org.apache.cayenne.Persistent)8 DbRelationship (org.apache.cayenne.map.DbRelationship)8 ObjAttribute (org.apache.cayenne.map.ObjAttribute)8 PropertyDescriptor (org.apache.cayenne.reflect.PropertyDescriptor)8 CayenneRuntimeException (org.apache.cayenne.CayenneRuntimeException)7 DbJoin (org.apache.cayenne.map.DbJoin)7 ObjEntity (org.apache.cayenne.map.ObjEntity)7 ObjectId (org.apache.cayenne.ObjectId)6 DbAttribute (org.apache.cayenne.map.DbAttribute)6 HashSet (java.util.HashSet)4 Map (java.util.Map)4 ArrayList (java.util.ArrayList)3 Collection (java.util.Collection)3