Package org.lilyproject.repository.impl

Source Code of org.lilyproject.repository.impl.MetadataSerDeser$DateTimeValueSerDeser

/*
* Copyright 2013 NGDATA nv
*
* 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.lilyproject.repository.impl;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.joda.time.DateTime;
import org.joda.time.DateTimeUtils;
import org.joda.time.DateTimeZone;
import org.lilyproject.bytes.api.ByteArray;
import org.lilyproject.bytes.api.DataInput;
import org.lilyproject.bytes.api.DataOutput;
import org.lilyproject.repository.api.Metadata;
import org.lilyproject.repository.api.MetadataBuilder;

/**
* Serialize and deserialize a {@link Metadata} object. The various value types supported by Metadata use a
* type-specific serialization, so that type information is retained and storage size optimal.
*/
public class MetadataSerDeser {
    private MetadataSerDeser() {
    }

    /**
     * Writes the metadata to the given output. It can be read back from a variable-length input using
     * {@link #read(DataInput)}.
     */
    public static void write(Metadata metadata, DataOutput output) {
        // Write the fields
        Map<String, Object> map = metadata.getMap();
        output.writeVInt(map.size());
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            // write the key
            output.writeVUTF(entry.getKey());
            // write the value
            Object value = entry.getValue();
            ValueSerDeser serdeser = CLASS_TO_SERDESER.get(value.getClass());
            if (serdeser == null) {
                throw new IllegalArgumentException("Unsupported kind of metadata value: type of '" + value + "' is "
                        + value.getClass().getName());
            }
            output.writeByte(serdeser.getTypeByte());
            serdeser.serialize(value, output);
        }

        // Write the deleted fields
        Set<String> fieldsToDelete = metadata.getFieldsToDelete();
        output.writeVInt(fieldsToDelete.size());
        for (String field : fieldsToDelete) {
            output.writeVUTF(field);
        }
    }

    public static Metadata read(DataInput input) {
        MetadataBuilder metadataBuilder = new MetadataBuilder();

        // read fields
        int size = input.readVInt();
        for (int i = 0; i < size; i++) {
            String key = input.readVUTF();
            byte valueType = input.readByte();
            ValueSerDeser serdeser = BYTE_TO_SERDESER.get(valueType);
            if (serdeser == null) {
                throw new IllegalArgumentException("Unsupported kind of metadata value: type byte " + (int)valueType);
            }
            Object value = serdeser.deserialize(input);
            metadataBuilder.object(key, value);
        }

        // read deleted fields
        size = input.readVInt();
        for (int i = 0; i < size; i++) {
            metadataBuilder.delete(input.readVUTF());
        }

        return metadataBuilder.build();
    }

    private static interface ValueSerDeser {
        Class getTypeClass();

        byte getTypeByte();

        void serialize(Object value, DataOutput dataOutput);

        Object deserialize(DataInput dataInput);
    }

    private static final ValueSerDeser STRING_SERDESER = new StringValueSerDeser();

    private static class StringValueSerDeser implements ValueSerDeser {
        @Override
        public Class getTypeClass() {
            return String.class;
        }

        @Override
        public byte getTypeByte() {
            return 1;
        }

        @Override
        public void serialize(Object value, DataOutput dataOutput) {
            dataOutput.writeVUTF((String)value);
        }

        @Override
        public Object deserialize(DataInput dataInput) {
            return dataInput.readVUTF();
        }
    }

    private static final ValueSerDeser INT_SERDESER = new IntegerValueSerDeser();

    private static class IntegerValueSerDeser implements ValueSerDeser {
        @Override
        public Class getTypeClass() {
            return Integer.class;
        }

        @Override
        public byte getTypeByte() {
            return 2;
        }

        @Override
        public void serialize(Object value, DataOutput dataOutput) {
            dataOutput.writeVInt((Integer) value);
        }

        @Override
        public Object deserialize(DataInput dataInput) {
            return dataInput.readVInt();
        }
    }

    private static final ValueSerDeser LONG_SERDESER = new LongValueSerDeser();

    private static class LongValueSerDeser implements ValueSerDeser {
        @Override
        public Class getTypeClass() {
            return Long.class;
        }

        @Override
        public byte getTypeByte() {
            return 3;
        }

        @Override
        public void serialize(Object value, DataOutput dataOutput) {
            dataOutput.writeVLong((Long) value);
        }

        @Override
        public Object deserialize(DataInput dataInput) {
            return dataInput.readVLong();
        }
    }

    private static final ValueSerDeser FLOAT_SERDESER = new FloatValueSerDeser();

    private static class FloatValueSerDeser implements ValueSerDeser {
        @Override
        public Class getTypeClass() {
            return Float.class;
        }

        @Override
        public byte getTypeByte() {
            return 4;
        }

        @Override
        public void serialize(Object value, DataOutput dataOutput) {
            dataOutput.writeFloat((Float) value);
        }

        @Override
        public Object deserialize(DataInput dataInput) {
            return dataInput.readFloat();
        }
    }

    private static final ValueSerDeser DOUBLE_SERDESER = new DoubleValueSerDeser();

    private static class DoubleValueSerDeser implements ValueSerDeser {
        @Override
        public Class getTypeClass() {
            return Double.class;
        }

        @Override
        public byte getTypeByte() {
            return 5;
        }

        @Override
        public void serialize(Object value, DataOutput dataOutput) {
            dataOutput.writeDouble((Double) value);
        }

        @Override
        public Object deserialize(DataInput dataInput) {
            return dataInput.readDouble();
        }
    }

    private static final ValueSerDeser BOOLEAN_SERDESER = new BooleanValueSerDeser();

    private static class BooleanValueSerDeser implements ValueSerDeser {
        @Override
        public Class getTypeClass() {
            return Boolean.class;
        }

        @Override
        public byte getTypeByte() {
            return 6;
        }

        @Override
        public void serialize(Object value, DataOutput dataOutput) {
            dataOutput.writeBoolean((Boolean) value);
        }

        @Override
        public Object deserialize(DataInput dataInput) {
            return dataInput.readBoolean();
        }
    }

    private static final ValueSerDeser BYTES_SERDESER = new BytesValueSerDeser();

    private static class BytesValueSerDeser implements ValueSerDeser {
        @Override
        public Class getTypeClass() {
            return ByteArray.class;
        }

        @Override
        public byte getTypeByte() {
            return 7;
        }

        @Override
        public void serialize(Object value, DataOutput dataOutput) {
            dataOutput.writeVInt(((ByteArray)value).length());
            dataOutput.writeBytes(((ByteArray) value).getBytesUnsafe());
        }

        @Override
        public Object deserialize(DataInput dataInput) {
            int size = dataInput.readVInt();
            return new ByteArray(dataInput.readBytes(size));
        }
    }

    private static final ValueSerDeser DATETIME_SERDESER = new DateTimeValueSerDeser();

    private static class DateTimeValueSerDeser implements ValueSerDeser {

        @Override
        public Class getTypeClass() {
            return org.joda.time.DateTime.class;
        }

        @Override
        public byte getTypeByte() {
            return 8;
        }

        @Override
        public void serialize(Object value, DataOutput dataOutput) {
            DateTime dateTime = (DateTime) value;
            dateTime = dateTime.toDateTime(DateTimeZone.UTC); //store as UTC
            dataOutput.writeLong(dateTime.getMillis());
        }

        @Override
        public Object deserialize(DataInput dataInput) {
            // Always construct UTC such that it is not depending on the default timezone of the current host
            return new DateTime(dataInput.readLong(), DateTimeZone.UTC);
        }
    }

    private static final ValueSerDeser[] serdesers = new ValueSerDeser[] { STRING_SERDESER, INT_SERDESER, LONG_SERDESER,
            FLOAT_SERDESER, DOUBLE_SERDESER, BOOLEAN_SERDESER, BYTES_SERDESER, DATETIME_SERDESER };

    private static final Map<Class, ValueSerDeser> CLASS_TO_SERDESER = new HashMap<Class, ValueSerDeser>();
    static {
        for (ValueSerDeser serdeser : serdesers) {
            CLASS_TO_SERDESER.put(serdeser.getTypeClass(), serdeser);
        }

        // This is just to protect against double usage of the same type class
        if (CLASS_TO_SERDESER.size() != serdesers.length) {
            throw new RuntimeException("Incorrect number of serdesers.");
        }
    }

    private static final Map<Byte, ValueSerDeser> BYTE_TO_SERDESER = new HashMap<Byte, ValueSerDeser>();
    static {
        for (ValueSerDeser serdeser : serdesers) {
            BYTE_TO_SERDESER.put(serdeser.getTypeByte(), serdeser);
        }

        // This is just to protect against double usage of the same type byte
        if (BYTE_TO_SERDESER.size() != serdesers.length) {
            throw new RuntimeException("Incorrect number of serdesers.");
        }
    }

}
TOP

Related Classes of org.lilyproject.repository.impl.MetadataSerDeser$DateTimeValueSerDeser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.