Search in sources :

Example 1 with CompileContext

use of org.neo4j.ogm.cypher.compiler.CompileContext in project neo4j-ogm by neo4j.

the class EntityGraphMapper method mapEntity.

/**
 * Builds Cypher to save the specified object and all its composite objects into the graph database.
 *
 * @param entity The object to persist into the graph database as a node
 * @return The "root" node of the object graph that matches
 */
private NodeBuilder mapEntity(Object entity, int horizon) {
    // if this object is transient it won't have a classinfo, and isn't persistable
    ClassInfo classInfo = metaData.classInfo(entity);
    if (classInfo == null) {
        return null;
    }
    CompileContext context = compiler.context();
    NodeBuilder nodeBuilder = context.visitedNode(entity);
    if (context.visited(entity, horizon)) {
        LOGGER.debug("already visited: {}", entity);
        return nodeBuilder;
    }
    if (nodeBuilder == null) {
        nodeBuilder = newNodeBuilder(entity, horizon);
        if (!isWriteProtected(WriteProtectionTarget.PROPERTIES, entity)) {
            updateNode(entity, context, nodeBuilder);
        }
    }
    if (horizon != 0) {
        mapEntityReferences(entity, nodeBuilder, horizon - 1);
    } else {
        LOGGER.debug("at horizon 0: {} ", entity);
    }
    return nodeBuilder;
}
Also used : NodeBuilder(org.neo4j.ogm.cypher.compiler.NodeBuilder) CompileContext(org.neo4j.ogm.cypher.compiler.CompileContext) ClassInfo(org.neo4j.ogm.metadata.ClassInfo)

Example 2 with CompileContext

use of org.neo4j.ogm.cypher.compiler.CompileContext in project neo4j-ogm by neo4j.

the class EntityGraphMapper method mapRelatedEntity.

/**
 * Attempts to build a simple directed relationship in the graph between
 * two objects represented as srcEntity and tgtEntity. This function recursively calls mapEntity on the
 * target entity first before attempting to create the relationship. In this way, the object graph
 * is traversed in depth-first order, and the relationships between the leaf nodes are created
 * first.
 *
 * @param srcNodeBuilder      a {@link NodeBuilder} that knows how to create cypher phrases about nodes
 * @param relationshipBuilder a {@link RelationshipBuilder} that knows how to create cypher phrases about relationships
 * @param horizon             a value representing how deep we are mapping
 * @param relNodes            {@link EntityGraphMapper.RelationshipNodes} representing the nodes at the end of this relationship
 */
private void mapRelatedEntity(NodeBuilder srcNodeBuilder, RelationshipBuilder relationshipBuilder, int level, int horizon, RelationshipNodes relNodes) {
    // context.visited fails if the class isn't a mapped class, so we have to check this first, even if mapEntity will do it again
    ClassInfo classInfo = metaData.classInfo(relNodes.target);
    if (classInfo == null) {
        return;
    }
    CompileContext context = compiler.context();
    boolean alreadyVisitedNode = context.visited(relNodes.target, horizon);
    boolean selfReferentialUndirectedRelationship = relationshipBuilder.hasDirection(Direction.UNDIRECTED) && relNodes.source.getClass() == relNodes.target.getClass();
    boolean relationshipFromExplicitlyMappedObject = level == 1;
    // Map this entity (mapEntity checks whether the entity has been visited before)
    NodeBuilder tgtNodeBuilder = mapEntity(relNodes.target, horizon);
    // - or the relationships is defined on an object being explicitly mapped
    if (!alreadyVisitedNode || !selfReferentialUndirectedRelationship || relationshipFromExplicitlyMappedObject) {
        LOGGER.debug("trying to map relationship between {} and {}", relNodes.source, relNodes.target);
        relNodes.targetId = mappingContext.nativeId(relNodes.target);
        updateRelationship(context, srcNodeBuilder, tgtNodeBuilder, relationshipBuilder, relNodes);
    }
}
Also used : NodeBuilder(org.neo4j.ogm.cypher.compiler.NodeBuilder) CompileContext(org.neo4j.ogm.cypher.compiler.CompileContext) ClassInfo(org.neo4j.ogm.metadata.ClassInfo)

Example 3 with CompileContext

use of org.neo4j.ogm.cypher.compiler.CompileContext in project neo4j-ogm by neo4j.

the class EntityGraphMapper method deleteObsoleteRelationships.

/**
 * Detects object references (including from lists) that have been deleted in the domain.
 * These must be persisted as explicit requests to delete the corresponding relationship in the graph
 */
private void deleteObsoleteRelationships() {
    CompileContext context = compiler.context();
    Map<Long, Object> snapshotOfKnownRelationshipEntities = mappingContext.getSnapshotOfRelationshipEntityRegister();
    Iterator<MappedRelationship> mappedRelationshipIterator = mappingContext.getRelationships().iterator();
    while (mappedRelationshipIterator.hasNext()) {
        MappedRelationship mappedRelationship = mappedRelationshipIterator.next();
        // means the user has deleted the relationship
        if (!context.removeRegisteredRelationship(mappedRelationship)) {
            LOGGER.debug("context-del: {}", mappedRelationship);
            // tell the compiler to prepare a statement that will delete the relationship from the graph
            RelationshipBuilder builder = compiler.unrelate(mappedRelationship.getStartNodeId(), mappedRelationship.getRelationshipType(), mappedRelationship.getEndNodeId(), mappedRelationship.getRelationshipId());
            Object entity = snapshotOfKnownRelationshipEntities.get(mappedRelationship.getRelationshipId());
            if (entity != null) {
                ClassInfo classInfo = metaData.classInfo(entity);
                if (classInfo.hasVersionField()) {
                    FieldInfo field = classInfo.getVersionField();
                    builder.setVersionProperty(field.propertyName(), (Long) field.read(entity));
                }
            }
            // remove all nodes that are referenced by this relationship in the mapping context
            // this will ensure that stale versions of these objects don't exist
            clearRelatedObjects(mappedRelationship.getStartNodeId());
            clearRelatedObjects(mappedRelationship.getEndNodeId());
            // finally remove the relationship from the mapping context
            // mappingContext.removeRelationship(mappedRelationship);
            mappedRelationshipIterator.remove();
        }
    }
}
Also used : CompileContext(org.neo4j.ogm.cypher.compiler.CompileContext) FieldInfo(org.neo4j.ogm.metadata.FieldInfo) RelationshipBuilder(org.neo4j.ogm.cypher.compiler.RelationshipBuilder) ClassInfo(org.neo4j.ogm.metadata.ClassInfo)

Example 4 with CompileContext

use of org.neo4j.ogm.cypher.compiler.CompileContext in project neo4j-ogm by neo4j.

the class RequestExecutor method executeSave.

/**
 * Execute a save request.
 * Decides how the request is split depending upon characteristics of what is to be saved.
 * Processes the response(s) and updates the mapping context.
 *
 * @param context the CompileContext for this request
 */
public void executeSave(CompileContext context) {
    Compiler compiler = context.getCompiler();
    compiler.useStatementFactory(new RowStatementFactory());
    List<ReferenceMapping> entityReferenceMappings = new ArrayList<>();
    List<ReferenceMapping> relReferenceMappings = new ArrayList<>();
    boolean forceTx = compiler.updateNodesStatements().stream().anyMatch(st -> st.optimisticLockingConfig().isPresent()) || compiler.updateRelationshipStatements().stream().anyMatch(st -> st.optimisticLockingConfig().isPresent());
    session.doInTransaction(() -> {
        // we must create the new nodes first, and then use their node IDs when creating relationships between them
        if (compiler.hasStatementsDependentOnNewNodes()) {
            // execute the statements to create new nodes. The ids will be returned
            // and will be used in subsequent statements that refer to these new nodes.
            executeStatements(context, entityReferenceMappings, relReferenceMappings, compiler.createNodesStatements());
            List<Statement> statements = new ArrayList<>();
            statements.addAll(compiler.createRelationshipsStatements());
            statements.addAll(compiler.updateNodesStatements());
            statements.addAll(compiler.updateRelationshipStatements());
            statements.addAll(compiler.deleteRelationshipStatements());
            statements.addAll(compiler.deleteRelationshipEntityStatements());
            executeStatements(context, entityReferenceMappings, relReferenceMappings, statements);
        } else {
            // only update / delete statements
            List<Statement> statements = compiler.getAllStatements();
            executeStatements(context, entityReferenceMappings, relReferenceMappings, statements);
        }
    }, forceTx, Transaction.Type.READ_WRITE);
    // Update the mapping context now that the request is successful
    updateNodeEntities(context, entityReferenceMappings);
    updateRelationshipEntities(context, relReferenceMappings);
    updateRelationships(context, relReferenceMappings);
}
Also used : MappedRelationship(org.neo4j.ogm.context.MappedRelationship) RelationshipEntity(org.neo4j.ogm.annotation.RelationshipEntity) AbstractTransaction(org.neo4j.ogm.transaction.AbstractTransaction) Logger(org.slf4j.Logger) LoggerFactory(org.slf4j.LoggerFactory) Response(org.neo4j.ogm.response.Response) HashMap(java.util.HashMap) CompileContext(org.neo4j.ogm.cypher.compiler.CompileContext) Neo4jSession(org.neo4j.ogm.session.Neo4jSession) MappingContext(org.neo4j.ogm.context.MappingContext) Statement(org.neo4j.ogm.request.Statement) ArrayList(java.util.ArrayList) List(java.util.List) RowModel(org.neo4j.ogm.model.RowModel) Map(java.util.Map) Compiler(org.neo4j.ogm.cypher.compiler.Compiler) ClassInfo(org.neo4j.ogm.metadata.ClassInfo) Transaction(org.neo4j.ogm.transaction.Transaction) EntityUtils(org.neo4j.ogm.utils.EntityUtils) TransientRelationship(org.neo4j.ogm.context.TransientRelationship) Compiler(org.neo4j.ogm.cypher.compiler.Compiler) Statement(org.neo4j.ogm.request.Statement) ArrayList(java.util.ArrayList)

Example 5 with CompileContext

use of org.neo4j.ogm.cypher.compiler.CompileContext in project neo4j-ogm by neo4j.

the class MergeWithPrimaryIndexTests method mapAndCompile.

private Compiler mapAndCompile(Object object) {
    CompileContext context = this.mapper.map(object);
    Compiler compiler = context.getCompiler();
    compiler.useStatementFactory(new RowStatementFactory());
    return compiler;
}
Also used : Compiler(org.neo4j.ogm.cypher.compiler.Compiler) RowStatementFactory(org.neo4j.ogm.session.request.RowStatementFactory) CompileContext(org.neo4j.ogm.cypher.compiler.CompileContext)

Aggregations

CompileContext (org.neo4j.ogm.cypher.compiler.CompileContext)10 ClassInfo (org.neo4j.ogm.metadata.ClassInfo)7 ArrayList (java.util.ArrayList)3 Compiler (org.neo4j.ogm.cypher.compiler.Compiler)3 NodeBuilder (org.neo4j.ogm.cypher.compiler.NodeBuilder)3 FieldInfo (org.neo4j.ogm.metadata.FieldInfo)3 Neo4jSession (org.neo4j.ogm.session.Neo4jSession)3 HashMap (java.util.HashMap)2 List (java.util.List)2 Map (java.util.Map)2 RelationshipEntity (org.neo4j.ogm.annotation.RelationshipEntity)2 MappedRelationship (org.neo4j.ogm.context.MappedRelationship)2 MappingContext (org.neo4j.ogm.context.MappingContext)2 TransientRelationship (org.neo4j.ogm.context.TransientRelationship)2 RelationshipBuilder (org.neo4j.ogm.cypher.compiler.RelationshipBuilder)2 RowModel (org.neo4j.ogm.model.RowModel)2 Statement (org.neo4j.ogm.request.Statement)2 Response (org.neo4j.ogm.response.Response)2 AbstractTransaction (org.neo4j.ogm.transaction.AbstractTransaction)2 Transaction (org.neo4j.ogm.transaction.Transaction)2