Search in sources :

Example 1 with Direction

use of org.neo4j.ogm.annotation.Relationship.Direction in project neo4j-ogm by neo4j.

the class EntityCollector method forCollectedEntities.

public void forCollectedEntities(CollectedHandler handler) {
    collected.forEach((sourceId, relationshipMap) -> {
        relationshipMap.forEach((relationship, targetTypeMap) -> {
            String type = relationship.type();
            Direction direction = relationship.direction();
            targetTypeMap.forEach((targetType, entityTriples) -> {
                List<Object> entities = entityTriples.stream().map(TargetTriple::getTarget).collect(toList());
                handler.handle(sourceId, type, direction, targetType, entities);
            });
        });
    });
}
Also used : Direction(org.neo4j.ogm.annotation.Relationship.Direction)

Example 2 with Direction

use of org.neo4j.ogm.annotation.Relationship.Direction in project neo4j-ogm by neo4j.

the class EntityGraphMapper method bothWayMappingRequired.

/**
 * Determines whether or not a two way mapping is required for the relationship.
 * Relationships annotated with either {@link Relationship} direction INCOMING or OUTGOING and defined between two entities of the same type
 * will be considered for a dual mapping.
 * Specifically, if the source and target entity are of the same type, and the related object from the source for relationship type R in direction D
 * is the same as the related object from the target for relationship type R in direction D, then the relationship is mapped both ways.
 *
 * @param srcObject             the domain object representing the start node of the relationship
 * @param relationshipType      the type of the relationship from the srcObject
 * @param tgtObject             the domain object representing the end node of the relationship
 * @param relationshipDirection the direction of the relationship from the srcObject
 * @return true if the relationship should be mapped both ways, false otherwise
 */
private boolean bothWayMappingRequired(Object srcObject, String relationshipType, Object tgtObject, Relationship.Direction relationshipDirection) {
    boolean mapBothWays = false;
    ClassInfo tgtInfo = metaData.classInfo(tgtObject);
    if (tgtInfo == null) {
        LOGGER.warn("Unable to process {} on {}. Check the mapping.", relationshipType, srcObject.getClass());
        // #347. attribute is not a rel ? maybe would be better to change FieldInfo.persistableAsProperty ?
        return false;
    }
    for (FieldInfo tgtRelReader : tgtInfo.relationshipFields()) {
        Direction tgtRelationshipDirection = tgtRelReader.relationshipDirection();
        // and the source must be related to the target and vice versa in the SAME direction
        if (tgtRelationshipDirection != Direction.UNDIRECTED && tgtRelReader.relationshipType().equals(relationshipType) && relationshipDirection.equals(tgtRelationshipDirection)) {
            Object target = tgtRelReader.read(tgtObject);
            mapBothWays = targetEqualsSource(target, srcObject);
        }
        // We don't need any other field if we already found a match.
        if (mapBothWays) {
            break;
        }
    }
    return mapBothWays;
}
Also used : Direction(org.neo4j.ogm.annotation.Relationship.Direction) FieldInfo(org.neo4j.ogm.metadata.FieldInfo) ClassInfo(org.neo4j.ogm.metadata.ClassInfo)

Example 3 with Direction

use of org.neo4j.ogm.annotation.Relationship.Direction in project neo4j-ogm by neo4j.

the class SaveEventDelegate method mapInstance.

// creates a MappedRelationship between the parent object and the reference. In the case that the reference
// object is a RE, the relationship is created from the start node and the end node of the RE.
// a MappedRelationship therefore represents a directed edge between two nodes in the graph.
private void mapInstance(Set<MappedRelationship> mappedRelationships, ClassInfo parentInfo, long parentId, FieldInfo reader, Object reference) {
    String type = reader.relationshipType();
    Direction direction = reader.relationshipDirection();
    ClassInfo referenceInfo = this.session.metaData().classInfo(reference);
    if (referenceInfo == null) {
        return;
    }
    if (referenceInfo.isRelationshipEntity()) {
        // The relationship entity might just get created and therefore we must be careful not to
        // trigger the creation of it's id place holder, otherwise we can't check wether it's new or not.
        Optional<Long> optionalReferenceId = session.context().optionalNativeId(reference);
        // graph relationship is transitive across the RE domain object
        Object startNode = referenceInfo.getStartNodeReader().read(reference);
        ClassInfo startNodeInfo = this.session.metaData().classInfo(startNode);
        Long startNodeId = session.context().nativeId(startNode);
        Object endNode = referenceInfo.getEndNodeReader().read(reference);
        ClassInfo endNodeInfo = this.session.metaData().classInfo(endNode);
        Long endNodeId = session.context().nativeId(endNode);
        MappedRelationship edge = new MappedRelationship(startNodeId, type, endNodeId, optionalReferenceId.orElse(null), startNodeInfo.getUnderlyingClass(), endNodeInfo.getUnderlyingClass());
        mappedRelationships.add(edge);
    } else {
        // We assume the existence of the reference here
        Long referenceId = session.context().nativeId(reference);
        if (direction == Direction.OUTGOING) {
            MappedRelationship edge = new MappedRelationship(parentId, type, referenceId, null, parentInfo.getUnderlyingClass(), referenceInfo.getUnderlyingClass());
            mappedRelationships.add(edge);
        } else {
            MappedRelationship edge = new MappedRelationship(referenceId, type, parentId, null, referenceInfo.getUnderlyingClass(), parentInfo.getUnderlyingClass());
            mappedRelationships.add(edge);
        }
    }
}
Also used : MappedRelationship(org.neo4j.ogm.context.MappedRelationship) Direction(org.neo4j.ogm.annotation.Relationship.Direction) ClassInfo(org.neo4j.ogm.metadata.ClassInfo)

Example 4 with Direction

use of org.neo4j.ogm.annotation.Relationship.Direction in project neo4j-ogm by neo4j.

the class SessionDelegate method updateRelationship.

private void updateRelationship(FilterWithRelationship filter, FieldInfo fieldInfo, String relationshipType) {
    filter.setRelationshipType(relationshipType);
    filter.setRelationshipDirection(Direction.UNDIRECTED);
    if (fieldInfo.getAnnotations() != null) {
        AnnotationInfo annotation = fieldInfo.getAnnotations().get(Relationship.class);
        if (annotation != null) {
            filter.setRelationshipType(annotation.get(Relationship.TYPE, relationshipType));
            Direction direction = Direction.valueOf(annotation.get(Relationship.DIRECTION, Direction.UNDIRECTED.name()));
            filter.setRelationshipDirection(direction);
        }
        if (fieldInfo.getAnnotations().get(StartNode.class) != null) {
            filter.setRelationshipDirection(Direction.OUTGOING);
        }
        if (fieldInfo.getAnnotations().get(EndNode.class) != null) {
            filter.setRelationshipDirection(Direction.INCOMING);
        }
    }
}
Also used : StartNode(org.neo4j.ogm.annotation.StartNode) EndNode(org.neo4j.ogm.annotation.EndNode) Direction(org.neo4j.ogm.annotation.Relationship.Direction) AnnotationInfo(org.neo4j.ogm.metadata.AnnotationInfo)

Example 5 with Direction

use of org.neo4j.ogm.annotation.Relationship.Direction in project neo4j-ogm by neo4j.

the class FilteredQueryBuilder method constructRelationshipQuery.

private static StringBuilder constructRelationshipQuery(String type, Iterable<Filter> filters, Map<String, Object> properties) {
    // Filters are created in 3 steps: For deep nested filter, the improved version
    // NodeQueryBuilder is used. For the others the old approach still applies.
    FiltersAtStartNode outgoingDeepNestedFilters = new FiltersAtStartNode();
    FiltersAtStartNode incomingDeepNestedFilters = new FiltersAtStartNode();
    FiltersAtStartNode outgoingFilters = new FiltersAtStartNode();
    FiltersAtStartNode incomingFilters = new FiltersAtStartNode();
    List<Filter> relationshipFilters = new ArrayList<>();
    Direction initialDirection = null;
    for (Filter filter : filters) {
        if (filter.isNested() || filter.isDeepNested()) {
            if (filter.isDeepNested()) {
                List<Filter.NestedPathSegment> nestedPath = filter.getNestedPath();
                Filter.NestedPathSegment firstNestedPathSegment = nestedPath.get(0);
                filter.setOwnerEntityType(firstNestedPathSegment.getPropertyType());
                FiltersAtStartNode target;
                if (Relationship.Direction.OUTGOING == firstNestedPathSegment.getRelationshipDirection()) {
                    target = outgoingDeepNestedFilters;
                } else {
                    target = incomingDeepNestedFilters;
                }
                Filter.NestedPathSegment[] newPath = new Filter.NestedPathSegment[nestedPath.size() - 1];
                if (nestedPath.size() > 1) {
                    // The first element will represent the owning entity, so we need to get rid of it.
                    nestedPath.subList(1, nestedPath.size()).toArray(newPath);
                } else {
                    // The list of deep nested filters need an anchor only for relationships with one
                    // nested segments.
                    target.startNodeLabel = firstNestedPathSegment.getNestedEntityTypeLabel();
                }
                filter.setNestedPath(newPath);
                target.content.add(filter);
                if (initialDirection == null) {
                    initialDirection = firstNestedPathSegment.getRelationshipDirection();
                }
            } else {
                FiltersAtStartNode target;
                Direction relationshipDirection = filter.getRelationshipDirection();
                if (Relationship.OUTGOING == relationshipDirection) {
                    target = outgoingFilters;
                } else {
                    target = incomingFilters;
                }
                if (initialDirection == null) {
                    initialDirection = filter.getRelationshipDirection();
                }
                addFilterToList(target, filter);
            }
        } else {
            if (relationshipFilters.size() == 0) {
                filter.setBooleanOperator(BooleanOperator.NONE);
            } else {
                if (filter.getBooleanOperator().equals(BooleanOperator.NONE)) {
                    throw new MissingOperatorException("BooleanOperator missing for filter with property name " + filter.getPropertyName());
                }
            }
            relationshipFilters.add(filter);
        }
    }
    StringBuilder query = new StringBuilder();
    boolean outgoingDeepNested = !outgoingDeepNestedFilters.content.isEmpty();
    if (outgoingDeepNested) {
        NodeQueryBuilder nqb = new NodeQueryBuilder(outgoingDeepNestedFilters.startNodeLabel, outgoingDeepNestedFilters.content, "n");
        FilteredQuery filteredQuery = nqb.build();
        query.append(filteredQuery.statement()).append(" ");
        properties.putAll(filteredQuery.parameters());
    }
    if (!incomingDeepNestedFilters.content.isEmpty()) {
        NodeQueryBuilder nqb = new NodeQueryBuilder(incomingDeepNestedFilters.startNodeLabel, incomingDeepNestedFilters.content, outgoingDeepNested ? "m" : "n");
        FilteredQuery filteredQuery = nqb.build();
        query.append(filteredQuery.statement()).append(" ");
        if (outgoingDeepNested) {
            query.append(", n ");
        }
        properties.putAll(filteredQuery.parameters());
    }
    createNodeMatchSubquery(properties, outgoingFilters, query, "n");
    createNodeMatchSubquery(properties, incomingFilters, query, "m");
    createRelationSubquery(type, properties, relationshipFilters, query, initialDirection);
    return query;
}
Also used : ArrayList(java.util.ArrayList) Direction(org.neo4j.ogm.annotation.Relationship.Direction) MissingOperatorException(org.neo4j.ogm.exception.core.MissingOperatorException) Filter(org.neo4j.ogm.cypher.Filter)

Aggregations

Direction (org.neo4j.ogm.annotation.Relationship.Direction)6 ClassInfo (org.neo4j.ogm.metadata.ClassInfo)3 ArrayList (java.util.ArrayList)2 FieldInfo (org.neo4j.ogm.metadata.FieldInfo)2 EndNode (org.neo4j.ogm.annotation.EndNode)1 StartNode (org.neo4j.ogm.annotation.StartNode)1 MappedRelationship (org.neo4j.ogm.context.MappedRelationship)1 Filter (org.neo4j.ogm.cypher.Filter)1 CompileContext (org.neo4j.ogm.cypher.compiler.CompileContext)1 InvalidRelationshipTargetException (org.neo4j.ogm.exception.core.InvalidRelationshipTargetException)1 MissingOperatorException (org.neo4j.ogm.exception.core.MissingOperatorException)1 AnnotationInfo (org.neo4j.ogm.metadata.AnnotationInfo)1