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

com.qwazr.database.store.ByteConverter Maven / Gradle / Ivy

There is a newer version: 1.5.0
Show newest version
/*
 * Copyright 2015-2017 Emmanuel Keller / QWAZR
 * 

* 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 com.qwazr.database.store; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.qwazr.server.ServerException; import com.qwazr.utils.CharsetUtils; import com.qwazr.utils.ObjectMappers; import com.qwazr.utils.SerializationUtils; import org.xerial.snappy.Snappy; import javax.ws.rs.core.Response; import java.io.IOException; import java.io.Serializable; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.util.ArrayList; import java.util.List; public interface ByteConverter { T convert(Object value) throws IOException; byte[] toBytes(T value) throws IOException; T toValue(byte[] bytes) throws IOException; default T toValue(ByteBuffer byteBuffer) throws IOException { final byte[] bytes = new byte[byteBuffer.remaining()]; System.arraycopy(byteBuffer.array(), byteBuffer.arrayOffset(), bytes, 0, bytes.length); return toValue(bytes); } default void forEach(T value, ValueConsumer consumer) { throw new ServerException(Response.Status.NOT_ACCEPTABLE, "Function not implemented"); } default void forFirst(T value, ValueConsumer consumer) { throw new ServerException(Response.Status.NOT_ACCEPTABLE, "Function not implemented"); } abstract class AbstractNumberConverter implements ByteConverter { final public T convert(Object value) throws IOException { if (value == null) return null; if (value instanceof Number) return fromNumber((Number) value); else if (value instanceof String) { try { return fromString((String) value); } catch (NumberFormatException e) { // Handled next } } throw new ServerException(Response.Status.NOT_ACCEPTABLE, "Cannot convert " + value.getClass() + " to a number"); } abstract T fromNumber(Number number) throws IOException; abstract T fromString(String string) throws IOException; } class IntegerByteConverter extends AbstractNumberConverter { public final static IntegerByteConverter INSTANCE = new IntegerByteConverter(); @Override final public byte[] toBytes(final Integer value) { return ByteBuffer.allocate(4).putInt(value).array(); } @Override final Integer fromString(final String string) { return Integer.parseInt(string); } @Override final Integer fromNumber(final Number number) { return number.intValue(); } @Override final public Integer toValue(final byte[] bytes) { return ByteBuffer.wrap(bytes).getInt(); } @Override final public Integer toValue(final ByteBuffer byteBuffer) { return byteBuffer.getInt(); } @Override final public void forEach(final Integer value, final ValueConsumer consumer) { if (value != null) consumer.consume(value); } @Override final public void forFirst(final Integer value, final ValueConsumer consumer) { forEach(value, consumer); } } class LongByteConverter extends AbstractNumberConverter { public final static LongByteConverter INSTANCE = new LongByteConverter(); @Override final public byte[] toBytes(final Long value) { return ByteBuffer.allocate(8).putLong(value).array(); } @Override final Long fromString(final String string) { return Long.parseLong(string); } @Override final Long fromNumber(final Number number) { return number.longValue(); } @Override final public Long toValue(final byte[] bytes) { return ByteBuffer.wrap(bytes).getLong(); } @Override final public Long toValue(final ByteBuffer byteBuffer) { return byteBuffer.getLong(); } @Override final public void forEach(final Long value, final ValueConsumer consumer) { if (value != null) consumer.consume(value); } @Override final public void forFirst(Long value, ValueConsumer consumer) { forEach(value, consumer); } } class DoubleByteConverter extends AbstractNumberConverter { public final static DoubleByteConverter INSTANCE = new DoubleByteConverter(); @Override final public byte[] toBytes(Double value) { return ByteBuffer.allocate(8).putDouble(value).array(); } @Override final Double fromString(final String string) { return Double.parseDouble(string); } @Override final Double fromNumber(final Number number) { return number.doubleValue(); } @Override final public Double toValue(byte[] bytes) { return ByteBuffer.wrap(bytes).getDouble(); } @Override final public Double toValue(final ByteBuffer byteBuffer) { return byteBuffer.getDouble(); } @Override final public void forEach(final Double value, final ValueConsumer consumer) { if (value != null) consumer.consume(value); } @Override final public void forFirst(final Double value, final ValueConsumer consumer) { forEach(value, consumer); } } class StringByteConverter implements ByteConverter { public final static StringByteConverter INSTANCE = new StringByteConverter(); @Override final public String convert(final Object value) { return value instanceof String ? (String) value : value.toString(); } @Override final public byte[] toBytes(final String value) { return CharsetUtils.encodeUtf8(value.toString()); } @Override final public String toValue(final byte[] bytes) { return CharsetUtils.decodeUtf8(bytes); } @Override final public String toValue(final ByteBuffer byteBuffer) throws IOException { return CharsetUtils.decodeUtf8(byteBuffer); } @Override final public void forEach(final String value, final ValueConsumer consumer) { if (value != null) consumer.consume(value); } @Override final public void forFirst(final String value, final ValueConsumer consumer) { forEach(value, consumer); } } abstract class AbstractCastConvert implements ByteConverter { @Override final public T convert(final Object value) { return (T) value; } } class JsonByteConverter extends AbstractCastConvert { private final Class objectClass; public JsonByteConverter(Class objectClass) { this.objectClass = objectClass; } @Override final public byte[] toBytes(T value) throws JsonProcessingException { return ObjectMappers.JSON.writeValueAsBytes(value); } @Override final public T toValue(byte[] bytes) throws IOException { return ObjectMappers.JSON.readValue(bytes, objectClass); } } final class JsonTypeByteConverter extends AbstractCastConvert { private final TypeReference typeReference; public JsonTypeByteConverter(TypeReference typeReference) { this.typeReference = typeReference; } @Override final public byte[] toBytes(Object value) throws JsonProcessingException { return ObjectMappers.JSON.writeValueAsBytes(value); } @Override final public T toValue(byte[] bytes) throws IOException { return ObjectMappers.JSON.readValue(bytes, typeReference); } } final class SerializableByteConverter extends AbstractCastConvert { @Override final public byte[] toBytes(T value) throws IOException { return SerializationUtils.toDefaultBytes(value); } @Override final public T toValue(byte[] bytes) throws IOException { try { return (T) SerializationUtils.fromDefaultBytes(bytes); } catch (ClassNotFoundException e) { throw new IOException(e); } } } class IntArrayByteConverter extends AbstractCastConvert { public final static IntArrayByteConverter INSTANCE = new IntArrayByteConverter(); @Override final public byte[] toBytes(int[] intArray) throws IOException { return Snappy.compress(intArray); } @Override final public int[] toValue(byte[] compressedByteArray) throws IOException { if (compressedByteArray == null) return null; return Snappy.uncompressIntArray(compressedByteArray); } @Override final public void forEach(int[] values, final ValueConsumer consumer) { if (values == null) return; for (int value : values) consumer.consume(value); } @Override final public void forFirst(int[] values, ValueConsumer consumer) { if (values == null || values.length == 0) return; consumer.consume(values[0]); } } class LongArrayByteConverter extends AbstractCastConvert { public final static LongArrayByteConverter INSTANCE = new LongArrayByteConverter(); @Override final public byte[] toBytes(long[] intArray) throws IOException { return Snappy.compress(intArray); } @Override final public long[] toValue(byte[] compressedByteArray) throws IOException { if (compressedByteArray == null) return null; return Snappy.uncompressLongArray(compressedByteArray); } @Override final public void forEach(long[] values, final ValueConsumer consumer) { if (values == null) return; for (long value : values) consumer.consume(value); } @Override final public void forFirst(long[] values, ValueConsumer consumer) { if (values == null || values.length == 0) return; consumer.consume(values[0]); } } class DoubleArrayByteConverter extends AbstractCastConvert { public final static DoubleArrayByteConverter INSTANCE = new DoubleArrayByteConverter(); @Override final public byte[] toBytes(double[] doubleArray) throws IOException { return Snappy.compress(doubleArray); } @Override final public double[] toValue(byte[] compressedByteArray) throws IOException { if (compressedByteArray == null) return null; return Snappy.uncompressDoubleArray(compressedByteArray); } @Override final public void forEach(double[] values, final ValueConsumer consumer) { if (values == null) return; for (double value : values) consumer.consume(value); } @Override final public void forFirst(double[] values, ValueConsumer consumer) { if (values == null || values.length == 0) return; consumer.consume(values[0]); } } class StringArrayByteConverter extends AbstractCastConvert { public final static StringArrayByteConverter INSTANCE = new StringArrayByteConverter(); @Override final public byte[] toBytes(final String[] stringArray) throws IOException { int l = 0; for (String s : stringArray) l += (s.length() + 1); char[] chars = new char[l]; CharBuffer buffer = CharBuffer.wrap(chars); for (String s : stringArray) { buffer.append(s); buffer.append((char) 0); } return Snappy.compress(chars); } private final static String[] emptyStringArray = new String[0]; @Override final public String[] toValue(byte[] compressedByteArray) throws IOException { if (compressedByteArray == null) return null; char[] chars = Snappy.uncompressCharArray(compressedByteArray); if (chars.length == 0) return emptyStringArray; List array = new ArrayList<>(); int last = 0; int pos = 0; for (char c : chars) { if (c == 0) { array.add(new String(chars, last, pos - last)); last = pos + 1; } pos++; } return array.toArray(new String[array.size()]); } @Override final public void forEach(String[] values, final ValueConsumer consumer) { if (values == null) return; for (String value : values) consumer.consume(value); } @Override final public void forFirst(String[] values, ValueConsumer consumer) { if (values == null || values.length == 0) return; consumer.consume(values[0]); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy