com.hurence.logisland.util.kura.Metrics Maven / Gradle / Ivy
/**
* Copyright (C) 2016 Hurence ([email protected])
*
* 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.util.kura;
/*******************************************************************************
* Copyright (c) 2017 Red Hat Inc and others
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat Inc - initial API and implementation
*******************************************************************************/
import com.google.protobuf.ByteString;
import com.hurence.logisland.record.Position;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.commons.lang3.reflect.MethodUtils;
import org.eclipse.kura.core.message.protobuf.KuraPayloadProto;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
public final class Metrics {
private Metrics() {
}
public static final String KEY_REQUESTER_CLIENT_ID = "requester.client.id";
public static final String KEY_REQUEST_ID = "request.id";
public static final String KEY_RESPONSE_CODE = "response.code";
public static final String KEY_RESPONSE_EXCEPTION_MESSAGE = "response.exception.message";
public static final String KEY_RESPONSE_EXCEPTION_STACKTRACE = "response.exception.stack";
/**
* Convert plain key value map into a Kura metric structure
* Only the supported Kura values types must be used (String, boolean, int,
* long, float, double, byte[])
*
* @param builder
* the builder to append the metrics to
* @param metrics
* the metrics map
* @throws IllegalArgumentException
* in case of an unsupported value type
*/
public static void buildMetrics(final KuraPayloadProto.KuraPayload.Builder builder, final Map metrics) {
Objects.requireNonNull(metrics);
for (final Map.Entry metric : metrics.entrySet()) {
addMetric(builder, metric.getKey(), metric.getValue());
}
}
public static KuraPayloadProto.KuraPayload toKuraPayload(final Payload payload) {
if (payload == null) {
return null;
}
final KuraPayloadProto.KuraPayload.Builder result = KuraPayloadProto.KuraPayload.newBuilder();
buildPayload(result, payload);
return result.build();
}
public static void buildPayload(final KuraPayloadProto.KuraPayload.Builder builder, final Payload payload) {
Objects.requireNonNull(builder);
Objects.requireNonNull(payload);
buildBody(builder, payload.getBody());
buildPosition(builder, payload.getPosition());
buildMetrics(builder, payload.getMetrics());
}
public static void buildPosition(final KuraPayloadProto.KuraPayload.Builder builder, final Position position) {
if (position == null) {
return;
}
Objects.requireNonNull(builder);
final KuraPayloadProto.KuraPayload.KuraPosition.Builder result = KuraPayloadProto.KuraPayload.KuraPosition.newBuilder();
if (position.getAltitude() != null) {
result.setAltitude(position.getAltitude());
}
if (position.getHeading() != null) {
result.setHeading(position.getHeading());
}
if (position.getLatitude() != null) {
result.setLatitude(position.getLatitude());
}
if (position.getLongitude() != null) {
result.setLongitude(position.getLongitude());
}
if (position.getPrecision() != null) {
result.setPrecision(position.getPrecision());
}
if (position.getSatellites() != null) {
result.setSatellites(position.getSatellites());
}
if (position.getSpeed() != null) {
result.setSpeed(position.getSpeed());
}
if (position.getTimestamp() != null) {
result.setTimestamp(position.getTimestamp().getTime());
}
builder.setPosition(result);
}
public static void buildBody(final KuraPayloadProto.KuraPayload.Builder builder, final ByteBuffer body) {
if (body == null) {
return;
}
Objects.requireNonNull(builder);
builder.setBody(ByteString.copyFrom(body));
}
public static void addMetric(final KuraPayloadProto.KuraPayload.Builder builder, final String key, final Object value) {
final KuraPayloadProto.KuraPayload.KuraMetric.Builder b = KuraPayloadProto.KuraPayload.KuraMetric.newBuilder();
b.setName(key);
if (value == null) {
return;
} else if (value instanceof Boolean) {
b.setType(KuraPayloadProto.KuraPayload.KuraMetric.ValueType.BOOL);
b.setBoolValue((boolean) value);
} else if (value instanceof Integer) {
b.setType(KuraPayloadProto.KuraPayload.KuraMetric.ValueType.INT32);
b.setIntValue((int) value);
} else if (value instanceof String) {
b.setType(KuraPayloadProto.KuraPayload.KuraMetric.ValueType.STRING);
b.setStringValue((String) value);
} else if (value instanceof Long) {
b.setType(KuraPayloadProto.KuraPayload.KuraMetric.ValueType.INT64);
b.setLongValue((Long) value);
} else if (value instanceof Double) {
b.setType(KuraPayloadProto.KuraPayload.KuraMetric.ValueType.DOUBLE);
b.setDoubleValue((Double) value);
} else if (value instanceof Float) {
b.setType(KuraPayloadProto.KuraPayload.KuraMetric.ValueType.FLOAT);
b.setFloatValue((Float) value);
} else if (value instanceof byte[]) {
b.setType(KuraPayloadProto.KuraPayload.KuraMetric.ValueType.BYTES);
b.setBytesValue(ByteString.copyFrom((byte[]) value));
} else {
throw new IllegalArgumentException(String.format("Illegal metric data type: %s", value.getClass()));
}
builder.addMetric(b);
}
public static Map extractMetrics(final KuraPayloadProto.KuraPayload payload) {
if (payload == null) {
return null;
}
return extractMetrics(payload.getMetricList());
}
public static Map extractMetrics(final List metricList) {
if (metricList == null) {
return null;
}
/*
* We are using a TreeMap in order to have a stable order of properties
*/
final Map result = new TreeMap<>();
for (final KuraPayloadProto.KuraPayload.KuraMetric metric : metricList) {
final String name = metric.getName();
switch (metric.getType()) {
case BOOL:
result.put(name, metric.getBoolValue());
break;
case BYTES:
result.put(name, metric.getBytesValue().toByteArray());
break;
case DOUBLE:
result.put(name, metric.getDoubleValue());
break;
case FLOAT:
result.put(name, metric.getFloatValue());
break;
case INT32:
result.put(name, metric.getIntValue());
break;
case INT64:
result.put(name, metric.getLongValue());
break;
case STRING:
result.put(name, metric.getStringValue());
break;
}
}
return result;
}
public static String getAsString(final Map metrics, final String key) {
return getAsString(metrics, key, null);
}
public static String getAsString(final Map metrics, final String key, final String defaultValue) {
final Object value = metrics.get(key);
if (value == null) {
return defaultValue;
}
if (value instanceof String) {
return (String) value;
}
return defaultValue;
}
public static T readFrom(final T object, final Map metrics) {
Objects.requireNonNull(object);
for (final Field field : FieldUtils.getFieldsListWithAnnotation(object.getClass(), Metric.class)) {
final Metric m = field.getAnnotation(Metric.class);
final boolean optional = field.isAnnotationPresent(Optional.class);
final Object value = metrics.get(m.value());
if (value == null && !optional) {
throw new IllegalArgumentException(
String.format("Field '%s' is missing metric '%s'", field.getName(), m.value()));
}
if (value == null) {
// not set but optional
continue;
}
try {
FieldUtils.writeField(field, object, value, true);
} catch (final IllegalArgumentException e) {
// provide a better message
throw new IllegalArgumentException(String.format("Failed to assign '%s' (%s) to field '%s'", value,
value.getClass().getName(), field.getName()), e);
} catch (final IllegalAccessException e) {
throw new RuntimeException(e);
}
}
for (final Method method : MethodUtils.getMethodsListWithAnnotation(object.getClass(), Metric.class)) {
final Metric m = method.getAnnotation(Metric.class);
final boolean optional = method.isAnnotationPresent(Optional.class);
final Object value = metrics.get(m.value());
if (value == null && !optional) {
throw new IllegalArgumentException(
String.format("Method '%s' is missing metric '%s'", method.getName(), m.value()));
}
if (value == null) {
// not set but optional
continue;
}
try {
method.invoke(object, value);
} catch (final IllegalArgumentException e) {
// provide a better message
throw new IllegalArgumentException(String.format("Failed to call '%s' (%s) with method '%s'", value,
value.getClass().getName(), method.getName()), e);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
return object;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy