MetrixDie.java
/*
* Copyright (c) 2020, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* SPDX-License-Identifier: MPL-2.0
*/
package com.powsybl.metrix.integration.io;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Iterables;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
/**
* @author Paul Bui-Quang {@literal <paul.buiquang at rte-france.com>}
*/
public class MetrixDie {
private static final Logger LOGGER = LoggerFactory.getLogger(MetrixDie.class);
private static final int ATTRIBUTE_NAME_LENGTH = 8;
private static final String INTEGER_FILE_NAME = "IntegerFile";
private static final String FLOAT_FILE_NAME = "FloatFile";
private static final String DOUBLE_FILE_NAME = "DoubleFile";
private static final String STRING_FILE_NAME = "StringFile";
private static final String BOOLEAN_FILE_NAME = "BooleanFile";
private static final String NOT_FOUND = " not found";
private static final String IS_NOT_A_SCALAR = " is not a scalar";
private final Map<String, IntAttribute> intAttributes = new LinkedHashMap<>();
private final Map<String, FloatAttribute> floatAttributes = new LinkedHashMap<>();
private final Map<String, DoubleAttribute> doubleAttributes = new LinkedHashMap<>();
private final Map<String, StringAttribute> stringAttributes = new LinkedHashMap<>();
private final Map<String, BooleanAttribute> booleanAttributes = new LinkedHashMap<>();
private static <T extends Attribute> void saveFort4xToJson(JsonGenerator generator, String fileName, Map<String, T> attributes) throws IOException {
generator.writeStartObject();
generator.writeStringField("name", fileName);
generator.writeFieldName("attributes");
generator.writeStartArray();
for (T attribute : attributes.values()) {
generator.writeStartObject();
generator.writeStringField("name", attribute.getName());
generator.writeStringField("type", attribute.getType().name());
generator.writeNumberField("valueCount", attribute.getValueCount());
generator.writeNumberField("firstIndexMaxValue", attribute.getFirstIndexMaxValue());
generator.writeNumberField("secondIndexMaxValue", attribute.getSecondIndexMaxValue());
generator.writeNumberField("firstValueIndex", 1);
generator.writeNumberField("lastValueIndex", attribute.getValueCount());
generator.writeFieldName("values");
generator.writeStartArray();
attribute.writeJson(generator);
generator.writeEndArray();
generator.writeEndObject();
}
generator.writeEndArray();
generator.writeEndObject();
}
public void saveToJson(BufferedWriter writer) throws IOException {
JsonFactory factory = new JsonFactory();
try (JsonGenerator generator = factory.createGenerator(writer)) {
generator.useDefaultPrettyPrinter();
generator.writeStartObject();
generator.writeFieldName("files");
generator.writeStartArray();
saveFort4xToJson(generator, INTEGER_FILE_NAME, intAttributes);
saveFort4xToJson(generator, FLOAT_FILE_NAME, floatAttributes);
saveFort4xToJson(generator, DOUBLE_FILE_NAME, doubleAttributes);
saveFort4xToJson(generator, STRING_FILE_NAME, stringAttributes);
saveFort4xToJson(generator, BOOLEAN_FILE_NAME, booleanAttributes);
generator.writeEndArray();
generator.writeEndObject();
}
}
public void saveToJson(Path file) throws IOException {
BufferedWriter bufferedWriter = Files.newBufferedWriter(file, StandardCharsets.UTF_8);
saveToJson(bufferedWriter);
}
private static <T extends Attribute> void loadFromJson(JsonNode nodes, Map<String, T> attributes, Class<T> attributeClass) throws IOException {
ObjectMapper mapper = new ObjectMapper();
for (Iterator<JsonNode> nodeAttributes = nodes.elements(); nodeAttributes.hasNext(); ) {
JsonNode attr = nodeAttributes.next();
T attribute = mapper.readValue(attr.toString(), attributeClass);
attributes.put(attribute.getName(), attribute);
}
}
public void loadFromJson(Path jsonFile) throws IOException {
try (BufferedReader reader = Files.newBufferedReader(jsonFile)) {
ObjectMapper mapper = new ObjectMapper();
JsonNode rootNode = mapper.readTree(reader).path("files");
for (Iterator<JsonNode> files = rootNode.elements(); files.hasNext(); ) {
JsonNode dieFile = files.next();
String name = dieFile.path("name").textValue();
JsonNode attributes = dieFile.path("attributes");
if (INTEGER_FILE_NAME.equals(name)) {
loadFromJson(attributes, intAttributes, IntAttribute.class);
} else if (FLOAT_FILE_NAME.equals(name)) {
loadFromJson(attributes, floatAttributes, FloatAttribute.class);
} else if (DOUBLE_FILE_NAME.equals(name)) {
loadFromJson(attributes, doubleAttributes, DoubleAttribute.class);
} else if (STRING_FILE_NAME.equals(name)) {
loadFromJson(attributes, stringAttributes, StringAttribute.class);
} else if (BOOLEAN_FILE_NAME.equals(name)) {
loadFromJson(attributes, booleanAttributes, BooleanAttribute.class);
}
}
}
}
private static void checkAttributeNameLength(String name) {
if (name.length() != ATTRIBUTE_NAME_LENGTH) {
throw new MetrixDieException("Incorrect attribute name length: "
+ name + " (should be " + ATTRIBUTE_NAME_LENGTH + ")");
}
}
public int[] getIntArray(String name) {
IntAttribute attribute = intAttributes.get(name);
if (attribute == null) {
throw new MetrixDieException("Int attribute " + name + NOT_FOUND);
}
return attribute.getValues();
}
public int getInt(String name) {
int[] array = getIntArray(name);
if (array.length != 1) {
throw new MetrixDieException("Int attribute " + name + IS_NOT_A_SCALAR);
}
return array[0];
}
public void setIntArray(String name, int[] values) {
checkAttributeNameLength(name);
intAttributes.put(name, new IntAttribute(name, values));
}
public void setInt(String name, int value) {
checkAttributeNameLength(name);
intAttributes.put(name, new IntAttribute(name, new int[]{value}));
}
public float[] getFloatArray(String name) {
FloatAttribute attribute = floatAttributes.get(name);
if (attribute == null) {
throw new MetrixDieException("Float attribute " + name + NOT_FOUND);
}
return attribute.getValues();
}
public float getFloat(String name) {
float[] array = getFloatArray(name);
if (array.length != 1) {
throw new MetrixDieException("Float attribute " + name + IS_NOT_A_SCALAR);
}
return array[0];
}
public void setFloatArray(String name, float[] values) {
checkAttributeNameLength(name);
floatAttributes.put(name, new FloatAttribute(name, values));
}
public void setFloat(String name, float value) {
checkAttributeNameLength(name);
floatAttributes.put(name, new FloatAttribute(name, new float[]{value}));
}
public double[] getDoubleArray(String name) {
DoubleAttribute attribute = doubleAttributes.get(name);
if (attribute == null) {
throw new MetrixDieException("Double attribute " + name + NOT_FOUND);
}
return attribute.getValues();
}
public double getDouble(String name) {
double[] array = getDoubleArray(name);
if (array.length != 1) {
throw new MetrixDieException("Double attribute " + name + IS_NOT_A_SCALAR);
}
return array[0];
}
public void setDoubleArray(String name, double[] values) {
checkAttributeNameLength(name);
doubleAttributes.put(name, new DoubleAttribute(name, values));
}
public void setDouble(String name, double value) {
checkAttributeNameLength(name);
doubleAttributes.put(name, new DoubleAttribute(name, new double[]{value}));
}
public String[] getStringArray(String name) {
StringAttribute attribute = stringAttributes.get(name);
if (attribute == null) {
throw new MetrixDieException("String attribute " + name + NOT_FOUND);
}
return attribute.getValues();
}
public String getString(String name) {
String[] array = getStringArray(name);
if (array.length != 1) {
throw new MetrixDieException("String attribute " + name + IS_NOT_A_SCALAR);
}
return array[0];
}
public void setStringArray(String name, String[] values) {
checkAttributeNameLength(name);
stringAttributes.put(name, new StringAttribute(name, values));
}
public void setString(String name, String value) {
checkAttributeNameLength(name);
stringAttributes.put(name, new StringAttribute(name, new String[]{value}));
}
public boolean[] getBooleanArray(String name) {
BooleanAttribute attribute = booleanAttributes.get(name);
if (attribute == null) {
throw new MetrixDieException("Boolean attribute " + name + NOT_FOUND);
}
return attribute.getValues();
}
public boolean getBoolean(String name) {
boolean[] array = getBooleanArray(name);
if (array.length != 1) {
throw new MetrixDieException("Boolean attribute " + name + IS_NOT_A_SCALAR);
}
return array[0];
}
public void setBooleanArray(String name, boolean[] values) {
checkAttributeNameLength(name);
booleanAttributes.put(name, new BooleanAttribute(name, values));
}
public void setBoolean(String name, boolean value) {
checkAttributeNameLength(name);
booleanAttributes.put(name, new BooleanAttribute(name, new boolean[]{value}));
}
public Set<String> getAttributeNames() {
Set<String> names = new HashSet<>();
names.addAll(intAttributes.keySet());
names.addAll(floatAttributes.keySet());
names.addAll(doubleAttributes.keySet());
names.addAll(stringAttributes.keySet());
names.addAll(booleanAttributes.keySet());
return names;
}
public void print(PrintStream out) {
for (Attribute attribute : Iterables.concat(intAttributes.values(),
floatAttributes.values(),
doubleAttributes.values(),
stringAttributes.values(),
booleanAttributes.values())) {
out.print(attribute.getName());
out.print(": [");
attribute.print(out);
out.println("]");
}
}
}