Search in sources :

Example 6 with ClassInfo

use of org.neo4j.ogm.metadata.ClassInfo in project neo4j-ogm by neo4j.

the class EntityGraphMapper method updateNode.

/**
 * Creates a new node or updates an existing one in the graph, if it has changed.
 *
 * @param entity      the domain object to be persisted
 * @param context     the current {@link CompileContext}
 * @param nodeBuilder a {@link NodeBuilder} that knows how to compile node create/update cypher phrases
 */
private void updateNode(Object entity, CompileContext context, NodeBuilder nodeBuilder) {
    // fire pre-save event here
    if (mappingContext.isDirty(entity)) {
        LOGGER.debug("{} has changed", entity);
        context.register(entity);
        ClassInfo classInfo = metaData.classInfo(entity);
        updateFieldsOnBuilder(entity, nodeBuilder, classInfo);
    } else {
        context.deregister(nodeBuilder);
        LOGGER.debug("{}, has not changed", entity);
    }
}
Also used : ClassInfo(org.neo4j.ogm.metadata.ClassInfo)

Example 7 with ClassInfo

use of org.neo4j.ogm.metadata.ClassInfo in project neo4j-ogm by neo4j.

the class GraphEntityMapper method createRelationshipEntity.

private Object createRelationshipEntity(Edge edge, Object startEntity, Object endEntity) {
    ClassInfo relationClassInfo = getRelationshipEntity(edge);
    if (relationClassInfo == null) {
        throw new MappingException("Could not find a class to map for relation " + edge);
    }
    Map<String, Object> allProps = new HashMap<>(toMap(edge.getPropertyList()));
    getCompositeProperties(edge.getPropertyList(), relationClassInfo).forEach((k, v) -> {
        allProps.put(k.getName(), v);
    });
    // also add start and end node as valid constructor values
    allProps.put(relationClassInfo.getStartNodeReader().getName(), startEntity);
    allProps.put(relationClassInfo.getEndNodeReader().getName(), endEntity);
    // create and hydrate the new RE
    Object relationshipEntity = entityFactory.newObject(relationClassInfo.getUnderlyingClass(), allProps);
    EntityUtils.setIdentity(relationshipEntity, edge.getId(), metadata);
    // REs also have properties
    setProperties(edge.getPropertyList(), relationshipEntity);
    // register it in the mapping context
    mappingContext.addRelationshipEntity(relationshipEntity, edge.getId());
    // set the start and end entities
    ClassInfo relEntityInfo = metadata.classInfo(relationshipEntity);
    FieldInfo startNodeWriter = relEntityInfo.getStartNodeReader();
    if (startNodeWriter != null) {
        startNodeWriter.write(relationshipEntity, startEntity);
    } else {
        throw new RuntimeException("Cannot find a writer for the StartNode of relational entity " + relEntityInfo.name());
    }
    FieldInfo endNodeWriter = relEntityInfo.getEndNodeReader();
    if (endNodeWriter != null) {
        endNodeWriter.write(relationshipEntity, endEntity);
    } else {
        throw new RuntimeException("Cannot find a writer for the EndNode of relational entity " + relEntityInfo.name());
    }
    return relationshipEntity;
}
Also used : FieldInfo(org.neo4j.ogm.metadata.FieldInfo) ClassInfo(org.neo4j.ogm.metadata.ClassInfo) MappingException(org.neo4j.ogm.exception.core.MappingException)

Example 8 with ClassInfo

use of org.neo4j.ogm.metadata.ClassInfo in project neo4j-ogm by neo4j.

the class GraphEntityMapper method mapOneToMany.

/**
 * Map many values to an instance based on the relationship type.
 * See DATAGRAPH-637
 *
 * @param instance         the instance to map values onto
 * @param valueType        the type of each value
 * @param values           the values to map
 * @param relationshipType the relationship type associated with these values
 */
private void mapOneToMany(Object instance, Class<?> valueType, Object values, String relationshipType, Direction relationshipDirection) {
    ClassInfo classInfo = metadata.classInfo(instance);
    FieldInfo writer = EntityAccessManager.getIterableField(classInfo, valueType, relationshipType, relationshipDirection);
    if (writer != null) {
        if (writer.type().isArray() || Iterable.class.isAssignableFrom(writer.type())) {
            FieldInfo reader = EntityAccessManager.getIterableField(classInfo, valueType, relationshipType, relationshipDirection);
            Object currentValues;
            if (reader != null) {
                currentValues = reader.read(instance);
                if (writer.type().isArray()) {
                    values = EntityAccessManager.merge(writer.type(), values, (Object[]) currentValues, valueType);
                } else {
                    values = EntityAccessManager.merge(writer.type(), values, (Collection) currentValues, valueType);
                }
            }
        }
        writer.write(instance, values);
        return;
    }
    // this is not necessarily an error. but we can't tell.
    logger.debug("Unable to map iterable of type: {} onto property of {}", valueType, classInfo.name());
}
Also used : FieldInfo(org.neo4j.ogm.metadata.FieldInfo) ClassInfo(org.neo4j.ogm.metadata.ClassInfo)

Example 9 with ClassInfo

use of org.neo4j.ogm.metadata.ClassInfo in project neo4j-ogm by neo4j.

the class GraphEntityMapper method getRelationshipEntity.

// Find the correct RE associated with the edge. The edge type may be polymorphic, so we need to do a bit of work
// to identify the correct RE to bind to. We must not cache the value when found, because the correct determination
// depends on the runtime values of the edge in the mapping context, which may vary for the same edge pattern.
private ClassInfo getRelationshipEntity(Edge edge) {
    Object source = mappingContext.getNodeEntity(edge.getStartNode());
    Object target = mappingContext.getNodeEntity(edge.getEndNode());
    Set<ClassInfo> classInfos = metadata.classInfoByLabelOrType(edge.getType());
    for (ClassInfo classInfo : classInfos) {
        // both source and target must be declared as START and END nodes respectively
        if (!nodeTypeMatches(classInfo, source, StartNode.class)) {
            continue;
        }
        if (!nodeTypeMatches(classInfo, target, EndNode.class)) {
            continue;
        }
        // if the source OR the target (or one of their superclasses) declares the relationship
        // back to the relationshipEntityClass, we've found a match
        Class relationshipEntityClass = classInfo.getUnderlyingClass();
        if (declaresRelationshipTo(relationshipEntityClass, source.getClass(), edge.getType(), Direction.OUTGOING)) {
            return classInfo;
        }
        if (declaresRelationshipTo(relationshipEntityClass, target.getClass(), edge.getType(), Direction.INCOMING)) {
            return classInfo;
        }
    }
    // the right one, otherwise ... give up
    if (classInfos.size() == 1) {
        ClassInfo classInfo = classInfos.iterator().next();
        if (nodeTypeMatches(classInfo, source, StartNode.class) && nodeTypeMatches(classInfo, target, EndNode.class)) {
            return classInfo;
        }
    } else {
        if (classInfos.size() == 0) {
            // not necessarily a problem, we mey be fetching edges we don't want to hydrate
            if (logger.isDebugEnabled()) {
                logger.debug("Unable to find a matching @RelationshipEntity for {}", edge.toString());
            }
        } else {
            // almost definitely a user bug
            logger.error("Found more than one matching @RelationshipEntity for {} but cannot tell which one to use", edge.toString());
        }
    }
    return null;
}
Also used : StartNode(org.neo4j.ogm.annotation.StartNode) EndNode(org.neo4j.ogm.annotation.EndNode) ClassInfo(org.neo4j.ogm.metadata.ClassInfo)

Example 10 with ClassInfo

use of org.neo4j.ogm.metadata.ClassInfo in project neo4j-ogm by neo4j.

the class GraphEntityMapper method setLabels.

private void setLabels(Node nodeModel, Object instance) {
    ClassInfo classInfo = metadata.classInfo(instance);
    FieldInfo labelFieldInfo = classInfo.labelFieldOrNull();
    if (labelFieldInfo != null) {
        Collection<String> staticLabels = classInfo.staticLabels();
        Set<String> dynamicLabels = new HashSet<>();
        for (String label : nodeModel.getLabels()) {
            if (!staticLabels.contains(label)) {
                dynamicLabels.add(label);
            }
        }
        writeProperty(classInfo, instance, PropertyModel.with(labelFieldInfo.getName(), dynamicLabels));
    }
}
Also used : FieldInfo(org.neo4j.ogm.metadata.FieldInfo) ClassInfo(org.neo4j.ogm.metadata.ClassInfo)

Aggregations

ClassInfo (org.neo4j.ogm.metadata.ClassInfo)145 FieldInfo (org.neo4j.ogm.metadata.FieldInfo)100 Test (org.junit.Test)76 ArrayList (java.util.ArrayList)11 HashSet (java.util.HashSet)8 MetaData (org.neo4j.ogm.metadata.MetaData)8 CompileContext (org.neo4j.ogm.cypher.compiler.CompileContext)6 HashMap (java.util.HashMap)5 Map (java.util.Map)5 NodeBuilder (org.neo4j.ogm.cypher.compiler.NodeBuilder)5 MappingException (org.neo4j.ogm.exception.core.MappingException)5 RowModel (org.neo4j.ogm.model.RowModel)5 Collection (java.util.Collection)4 LinkedHashSet (java.util.LinkedHashSet)4 List (java.util.List)4 Optional (java.util.Optional)4 CypherQuery (org.neo4j.ogm.cypher.query.CypherQuery)4 Member (org.neo4j.ogm.domain.forum.Member)4 Satellite (org.neo4j.ogm.domain.satellites.Satellite)4 Collections (java.util.Collections)3