/*
* Copyright (C) 2006-2016 DLR, Germany
*
* All rights reserved
*
* http://www.rcenvironment.de/
*/
package de.rcenvironment.core.component.datamanagement.api;
import java.io.IOException;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.node.ArrayNode;
import org.codehaus.jackson.node.ObjectNode;
import de.rcenvironment.core.datamodel.api.TypedDatum;
import de.rcenvironment.core.datamodel.api.TypedDatumSerializer;
import de.rcenvironment.core.utils.common.JsonUtils;
/**
* Default implementation of {@link ComponentHistoryDataItem} containing inputs and outputs.
*
* @author Doreen Seider
*/
public class DefaultComponentHistoryDataItem implements ComponentHistoryDataItem {
/** Serialization key for inputs. */
public static final String INPUTS = "in";
/** Serialization key for ouputs. */
public static final String OUTPUTS = "out";
/** Serialization key for timestamp. */
public static final String TIMESTAMP = "ts";
/** Serialization key for name. */
public static final String NAME = "n";
/** Serialization key for value. */
public static final String VALUE = "v";
private static final long serialVersionUID = -3420034372755242546L;
private static final String FORMAT_VERSION_COMMON = "f_vc";
private static final String FORMAT_VERSION_1 = "1";
private static final String CURRENT_FORMAT_VERSION = FORMAT_VERSION_1;
protected Map<String, Deque<EndpointHistoryDataItem>> inputs = Collections.synchronizedMap(new HashMap<String,
Deque<EndpointHistoryDataItem>>());
protected Map<String, Deque<EndpointHistoryDataItem>> outputs = Collections.synchronizedMap(new HashMap<String,
Deque<EndpointHistoryDataItem>>());
// MetaData for Inputs
protected Map<String, Map<String, String>> inputMetaData = Collections.synchronizedMap(new HashMap<String, Map<String, String>>());
// MetaData for Outputs
protected Map<String, Map<String, String>> outputMetaData = Collections.synchronizedMap(new HashMap<String, Map<String, String>>());
private String identifier;
public void setIdentifier(String identifier) {
this.identifier = identifier;
}
@Override
public String getIdentifier() {
return identifier;
}
@Override
public synchronized String serialize(TypedDatumSerializer serializer) throws IOException {
ObjectMapper mapper = JsonUtils.getDefaultObjectMapper();
ObjectNode rootNode = mapper.createObjectNode();
rootNode.put(FORMAT_VERSION_COMMON, CURRENT_FORMAT_VERSION);
rootNode.put(INPUTS, getEndpointsAsJsonObjectNode(inputs, mapper, serializer));
rootNode.put(OUTPUTS, getEndpointsAsJsonObjectNode(outputs, mapper, serializer));
return rootNode.toString();
}
public Map<String, Deque<EndpointHistoryDataItem>> getInputs() {
return inputs;
}
public Map<String, Deque<EndpointHistoryDataItem>> getOutputs() {
return outputs;
}
/**
* Get the endpoint meta data for an endpoint.
*
* @param endpointName name of the endpoint.
* @return map containing the metadata.
*/
public Map<String, String> getMetaDataForInput(String endpointName) {
return inputMetaData.get(endpointName);
}
/**
* Get the endpoint meta data for an endpoint.
*
* @param endpointName name of the endpoint.
* @return map containing the metadata.
*/
public Map<String, String> getMetaDataForOutput(String endpointName) {
return outputMetaData.get(endpointName);
}
/**
* @param historyData text representation of {@link ScriptComponentHistoryDataItem}
* @param serializer {@link TypedDatumSerializer} instance
* @return new {@link ScriptComponentHistoryDataItem} object
* @throws IOException on error
*/
public static DefaultComponentHistoryDataItem fromString(String historyData, TypedDatumSerializer serializer)
throws IOException {
DefaultComponentHistoryDataItem historyDataItem = new DefaultComponentHistoryDataItem();
DefaultComponentHistoryDataItem.initializeDefaultHistoryDataFromString(historyDataItem, historyData, serializer);
return historyDataItem;
}
protected static void initializeDefaultHistoryDataFromString(DefaultComponentHistoryDataItem historyDataItem,
String historyData, TypedDatumSerializer serializer) throws IOException {
historyDataItem.inputs = DefaultComponentHistoryDataItem.getInputsFromString(historyData, serializer);
historyDataItem.outputs = DefaultComponentHistoryDataItem.getOutputsFromString(historyData, serializer);
}
private ObjectNode getEndpointsAsJsonObjectNode(Map<String, Deque<EndpointHistoryDataItem>> endpoints, ObjectMapper mapper,
TypedDatumSerializer serializer) {
ObjectNode endpointObjectNode = mapper.createObjectNode();
for (String inputName : endpoints.keySet()) {
ArrayNode endpointArrayNode = mapper.createArrayNode();
for (EndpointHistoryDataItem endpointData : endpoints.get(inputName)) {
ObjectNode endpointDataObjectNode = mapper.createObjectNode();
endpointDataObjectNode.put(TIMESTAMP, endpointData.getTimestamp());
endpointDataObjectNode.put(NAME, endpointData.getEndpointName());
endpointDataObjectNode.put(VALUE, serializer.serialize(endpointData.getValue()));
endpointArrayNode.add(endpointDataObjectNode);
}
endpointObjectNode.put(inputName, endpointArrayNode);
}
return endpointObjectNode;
}
/**
* @param inputName name of input to add
* @param value value of input to add
*/
public synchronized void addInput(String inputName, TypedDatum value) {
if (!inputs.containsKey(inputName)) {
inputs.put(inputName, new LinkedList<EndpointHistoryDataItem>());
}
inputs.get(inputName).addLast(new EndpointHistoryDataItem(System.currentTimeMillis(), inputName, value));
}
/**
* @param inputName name of input to add
* @param metaData the metaData to add
*/
public synchronized void setInputMetaData(String inputName, Map<String, String> metaData) {
inputMetaData.put(inputName, metaData);
}
/**
* @param outputName name of output
* @param value value of output to add
*/
public synchronized void addOutput(String outputName, TypedDatum value) {
if (!outputs.containsKey(outputName)) {
outputs.put(outputName, new LinkedList<EndpointHistoryDataItem>());
}
outputs.get(outputName).addLast(new EndpointHistoryDataItem(System.currentTimeMillis(), outputName, value));
}
/**
* @param outputName name of output
* @param metaData the metaData to add
*/
public synchronized void setOutputMetaData(String outputName, Map<String, String> metaData) {
outputMetaData.put(outputName, metaData);
}
private static Map<String, Deque<EndpointHistoryDataItem>> getInputsFromString(String endpoints, TypedDatumSerializer serializer)
throws IOException {
ObjectMapper mapper = JsonUtils.getDefaultObjectMapper();
try {
JsonNode tree = mapper.readTree(endpoints);
return getEndpointsFromString((ObjectNode) tree.get(INPUTS), serializer);
} catch (JsonProcessingException e) {
throw new IOException(e);
}
}
private static Map<String, Deque<EndpointHistoryDataItem>> getOutputsFromString(String endpoints, TypedDatumSerializer serializer)
throws IOException {
ObjectMapper mapper = JsonUtils.getDefaultObjectMapper();
try {
JsonNode tree = mapper.readTree(endpoints);
return getEndpointsFromString((ObjectNode) tree.get(OUTPUTS), serializer);
} catch (JsonProcessingException e) {
throw new IOException(e);
}
}
private static Map<String, Deque<EndpointHistoryDataItem>> getEndpointsFromString(ObjectNode endpointObjectNode,
TypedDatumSerializer serializer) {
Map<String, Deque<EndpointHistoryDataItem>> endpoints = new HashMap<>();
if (endpointObjectNode != null) {
Iterator<String> endpointNamesIterator = endpointObjectNode.getFieldNames();
while (endpointNamesIterator.hasNext()) {
String endpointName = endpointNamesIterator.next();
endpoints.put(endpointName, new LinkedList<EndpointHistoryDataItem>());
ArrayNode endpointJsonArray = (ArrayNode) endpointObjectNode.get(endpointName);
Iterator<JsonNode> endpointDataObjectNodesIterator = endpointJsonArray.getElements();
while (endpointDataObjectNodesIterator.hasNext()) {
ObjectNode endpointDataObjectNode = (ObjectNode) endpointDataObjectNodesIterator.next();
EndpointHistoryDataItem endpointHistoryData = new EndpointHistoryDataItem(
endpointDataObjectNode.get(TIMESTAMP).getLongValue(),
endpointDataObjectNode.get(NAME).getTextValue(),
serializer.deserialize(endpointDataObjectNode.get(VALUE).getTextValue()));
endpoints.get(endpointName).add(endpointHistoryData);
}
}
}
return endpoints;
}
}