com.hurence.logisland.serializer.KuraProtobufSerializer.java Source code

Java tutorial

Introduction

Here is the source code for com.hurence.logisland.serializer.KuraProtobufSerializer.java

Source

/**
 * Copyright (C) 2016 Hurence (support@hurence.com)
 *
 * 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.hurence.logisland.serializer;

import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException;
import com.hurence.logisland.record.*;
import com.hurence.logisland.util.GZipUtil;
import org.apache.commons.io.IOUtils;
import org.eclipse.kura.core.message.protobuf.KuraPayloadProto;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;

public class KuraProtobufSerializer implements RecordSerializer {

    public static final String KURA_RECORD = "kura_record";
    public static final String KURA_METRIC = "kura_metric";

    private static Logger logger = LoggerFactory.getLogger(KuraProtobufSerializer.class);

    @Override
    public void serialize(OutputStream objectDataOutput, Record record) throws RecordSerializationException {

        final KuraPayloadProto.KuraPayload.Builder protoMsg = KuraPayloadProto.KuraPayload.newBuilder();

        protoMsg.setTimestamp(record.getTime().getTime());

        if (record.hasPosition()) {
            protoMsg.setPosition(buildPositionProtoBuf(record.getPosition()));
        }

        record.getAllFields().stream().filter(
                field -> field.getType().equals(FieldType.RECORD) && field.asRecord().getType().equals(KURA_METRIC))
                .forEach(field -> {

                    final Record value = field.asRecord();
                    try {
                        final KuraPayloadProto.KuraPayload.KuraMetric.Builder metricB = KuraPayloadProto.KuraPayload.KuraMetric
                                .newBuilder();
                        metricB.setName(field.getName());

                        setProtoKuraMetricValue(metricB,
                                field.asRecord().getField(FieldDictionary.RECORD_VALUE).getRawValue());
                        metricB.build();

                        protoMsg.addMetric(metricB);
                    } catch (final Exception eihte) {
                        try {
                            System.err.println("During serialization, ignoring metric named:  " + field.getName()
                                    + "  . Unrecognized value type: " + value.getClass().getName() + ".");
                        } catch (final NullPointerException npe) {
                            System.err.println("During serialization, ignoring metric named: " + field.getName()
                                    + ". The value is null.");
                        }
                        throw new RuntimeException(eihte);
                    }
                });

        /* if (record.hasField(FieldDictionary.RECORD_BODY)) {
        protoMsg.setBody(ByteString.copyFrom(record.getField(FieldDictionary.RECORD_BODY).asString().getBytes()));
         }*/
        protoMsg.setBody(ByteString.copyFrom(record.getField(FieldDictionary.RECORD_ID).asString().getBytes()));

        try {
            byte[] paylod = protoMsg.build().toByteArray();
            objectDataOutput.write(paylod);
        } catch (IOException e) {
            logger.debug("serialization failed", e);
        }

    }

    @Override
    public Record deserialize(InputStream objectDataInput) throws RecordSerializationException {

        Record kuraRecord = new StandardRecord(KURA_RECORD);
        try {
            byte[] bytes = IOUtils.toByteArray(objectDataInput);
            if (GZipUtil.isCompressed(bytes)) {
                try {
                    bytes = GZipUtil.decompress(bytes);
                } catch (final IOException e) {
                    logger.debug("Decompression failed", e);
                }
            }

            KuraPayloadProto.KuraPayload protoMsg = null;
            try {
                protoMsg = KuraPayloadProto.KuraPayload.parseFrom(bytes);
            } catch (final InvalidProtocolBufferException ipbe) {
                throw new RuntimeException(ipbe);
            }

            if (protoMsg.hasTimestamp()) {
                kuraRecord.setTime(protoMsg.getTimestamp());
            }

            if (protoMsg.hasPosition()) {
                kuraRecord.setPosition(this.buildFromProtoBuf(protoMsg.getPosition()));
            }

            for (int i = 0; i < protoMsg.getMetricCount(); i++) {
                final String name = protoMsg.getMetric(i).getName();
                try {

                    Record kuraMetric = new StandardRecord(RecordDictionary.METRIC)
                            .setStringField(FieldDictionary.RECORD_NAME, name);

                    final Object value = this.getProtoKuraMetricValue(protoMsg.getMetric(i),
                            protoMsg.getMetric(i).getType());

                    switch (protoMsg.getMetric(i).getType()) {
                    case DOUBLE:
                        kuraMetric.setType(FieldType.DOUBLE.getName());
                        kuraMetric.setField(FieldDictionary.RECORD_VALUE, FieldType.DOUBLE, value);
                        break;
                    case BOOL:
                        kuraMetric.setType(FieldType.BOOLEAN.getName());
                        kuraMetric.setField(FieldDictionary.RECORD_VALUE, FieldType.BOOLEAN, value);
                        break;
                    case BYTES:
                        kuraMetric.setType(FieldType.BYTES.getName());
                        kuraMetric.setField(FieldDictionary.RECORD_VALUE, FieldType.BYTES, value);
                        break;
                    case FLOAT:
                        kuraMetric.setType(FieldType.FLOAT.getName());
                        kuraMetric.setField(FieldDictionary.RECORD_VALUE, FieldType.FLOAT, value);
                        break;
                    case INT32:
                        kuraMetric.setType(FieldType.INT.getName());
                        kuraMetric.setField(FieldDictionary.RECORD_VALUE, FieldType.INT, value);
                        break;
                    case INT64:
                        kuraMetric.setType(FieldType.LONG.getName());
                        kuraMetric.setField(FieldDictionary.RECORD_VALUE, FieldType.LONG, value);
                        break;
                    case STRING:
                        kuraMetric.setType(FieldType.STRING.getName());
                        kuraMetric.setField(FieldDictionary.RECORD_VALUE, FieldType.STRING, value);
                        break;
                    default:
                        logger.error("unknown metric value type for Kura record");
                        break;
                    }

                    kuraRecord.setField(name, FieldType.RECORD, kuraMetric);

                } catch (final Exception ihte) {
                    logger.debug("During deserialization, ignoring metric named: " + name
                            + ". Unrecognized value type: " + protoMsg.getMetric(i).getType(), ihte);
                }
            }

            if (protoMsg.hasBody()) {
                kuraRecord.setId(protoMsg.getBody().toStringUtf8());

            }
        } catch (IOException ex) {
            logger.error("unknown error for Kura record", ex);
        }

        return kuraRecord;
    }

    private Position buildFromProtoBuf(final KuraPayloadProto.KuraPayload.KuraPosition protoPosition) {
        final Position position = Position.from(
                protoPosition.hasAltitude() ? protoPosition.getAltitude() : Double.MIN_VALUE,
                protoPosition.hasHeading() ? protoPosition.getHeading() : Double.MIN_VALUE,
                protoPosition.hasLatitude() ? protoPosition.getLatitude() : Double.MIN_VALUE,
                protoPosition.hasLongitude() ? protoPosition.getLongitude() : Double.MIN_VALUE,
                protoPosition.hasPrecision() ? protoPosition.getPrecision() : Double.MIN_VALUE,
                protoPosition.hasSatellites() ? protoPosition.getSatellites() : Integer.MIN_VALUE,
                protoPosition.hasStatus() ? protoPosition.getStatus() : Integer.MIN_VALUE,
                protoPosition.hasSpeed() ? protoPosition.getSpeed() : Double.MIN_VALUE,
                protoPosition.hasTimestamp() ? new Date(protoPosition.getTimestamp()) : new Date(0));

        return position;
    }

    private Object getProtoKuraMetricValue(final KuraPayloadProto.KuraPayload.KuraMetric metric,
            final KuraPayloadProto.KuraPayload.KuraMetric.ValueType type) throws Exception {
        switch (type) {

        case DOUBLE:
            return metric.getDoubleValue();

        case FLOAT:
            return metric.getFloatValue();

        case INT64:
            return metric.getLongValue();

        case INT32:
            return metric.getIntValue();

        case BOOL:
            return metric.getBoolValue();

        case STRING:
            return metric.getStringValue();

        case BYTES:
            final ByteString bs = metric.getBytesValue();
            return bs.toByteArray();

        default:
            throw new Exception(type.name());
        }
    }

    private static void setProtoKuraMetricValue(final KuraPayloadProto.KuraPayload.KuraMetric.Builder metric,
            final Object o) throws Exception {

        if (o instanceof String) {
            metric.setType(KuraPayloadProto.KuraPayload.KuraMetric.ValueType.STRING);
            metric.setStringValue((String) o);
        } else if (o instanceof Double) {
            metric.setType(KuraPayloadProto.KuraPayload.KuraMetric.ValueType.DOUBLE);
            metric.setDoubleValue((Double) o);
        } else if (o instanceof Integer) {
            metric.setType(KuraPayloadProto.KuraPayload.KuraMetric.ValueType.INT32);
            metric.setIntValue((Integer) o);
        } else if (o instanceof Float) {
            metric.setType(KuraPayloadProto.KuraPayload.KuraMetric.ValueType.FLOAT);
            metric.setFloatValue((Float) o);
        } else if (o instanceof Long) {
            metric.setType(KuraPayloadProto.KuraPayload.KuraMetric.ValueType.INT64);
            metric.setLongValue((Long) o);
        } else if (o instanceof Boolean) {
            metric.setType(KuraPayloadProto.KuraPayload.KuraMetric.ValueType.BOOL);
            metric.setBoolValue((Boolean) o);
        } else if (o instanceof byte[]) {
            metric.setType(KuraPayloadProto.KuraPayload.KuraMetric.ValueType.BYTES);
            metric.setBytesValue(ByteString.copyFrom((byte[]) o));
        } else if (o == null) {
            throw new Exception("null value");
        } else {
            throw new Exception(o.getClass().getName());
        }
    }

    private KuraPayloadProto.KuraPayload.KuraPosition buildPositionProtoBuf(Position position) {
        KuraPayloadProto.KuraPayload.KuraPosition.Builder protoPos = null;
        protoPos = KuraPayloadProto.KuraPayload.KuraPosition.newBuilder();

        if (position.getLatitude() != null) {
            protoPos.setLatitude(position.getLatitude());
        }
        if (position.getLongitude() != null) {
            protoPos.setLongitude(position.getLongitude());
        }
        if (position.getAltitude() != null) {
            protoPos.setAltitude(position.getAltitude());
        }
        if (position.getPrecision() != null) {
            protoPos.setPrecision(position.getPrecision());
        }
        if (position.getHeading() != null) {
            protoPos.setHeading(position.getHeading());
        }
        if (position.getSpeed() != null) {
            protoPos.setSpeed(position.getSpeed());
        }
        if (position.getTimestamp() != null) {
            protoPos.setTimestamp(position.getTimestamp().getTime());
        }
        if (position.getSatellites() != null) {
            protoPos.setSatellites(position.getSatellites());
        }
        if (position.getStatus() != null) {
            protoPos.setStatus(position.getStatus());
        }
        return protoPos.build();
    }

}