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

com.raylabz.bytesurge.stream.ReadStream Maven / Gradle / Ivy

There is a newer version: 0.0.5
Show newest version
package com.raylabz.bytesurge.stream;

import com.raylabz.bytesurge.container.*;
import com.raylabz.bytesurge.schema.ArraySchema;
import com.raylabz.bytesurge.schema.ObjectSchema;
import com.raylabz.bytesurge.schema.Schema;
import com.raylabz.bytesurge.schema.SchemaType;

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

/**
 * A stream used to read data based on a particular schema.
 * @author Nicos Kasenides - RayLabz
 * @version 0.0.1
 */
public class ReadStream extends Stream {

    /**
     * The raw bytes of this ReadStream.
     */
    protected byte[] bytes;

    /**
     * A ByteArrayInputStream, used to read bytes.
     */
    protected ByteArrayInputStream byteArrayInputStream;

    /**
     * A DataInputStream, used to read primitive types.
     */
    protected DataInputStream stream;

    /**
     * Constructs a ReadStream.
     * @param schema The schema of the stream.
     * @param bytes Raw bytes to use as data.
     */
    public ReadStream(Schema schema, byte[] bytes) {
        super(schema);
        this.bytes = bytes;
        byteArrayInputStream = new ByteArrayInputStream(bytes);
        stream = new DataInputStream(byteArrayInputStream);
    }

    /**
     * Reads an integer from the stream.
     * @return Returns an integer.
     * @throws IOException when the data is not of the expected type (according to the schema), or when there is no more data to read.
     */
    public int readInt() throws IOException {
        if (!schemaQueue.isEmpty()) {
            final Schema expectedSchema = schemaQueue.poll();
            if (expectedSchema.getSchemaType() == SchemaType.INT) {
                return stream.readInt();
            }
            throw new IOException("Cannot read incoming message. Schema expected " + expectedSchema.getSchemaType() + " but attempted to read INT.");
        }
        throw new IOException("Cannot read data from message - unexpected value (end of schema).");
    }

    /**
     * Reads a short from the stream.
     * @return Returns a short.
     * @throws IOException when the data is not of the expected type (according to the schema), or when there is no more data to read.
     */
    public short readShort() throws IOException {
        if (!schemaQueue.isEmpty()) {
            final Schema expectedSchema = schemaQueue.poll();
            if (expectedSchema.getSchemaType() == SchemaType.SHORT) {
                return stream.readShort();
            }
            throw new IOException("Cannot read incoming message. Schema expected " + expectedSchema.getSchemaType() + " but attempted to read SHORT.");
        }
        throw new IOException("Cannot read data from message - unexpected value (end of schema).");
    }

    /**
     * Reads a long from the stream.
     * @return Returns a long.
     * @throws IOException when the data is not of the expected type (according to the schema), or when there is no more data to read.
     */
    public long readLong() throws IOException {
        if (!schemaQueue.isEmpty()) {
            final Schema expectedSchema = schemaQueue.poll();
            if (expectedSchema.getSchemaType() == SchemaType.LONG) {
                return stream.readLong();
            }
            throw new IOException("Cannot read incoming message. Schema expected " + expectedSchema.getSchemaType() + " but attempted to read LONG.");
        }
        throw new IOException("Cannot read data from message - unexpected value (end of schema).");
    }

    /**
     * Reads a float from the stream.
     * @return Returns a float.
     * @throws IOException when the data is not of the expected type (according to the schema), or when there is no more data to read.
     */
    public float readFloat() throws IOException {
        if (!schemaQueue.isEmpty()) {
            final Schema expectedSchema = schemaQueue.poll();
            if (expectedSchema.getSchemaType() == SchemaType.FLOAT) {
                return stream.readFloat();
            }
            throw new IOException("Cannot read incoming message. Schema expected " + expectedSchema.getSchemaType() + " but attempted to read FLOAT.");
        }
        throw new IOException("Cannot read data from message - unexpected value (end of schema).");
    }

    /**
     * Reads a double from the stream.
     * @return Returns a double.
     * @throws IOException when the data is not of the expected type (according to the schema), or when there is no more data to read.
     */
    public double readDouble() throws IOException {
        if (!schemaQueue.isEmpty()) {
            final Schema expectedSchema = schemaQueue.poll();
            if (expectedSchema.getSchemaType() == SchemaType.DOUBLE) {
                return stream.readDouble();
            }
            throw new IOException("Cannot read incoming message. Schema expected " + expectedSchema.getSchemaType() + " but attempted to read DOUBLE.");
        }
        throw new IOException("Cannot read data from message - unexpected value (end of schema).");
    }

    /**
     * Reads a character from the stream.
     * @return Returns a character.
     * @throws IOException when the data is not of the expected type (according to the schema), or when there is no more data to read.
     */
    public char readChar() throws IOException {
        if (!schemaQueue.isEmpty()) {
            final Schema expectedSchema = schemaQueue.poll();
            if (expectedSchema.getSchemaType() == SchemaType.CHAR) {
                return stream.readChar();
            }
            throw new IOException("Cannot read incoming message. Schema expected " + expectedSchema.getSchemaType() + " but attempted to read CHAR.");
        }
        throw new IOException("Cannot read data from message - unexpected value (end of schema).");
    }

    /**
     * Reads a boolean from the stream.
     * @return Returns a boolean.
     * @throws IOException when the data is not of the expected type (according to the schema), or when there is no more data to read.
     */
    public boolean readBoolean() throws IOException {
        if (!schemaQueue.isEmpty()) {
            final Schema expectedSchema = schemaQueue.poll();
            if (expectedSchema.getSchemaType() == SchemaType.BOOLEAN) {
                return stream.readBoolean();
            }
            throw new IOException("Cannot read incoming message. Schema expected " + expectedSchema.getSchemaType() + " but attempted to read BOOLEAN.");
        }
        throw new IOException("Cannot read data from message - unexpected value (end of schema).");
    }

    /**
     * Reads a byte from the stream.
     * @return Returns a byte.
     * @throws IOException when the data is not of the expected type (according to the schema), or when there is no more data to read.
     */
    public byte readByte() throws IOException {
        if (!schemaQueue.isEmpty()) {
            final Schema expectedSchema = schemaQueue.poll();
            if (expectedSchema.getSchemaType() == SchemaType.BYTE) {
                return stream.readByte();
            }
            throw new IOException("Cannot read incoming message. Schema expected " + expectedSchema.getSchemaType() + " but attempted to read BYTE.");
        }
        throw new IOException("Cannot read data from message - unexpected value (end of schema).");
    }

    /**
     * Reads a UTF-8 formatted String from the stream.
     * @return Returns a UTF-8 formatted String.
     * @throws IOException when the data is not of the expected type (according to the schema), or when there is no more data to read.
     */
    public String readUTF8() throws IOException {
        if (!schemaQueue.isEmpty()) {
            final Schema expectedSchema = schemaQueue.poll();
            if (expectedSchema.getSchemaType() == SchemaType.UTF8) {
                return stream.readUTF();
            }
            throw new IOException("Cannot read incoming message. Schema expected " + expectedSchema.getSchemaType() + " but attempted to read UTF8.");
        }
        throw new IOException("Cannot read data from message - unexpected value (end of schema).");
    }

    /**
     * Reads an object from the stream.
     * @param objectSchema The ObjectSchema for the object to read.
     * @return Returns an ObjectContainer.
     * @throws IOException when the data is not of the expected type (according to the schema), or when there is no more data to read.
     */
    public ObjectContainer readObject(ObjectSchema objectSchema) throws IOException {
        ObjectContainer container = new ObjectContainer(objectSchema);
        for (Map.Entry entry : objectSchema.getInnerSchemas().entrySet()) {
            final String name = entry.getKey();
            final Schema s = entry.getValue();
            switch (s.getSchemaType()) {
                case SHORT:
                    container.putAttribute(name, new ShortContainer(readShort()));
                    break;
                case INT:
                    container.putAttribute(name, new IntContainer(readInt()));
                    break;
                case LONG:
                    container.putAttribute(name, new LongContainer(readLong()));
                    break;
                case FLOAT:
                    container.putAttribute(name, new FloatContainer(readFloat()));
                    break;
                case DOUBLE:
                    container.putAttribute(name, new DoubleContainer(readDouble()));
                    break;
                case CHAR:
                    container.putAttribute(name, new CharContainer(readChar()));
                    break;
                case BOOLEAN:
                    container.putAttribute(name, new BooleanContainer(readBoolean()));
                    break;
                case BYTE:
                    container.putAttribute(name, new ByteContainer(readByte()));
                    break;
                case UTF8:
                    container.putAttribute(name, new UTF8Container(readUTF8()));
                    break;
                case OBJECT:
                    ObjectSchema innerObjectSchema = (ObjectSchema) s;
                    final ObjectContainer innerObjectContainer = readObject(innerObjectSchema);
                    container.putAttribute(name, innerObjectContainer);
                    break;
                case ARRAY:
                    ArraySchema innerArraySchema = (ArraySchema) s;
                    final ArrayContainer arrayContainer = readArray(innerArraySchema);
                    container.putAttribute(name, arrayContainer);
                    break;
            }
        }
        return container;
    }

    /**
     * Reads an array from the stream.
     * @param arraySchema The ArraySchema for the array to read
     * @return Returns an ArrayContainer.
     * @throws IOException when the data is not of the expected type (according to the schema), or when there is no more data to read.
     */
    public ArrayContainer readArray(ArraySchema arraySchema) throws IOException {
        final int numOfElements = readInt();
        final byte arrayType = readByte();
        if (arrayType == arraySchema.getElementSchema().getSchemaType().getValue()) {
            ArrayContainer container = new ArrayContainer(arraySchema);
            for (int i = 0; i < arraySchema.getSize(); i++) {
                switch (arraySchema.getElementSchema().getSchemaType()) {
                    case SHORT:
                        ShortContainer shortContainer = new ShortContainer(readShort());
                        container.addElement(shortContainer);
                        break;
                    case INT:
                        IntContainer intContainer = new IntContainer(readInt());
                        container.addElement(intContainer);
                        break;
                    case LONG:
                        LongContainer longContainer = new LongContainer(readLong());
                        container.addElement(longContainer);
                        break;
                    case FLOAT:
                        FloatContainer floatContainer = new FloatContainer(readFloat());
                        container.addElement(floatContainer);
                        break;
                    case DOUBLE:
                        DoubleContainer doubleContainer = new DoubleContainer(readDouble());
                        container.addElement((doubleContainer));
                        break;
                    case CHAR:
                        CharContainer charContainer = new CharContainer(readChar());
                        container.addElement(charContainer);
                        break;
                    case BOOLEAN:
                        BooleanContainer booleanContainer = new BooleanContainer(readBoolean());
                        container.addElement(booleanContainer);
                        break;
                    case BYTE:
                        ByteContainer byteContainer = new ByteContainer(readByte());
                        container.addElement(byteContainer);
                        break;
                    case UTF8:
                        UTF8Container utf8Container = new UTF8Container(readUTF8());
                        container.addElement(utf8Container);
                        break;
                    case OBJECT:
                        ObjectSchema objectSchema = (ObjectSchema) arraySchema.getElementSchema();
                        ObjectContainer objectContainer = readObject(objectSchema);
                        container.addElement(objectContainer);
                        break;
                    case ARRAY:
                        ArraySchema innerArraySchema = (ArraySchema) arraySchema.getElementSchema();
                        ArrayContainer innerArrayContainer = readArray(innerArraySchema);
                        container.addElement(innerArrayContainer);
                        break;
                }
            }
            return container;
        }
        else {
            throw new IOException("Cannot read data from message - expected " + arraySchema.getElementSchema().getSchemaType() + " array type but got " + SchemaType.fromByte(arrayType));
        }
    }

    /**
     * Reads a short array from the stream.
     * @return Returns an array of short.
     * @throws IOException when the data is not of the expected type (according to the schema), or when there is no more data to read.
     */
    public short[] readShortArray() throws IOException {
        final int numOfElements = readInt();
        final byte arrayType = readByte();

        if (arrayType == SchemaType.SHORT.getValue()) {
            final short[] values = new short[numOfElements];
            for (int i = 0; i < numOfElements; i++) {
                values[i] = readShort();
            }
            return values;
        }
        else {
            throw new IOException("Cannot read data from message - expected " + SchemaType.SHORT.getValue() + " array type but got " + arrayType);
        }
    }

    /**
     * Reads an integer array from the stream.
     * @return Returns an array of integer.
     * @throws IOException when the data is not of the expected type (according to the schema), or when there is no more data to read.
     */
    public int[] readIntArray() throws IOException {
        final int numOfElements = readInt();
        final byte arrayType = readByte();

        if (arrayType == SchemaType.INT.getValue()) {
            final int[] values = new int[numOfElements];
            for (int i = 0; i < numOfElements; i++) {
                values[i] = readInt();
            }
            return values;
        }
        else {
            throw new IOException("Cannot read data from message - expected " + SchemaType.INT.getValue() + " array type but got " + arrayType);
        }
    }

    /**
     * Reads a long array from the stream.
     * @return Returns an array of long.
     * @throws IOException when the data is not of the expected type (according to the schema), or when there is no more data to read.
     */
    public long[] readLongArray() throws IOException {
        final int numOfElements = readInt();
        final byte arrayType = readByte();

        if (arrayType == SchemaType.LONG.getValue()) {
            final long[] values = new long[numOfElements];
            for (int i = 0; i < numOfElements; i++) {
                values[i] = readLong();
            }
            return values;
        }
        else {
            throw new IOException("Cannot read data from message - expected " + SchemaType.LONG.getValue() + " array type but got " + arrayType);
        }
    }

    /**
     * Reads a float array from the stream.
     * @return Returns an array of float.
     * @throws IOException when the data is not of the expected type (according to the schema), or when there is no more data to read.
     */
    public float[] readFloatArray() throws IOException {
        final int numOfElements = readInt();
        final byte arrayType = readByte();

        if (arrayType == SchemaType.FLOAT.getValue()) {
            final float[] values = new float[numOfElements];
            for (int i = 0; i < numOfElements; i++) {
                values[i] = readFloat();
            }
            return values;
        }
        else {
            throw new IOException("Cannot read data from message - expected " + SchemaType.FLOAT.getValue() + " array type but got " + arrayType);
        }
    }

    /**
     * Reads a double array from the stream.
     * @return Returns an array of double.
     * @throws IOException when the data is not of the expected type (according to the schema), or when there is no more data to read.
     */
    public double[] readDoubleArray() throws IOException {
        final int numOfElements = readInt();
        final byte arrayType = readByte();

        if (arrayType == SchemaType.DOUBLE.getValue()) {
            final double[] values = new double[numOfElements];
            for (int i = 0; i < numOfElements; i++) {
                values[i] = readDouble();
            }
            return values;
        }
        else {
            throw new IOException("Cannot read data from message - expected " + SchemaType.DOUBLE.getValue() + " array type but got " + arrayType);
        }
    }

    /**
     * Reads a character array from the stream.
     * @return Returns an array of character.
     * @throws IOException when the data is not of the expected type (according to the schema), or when there is no more data to read.
     */
    public char[] readCharArray() throws IOException {
        final int numOfElements = readInt();
        final byte arrayType = readByte();

        if (arrayType == SchemaType.CHAR.getValue()) {
            final char[] values = new char[numOfElements];
            for (int i = 0; i < numOfElements; i++) {
                values[i] = readChar();
            }
            return values;
        }
        else {
            throw new IOException("Cannot read data from message - expected " + SchemaType.CHAR.getValue() + " array type but got " + arrayType);
        }
    }

    /**
     * Reads a boolean array from the stream.
     * @return Returns an array of boolean.
     * @throws IOException when the data is not of the expected type (according to the schema), or when there is no more data to read.
     */
    public boolean[] readBooleanArray() throws IOException {
        final int numOfElements = readInt();
        final byte arrayType = readByte();

        if (arrayType == SchemaType.BOOLEAN.getValue()) {
            final boolean[] values = new boolean[numOfElements];
            for (int i = 0; i < numOfElements; i++) {
                values[i] = readBoolean();
            }
            return values;
        }
        else {
            throw new IOException("Cannot read data from message - expected " + SchemaType.BOOLEAN.getValue() + " array type but got " + arrayType);
        }
    }

    /**
     * Reads a byte array from the stream.
     * @return Returns an array of byte.
     * @throws IOException when the data is not of the expected type (according to the schema), or when there is no more data to read.
     */
    public byte[] readByteArray() throws IOException {
        final int numOfElements = readInt();
        final byte arrayType = readByte();

        if (arrayType == SchemaType.BYTE.getValue()) {
            final byte[] values = new byte[numOfElements];
            for (int i = 0; i < numOfElements; i++) {
                values[i] = readByte();
            }
            return values;
        }
        else {
            throw new IOException("Cannot read data from message - expected " + SchemaType.BYTE.getValue() + " array type but got " + arrayType);
        }
    }

    /**
     * Reads a UTF8-formatted String array from the stream.
     * @return Returns an array of UTF8-formatted String.
     * @throws IOException when the data is not of the expected type (according to the schema), or when there is no more data to read.
     */
    public String[] readUTF8Array() throws IOException {
        final int numOfElements = readInt();
        final byte arrayType = readByte();

        if (arrayType == SchemaType.UTF8.getValue()) {
            final String[] values = new String[numOfElements];
            for (int i = 0; i < numOfElements; i++) {
                values[i] = readUTF8();
            }
            return values;
        }
        else {
            throw new IOException("Cannot read data from message - expected " + SchemaType.UTF8.getValue() + " array type but got " + arrayType);
        }
    }

    /**
     * Closes the ReadStream.
     * @throws IOException thrown when the stream cannot be closed.
     */
    public void close() throws IOException {
        stream.close();
        byteArrayInputStream.close();
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy