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

org.bboxdb.networkproxy.misc.TupleStringSerializer Maven / Gradle / Ivy

There is a newer version: 1.0.0-rc3
Show newest version
/*******************************************************************************
 *
 *    Copyright (C) 2015-2018 the BBoxDB project
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 *
 *******************************************************************************/
package org.bboxdb.networkproxy.misc;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

import org.bboxdb.commons.io.DataEncoderHelper;
import org.bboxdb.commons.math.Hyperrectangle;
import org.bboxdb.misc.Const;
import org.bboxdb.storage.entity.DeletedTuple;
import org.bboxdb.storage.entity.JoinedTuple;
import org.bboxdb.storage.entity.Tuple;
import org.bboxdb.storage.util.TupleHelper;

import com.google.common.io.ByteStreams;

public class TupleStringSerializer {

	/**
	 * Write a tuple to the writer
	 * @param tuple
	 * @param writer
	 * @throws IOException
	 */
	public static void writeTuple(final Tuple tuple, final OutputStream outputStream) throws IOException {
		final byte[] tupleData = TupleStringSerializer.tupleToProxyBytes(tuple);

		outputStream.write(DataEncoderHelper.intToByteBuffer(tupleData.length).array());
		outputStream.write(tupleData);
	}

	/**
	 * Read tuple from reader
	 * @param reader
	 * @return
	 * @throws IOException
	 */
	public static Tuple readTuple(final InputStream reader) throws IOException {
		final int tupleLength = DataEncoderHelper.readIntFromStream(reader);
		final byte[] tupleBytes = new byte[tupleLength];

		ByteStreams.readFully(reader, tupleBytes);

		return proxyBytesToTuple(tupleBytes);
	}
	
	/**
	 * Write a joined tuple to the writer
	 * @param tuple
	 * @param writer
	 * @throws IOException
	 */
	public static void writeJoinedTuple(final JoinedTuple tuple, final OutputStream outputStream) throws IOException {
		final byte[] tupleData = TupleStringSerializer.joinedTupleToProxyBytes(tuple);

		outputStream.write(DataEncoderHelper.intToByteBuffer(tupleData.length).array());
		outputStream.write(tupleData);
	}

	/**
	 * Read joined from reader
	 * @param reader
	 * @return
	 * @throws IOException
	 */
	public static JoinedTuple readJoinedTuple(final InputStream reader) throws IOException {
		final int tupleLength = DataEncoderHelper.readIntFromStream(reader);
		final byte[] tupleBytes = new byte[tupleLength];

		ByteStreams.readFully(reader, tupleBytes);

		return proxyBytesToJoinedTuple(tupleBytes);
	}

	/**
	 * Convert the tuple into a string
	 * @param tuple
	 * @param sb
	 * @return
	 * @throws IOException
	 */
	public static byte[] tupleToProxyBytes(final Tuple tuple) throws IOException {
		final ByteArrayOutputStream bos = new ByteArrayOutputStream();

		final byte[] keyBytes = tuple.getKey().getBytes();
		final byte[] bboxBytes = tuple.getBoundingBox().toCompactString().getBytes();
		final byte[] dataBytes = tuple.getDataBytes();

		final int keyLength = keyBytes.length;
		final int bboxLength = bboxBytes.length;
		final int dataLength = dataBytes.length;

		bos.write(DataEncoderHelper.intToByteBuffer(keyLength).array());
		bos.write(keyBytes);
		bos.write(DataEncoderHelper.intToByteBuffer(bboxLength).array());
		bos.write(bboxBytes);
		bos.write(DataEncoderHelper.intToByteBuffer(dataLength).array());
		bos.write(dataBytes);
		bos.write(DataEncoderHelper.longToByteBuffer(tuple.getVersionTimestamp()).array());

		return bos.toByteArray();
	}
	

	/**
	 * Convert a joined tuple into the proxy representation
	 * @param joinedTuple
	 * @return
	 * @throws IOException
	 */
	public static byte[] joinedTupleToProxyBytes(final JoinedTuple joinedTuple) throws IOException {
		final ByteArrayOutputStream bos = new ByteArrayOutputStream();
		
		// Amount of tuples in the joined tuple
		final int numberOfStores = joinedTuple.getTupleStoreNames().size();
		bos.write(DataEncoderHelper.intToByteBuffer(numberOfStores).array());
		
		// Write tuple names
		for(final String tupleStoreName : joinedTuple.getTupleStoreNames()) {
			final byte[] nameBytes = tupleStoreName.getBytes();
			final int nameLength = nameBytes.length;
			bos.write(DataEncoderHelper.intToByteBuffer(nameLength).array());
			bos.write(nameBytes);
		}
		
		// Tuples
		for(final Tuple tuple : joinedTuple.getTuples()) {
			final byte[] tupleBytes = tupleToProxyBytes(tuple);
			final int tupleLength = tupleBytes.length;
			bos.write(DataEncoderHelper.intToByteBuffer(tupleLength).array());
			bos.write(tupleBytes);
		}
		
		return bos.toByteArray();
	}
	
	/**
	 * Convert the proxy string back to a tuple
	 * @param string
	 * @return
	 */
	public static Tuple proxyBytesToTuple(final byte[] bytes) throws IOException {

		try {
			if(bytes == null) {
				throw new IOException("Unable to handle a null argument");
			}

			final ByteBuffer bb = ByteBuffer.wrap(bytes);
			bb.order(Const.APPLICATION_BYTE_ORDER);

			// Key
			final int keyLength = bb.getInt();
			final byte[] keyBytes = new byte[keyLength];
			bb.get(keyBytes, 0, keyBytes.length);
			final String key = new String(keyBytes);

			// Bounding box
			final int bboxLength = bb.getInt();
			final byte[] bboxBytes = new byte[bboxLength];
			bb.get(bboxBytes, 0, bboxBytes.length);
			final String bboxString = new String(bboxBytes);
			final Hyperrectangle bbox = Hyperrectangle.fromString(bboxString);

			// Value
			final int valueLength = bb.getInt();
			final byte[] valueBytes = new byte[valueLength];
			bb.get(valueBytes, 0, valueBytes.length);

			// Version timestamp
			final long timestamp = bb.getLong();

			if(bb.hasRemaining()) {
				throw new IOException("Buffer has remaining bytes");
			}

			if(TupleHelper.isDeletedTuple(bbox, valueBytes)) {
				return new DeletedTuple(key, timestamp);
			} else {
				return new Tuple(key, bbox, valueBytes, timestamp);
			}

		} catch (BufferUnderflowException e) {
			throw new IOException(e);
		}
	}

	/**
	 * Convert the proxy bytes back into a joined tuple
	 * @param bytes
	 * @return
	 * @throws IOException
	 */
	public static JoinedTuple proxyBytesToJoinedTuple(final byte[] bytes) throws IOException {
		try {
			if(bytes == null) {
				throw new IOException("Unable to handle a null argument");
			}
	
			final ByteBuffer bb = ByteBuffer.wrap(bytes);
			bb.order(Const.APPLICATION_BYTE_ORDER);
			
			final int amountOfEntries = bb.getInt();
			
			// Read tuple store names
			final List tupleStoreNames = new ArrayList<>();
			for(int i = 0; i < amountOfEntries; i++) {
				final int nameLength = bb.getInt();
				final byte[] nameBytes = new byte[nameLength];
				bb.get(nameBytes, 0, nameBytes.length);
				final String tableName = new String(nameBytes);
				tupleStoreNames.add(tableName);
			}
			
			// Read tuples
			final List tupleList = new ArrayList<>();
			for(int i = 0; i < amountOfEntries; i++) {
				final int tupleLength = bb.getInt();
				final byte[] tupleBytes = new byte[tupleLength];
				bb.get(tupleBytes, 0, tupleBytes.length);
				final Tuple tuple = proxyBytesToTuple(tupleBytes);
				tupleList.add(tuple);
			}
			
			return new JoinedTuple(tupleList, tupleStoreNames);
		} catch (BufferUnderflowException e) {
			throw new IOException(e);
		}
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy