Skip to content

Commit

Permalink
Reporter POC: fix deserialization with no specified dictionary (#1783)
Browse files Browse the repository at this point in the history
Signed-off-by: Florian Dupuy <[email protected]>
  • Loading branch information
flo-dup authored and miovd committed Jul 7, 2021
1 parent 092d0f8 commit 144240b
Show file tree
Hide file tree
Showing 11 changed files with 99 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
import java.util.Objects;

/**
* An abstract class providing some default method implementations for {@link Reporter} implementations.
* <i>WARNING:</i> <code>Reporter</code> <i>is still a beta feature, structural changes might occur in the future releases</i>
*
* <p>An abstract class providing some default method implementations for {@link Reporter} implementations.
* @author Florian Dupuy <florian.dupuy at rte-france.com>
*/
public abstract class AbstractReporter implements Reporter {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
import java.util.Objects;

/**
* A class representing a functional log, consisting of a key identifying the report, a map of {@link TypedValue} indexed
* <i>WARNING:</i> <code>Reporter</code> <i>is still a beta feature, structural changes might occur in the future releases</i>
*
* <p>A class representing a functional log, consisting of a key identifying the report, a map of {@link TypedValue} indexed
* by their keys, and a default report message string, which may contain references to those values or to the values
* of corresponding {@link Reporter}.
* @author Florian Dupuy <florian.dupuy at rte-france.com>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
import java.util.Map;

/**
* A builder to create {@link Report} objects.
* <i>WARNING:</i> <code>Reporter</code> <i>is still a beta feature, structural changes might occur in the future releases</i>
*
* <p>A builder to create {@link Report} objects.
*
* @author Florian Dupuy <florian.dupuy at rte-france.com>
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
import java.util.Map;

/**
* A <code>Reporter</code> allows building up functional reports with a hierarchy reflecting task/subtasks of processes.
* <i>WARNING:</i> <code>Reporter</code> <i>is still a beta feature, structural changes might occur in the future releases</i>
*
* <p>A <code>Reporter</code> allows building up functional reports with a hierarchy reflecting task/subtasks of processes.
* The enclosed reports are based on {@link Report} class.
*
* <p>A <code>Reporter</code> can create sub-reporters to separate from current reports the reports from that task.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
import java.util.*;

/**
* An in-memory implementation of {@link Reporter}.
* <i>WARNING:</i> <code>Reporter</code> <i>is still a beta feature, structural changes might occur in the future releases</i>
*
* <p>An in-memory implementation of {@link Reporter}.
*
* <p>Being an implementation of {@link Reporter}, instances of <code>ReporterModel</code> are not thread-safe.
* A reporterModel is not meant to be shared with other threads nor to be saved as a class parameter, but should instead
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.InputStream;
Expand All @@ -24,11 +26,16 @@
import java.util.Objects;

/**
* <i>WARNING:</i> <code>Reporter</code> <i>is still a beta feature, structural changes might occur in the future releases</i>
*
* @author Florian Dupuy <florian.dupuy at rte-france.com>
*/
public class ReporterModelDeserializer extends StdDeserializer<ReporterModel> {

private static final Logger LOGGER = LoggerFactory.getLogger(ReporterModelDeserializer.class);

public static final String DICTIONARY_VALUE_ID = "dictionary";
public static final String DICTIONARY_DEFAULT_NAME = "default";

ReporterModelDeserializer() {
super(ReporterModel.class);
Expand All @@ -41,29 +48,59 @@ public ReporterModel deserialize(JsonParser p, DeserializationContext ctx) throw
Map<String, String> dictionary = Collections.emptyMap();
JsonNode dicsNode = root.get("dics");
if (dicsNode != null) {
JsonNode dicNode = dicsNode.get(getDicName(ctx));
String dictionaryName = getDictionaryName(ctx);
JsonNode dicNode = dicsNode.get(dictionaryName);
if (dicNode == null && dicsNode.fields().next() != null) {
Map.Entry<String, JsonNode> firstDictionary = dicsNode.fields().next();
dicNode = firstDictionary.getValue();
LOGGER.warn("Cannot find `{}` dictionary, taking first entry (`{}`)", dictionaryName, firstDictionary.getKey());
}
if (dicNode != null) {
dictionary = codec.readValue(dicNode.traverse(), new TypeReference<HashMap<String, String>>() {
});
} else {
LOGGER.warn("No dictionary found! `dics` root entry is empty");
}
} else {
LOGGER.warn("No dictionary found! `dics` root entry is missing");
}
return ReporterModel.parseJsonNode(root.get("reportTree"), dictionary, codec);
}

private String getDicName(DeserializationContext ctx) throws JsonMappingException {
Object dicNameInjected = ctx.findInjectableValue(DICTIONARY_VALUE_ID, null, null);
return dicNameInjected instanceof String ? (String) dicNameInjected : "default";
private String getDictionaryName(DeserializationContext ctx) {
try {
Object dicNameInjected = ctx.findInjectableValue(DICTIONARY_VALUE_ID, null, null);
return dicNameInjected instanceof String ? (String) dicNameInjected : DICTIONARY_DEFAULT_NAME;
} catch (JsonMappingException e) {
LOGGER.info("No injectable value found for id `{}` in DeserializationContext, therefore taking `{}` dictionary",
DICTIONARY_VALUE_ID, DICTIONARY_DEFAULT_NAME);
return DICTIONARY_DEFAULT_NAME;
}
}

public static ReporterModel read(Path jsonFile) {
return read(jsonFile, "default");
return read(jsonFile, DICTIONARY_DEFAULT_NAME);
}

public static ReporterModel read(InputStream jsonIs) {
return read(jsonIs, DICTIONARY_DEFAULT_NAME);
}

public static ReporterModel read(Path jsonFile, String dictionary) {
Objects.requireNonNull(jsonFile);
Objects.requireNonNull(dictionary);
try (InputStream is = Files.newInputStream(jsonFile)) {
return getReporterModelObjectMapper(dictionary).readValue(is, ReporterModel.class);
return read(is, dictionary);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}

public static ReporterModel read(InputStream jsonIs, String dictionary) {
Objects.requireNonNull(jsonIs);
Objects.requireNonNull(dictionary);
try {
return getReporterModelObjectMapper(dictionary).readValue(jsonIs, ReporterModel.class);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import com.fasterxml.jackson.databind.module.SimpleModule;

/**
* <i>WARNING:</i> <code>Reporter</code> <i>is still a beta feature, structural changes might occur in the future releases</i>
*
* @author Florian Dupuy <florian.dupuy at rte-france.com>
*/
public class ReporterModelJsonModule extends SimpleModule {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import java.util.Objects;

/**
* <i>WARNING:</i> <code>Reporter</code> <i>is still a beta feature, structural changes might occur in the future releases</i>
*
* @author Florian Dupuy <florian.dupuy at rte-france.com>
*/
public class ReporterModelSerializer extends StdSerializer<ReporterModel> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@
import java.util.Objects;

/**
* A class associating a value with a type.
* <i>WARNING:</i> <code>Reporter</code> <i>is still a beta feature, structural changes might occur in the future releases</i>
*
* <p>A class associating a value with a type.
* The value should be an instance of any of the following classes: Integer, Long, Float, Double, Boolean or String.
* The type is given by a string. Some generic types are provided by public constants of current class.
* @author Florian Dupuy <florian.dupuy at rte-france.com>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* Copyright (c) 2021, 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/.
*/

/**
* Reporter API for functional logs beta-feature and default in-memory implementation
*
* <p><i>WARNING:</i> <code>Reporter</code> <i>is still a beta feature, structural changes might occur in the future releases</i>
*
* @author Florian Dupuy <florian.dupuy at rte-france.com>
*/
package com.powsybl.commons.reporter;
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/
package com.powsybl.ucte.converter;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.io.ByteStreams;
import com.powsybl.commons.AbstractConverterTest;
import com.powsybl.commons.PowsyblException;
Expand Down Expand Up @@ -74,6 +75,24 @@ public void roundTripReporterJsonTest() throws Exception {
reporter.report("novalueReport", "No value report");
Importers.loadNetwork(filename, getClass().getResourceAsStream("/" + filename), reporter);
roundTripTest(reporter, ReporterModelSerializer::write, ReporterModelDeserializer::read, "/frVoltageRegulatingXnodeReport.json");

// Testing deserializing with unknown specified dictionary
ReporterModel rm = ReporterModelDeserializer.read(getClass().getResourceAsStream("/frVoltageRegulatingXnodeReport.json"), "de");
assertEquals(1, rm.getReports().size());
assertEquals("No value report", rm.getReports().iterator().next().getDefaultMessage());
assertEquals(4, rm.getSubReporters().size());
assertEquals("Reading UCTE network file", rm.getSubReporters().get(0).getDefaultName());
}

@Test
public void jsonDeserializeNoSpecifiedDictionary() throws Exception {
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new ReporterModelJsonModule());
ReporterModel rm = mapper.readValue(getClass().getResource("/frVoltageRegulatingXnodeReport.json"), ReporterModel.class);
assertEquals(1, rm.getReports().size());
assertEquals("No value report", rm.getReports().iterator().next().getDefaultMessage());
assertEquals(4, rm.getSubReporters().size());
assertEquals("Reading UCTE network file", rm.getSubReporters().get(0).getDefaultName());
}

@Test
Expand Down

0 comments on commit 144240b

Please sign in to comment.