All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.neo4j.bolt.v1.messaging.BoltResponseMessageWriter Maven / Gradle / Ivy

/*
 * Copyright (c) 2002-2017 "Neo Technology,"
 * Network Engine for Objects in Lund AB [http://neotechnology.com]
 *
 * This file is part of Neo4j.
 *
 * Neo4j is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see .
 */
package org.neo4j.bolt.v1.messaging;

import java.io.IOException;
import java.util.Map;

import org.neo4j.bolt.v1.runtime.spi.Record;
import org.neo4j.kernel.api.exceptions.Status;

import static org.neo4j.bolt.v1.messaging.BoltResponseMessage.FAILURE;
import static org.neo4j.bolt.v1.messaging.BoltResponseMessage.IGNORED;
import static org.neo4j.bolt.v1.messaging.BoltResponseMessage.RECORD;
import static org.neo4j.bolt.v1.messaging.BoltResponseMessage.SUCCESS;

/**
 * Writer for Bolt request messages to be sent to a {@link Neo4jPack.Packer}.
 */
public class BoltResponseMessageWriter implements BoltResponseMessageHandler
{
    public static final BoltResponseMessageBoundaryHook NO_BOUNDARY_HOOK = () ->
    {
    };

    private final Neo4jPack.Packer packer;
    private final BoltResponseMessageBoundaryHook onMessageComplete;

    /**
     * @param packer            serializer to output channel
     * @param onMessageComplete invoked for each message, after it's done writing to the output
     */
    public BoltResponseMessageWriter( Neo4jPack.Packer packer, BoltResponseMessageBoundaryHook onMessageComplete )
    {
        this.packer = packer;
        this.onMessageComplete = onMessageComplete;
    }

    @Override
    public void onRecord( Record item ) throws IOException
    {
        Object[] fields = item.fields();
        packer.packStructHeader( 1, RECORD.signature() );
        packer.packListHeader( fields.length );
        for ( Object field : fields )
        {
            packer.pack( field );
        }
        onMessageComplete.onMessageComplete();

        //The record might contain unpackable values,
        //hence we must consume any errors that might
        //have occurred.
        packer.consumeError();  // TODO: find a better way
    }

    @Override
    public void onSuccess( Map metadata ) throws IOException
    {
        packer.packStructHeader( 1, SUCCESS.signature() );
        packer.packRawMap( metadata );
        onMessageComplete.onMessageComplete();
    }

    @Override
    public void onIgnored() throws IOException
    {
        packer.packStructHeader( 0, IGNORED.signature() );
        onMessageComplete.onMessageComplete();
    }

    @Override
    public void onFailure( Status status, String message ) throws IOException
    {
        packer.packStructHeader( 1, FAILURE.signature() );
        packer.packMapHeader( 2 );

        packer.pack( "code" );
        packer.pack( status.code().serialize() );

        packer.pack( "message" );
        packer.pack( message );

        onMessageComplete.onMessageComplete();
    }

    @Override
    public void onFatal( Status status, String message ) throws IOException
    {
        onFailure( status, message );
        flush();
    }

    public void flush() throws IOException
    {
        packer.flush();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy