Skip to content
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ dependencies {
implementation 'commons-io:commons-io:2.21.0' // I/O functionalities
implementation 'commons-codec:commons-codec:1.20.0' // needed by commons-compress
implementation 'org.apache.commons:commons-compress:1.28.0' // I/O functionalities

implementation 'com.fasterxml.jackson.core:jackson-databind:2.17.2'
}

tasks.withType(JavaCompile) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* © 2025. TU Dortmund University,
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
* Research group Distribution grid planning and operation
*/
package edu.ie3.datamodel.io.connectors;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.function.Function;

/** Connector for JSON-based sources and sinks. */
public class JsonFileConnector extends FileConnector {
private static final String FILE_ENDING = ".json";

public JsonFileConnector(Path baseDirectory) {
super(baseDirectory);
}

public JsonFileConnector(Path baseDirectory, Function<String, InputStream> customInputStream) {
super(baseDirectory, customInputStream);
}

/**
* Opens a buffered reader for the given JSON file, using UTF-8 decoding.
*
* @param filePath relative path without ending
* @return buffered reader referencing the JSON file
*/
public BufferedReader initReader(Path filePath) throws FileNotFoundException {
InputStream inputStream = openInputStream(filePath);
return new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8), 16384);
}

/**
* Opens an input stream for the given JSON file.
*
* @param filePath relative path without ending
* @return input stream for the file
*/
public InputStream initInputStream(Path filePath) throws FileNotFoundException {
return openInputStream(filePath);
}

@Override
protected String getFileEnding() {
return FILE_ENDING;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* © 2025. TU Dortmund University,
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
* Research group Distribution grid planning and operation
*/
package edu.ie3.datamodel.io.factory.markov;

import com.fasterxml.jackson.databind.JsonNode;
import edu.ie3.datamodel.io.factory.Factory;
import edu.ie3.datamodel.models.profile.markov.MarkovLoadModel;
import edu.ie3.datamodel.models.profile.markov.MarkovLoadModel.*;
import java.time.ZonedDateTime;
import java.util.List;
import java.util.Optional;
import java.util.Set;

/** Factory turning Markov JSON data into {@link MarkovLoadModel}s. */
public class MarkovLoadModelFactory
extends Factory<MarkovLoadModel, MarkovModelData, MarkovLoadModel>
implements MarkovModelParsingSupport {

public MarkovLoadModelFactory() {
super(MarkovLoadModel.class);
}

@Override
protected MarkovLoadModel buildModel(MarkovModelData data) {
JsonNode root = data.getRoot();
String schema = requireText(root, "schema");
ZonedDateTime generatedAt = parseTimestamp(requireText(root, "generated_at"));
Generator generator = parseGenerator(requireNode(root, "generator"));
TimeModel timeModel = parseTimeModel(requireNode(root, "time_model"));
ValueModel valueModel = parseValueModel(requireNode(root, "value_model"));
Parameters parameters = parseParameters(root.path("parameters"));

JsonNode dataNode = requireNode(root, "data");
TransitionData transitionData =
parseTransitions(dataNode, timeModel.bucketCount(), valueModel.discretization().states());
GmmBuckets gmmBuckets = parseGmmBuckets(requireNode(dataNode, "gmms"));

return new MarkovLoadModel(
schema,
generatedAt,
generator,
timeModel,
valueModel,
parameters,
transitionData,
Optional.of(gmmBuckets));
}

@Override
protected List<Set<String>> getFields(Class<?> entityClass) {
Set<String> requiredFields =
newSet(
"schema",
"generatedAt",
"generator.name",
"generator.version",
"timeModel.bucketCount",
"timeModel.bucketEncoding.formula",
"timeModel.samplingIntervalMinutes",
"timeModel.timezone",
"valueModel.valueUnit",
"valueModel.normalization.method",
"valueModel.discretization.states",
"valueModel.discretization.thresholdsRight",
"data.transitions.shape",
"data.transitions.values",
"data.gmms.buckets");
return List.of(requiredFields);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* © 2025. TU Dortmund University,
* Institute of Energy Systems, Energy Efficiency and Energy Economics,
* Research group Distribution grid planning and operation
*/
package edu.ie3.datamodel.io.factory.markov;

import com.fasterxml.jackson.databind.JsonNode;
import edu.ie3.datamodel.io.factory.FactoryData;
import edu.ie3.datamodel.models.profile.markov.MarkovLoadModel;
import java.util.Collections;
import java.util.Objects;

/** Factory data wrapper around a parsed Markov-load JSON tree. */
public class MarkovModelData extends FactoryData {
private final JsonNode root;

public MarkovModelData(JsonNode root) {
super(Collections.emptyMap(), MarkovLoadModel.class);
this.root = Objects.requireNonNull(root, "root");
}

public JsonNode getRoot() {
return root;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof MarkovModelData that)) return false;
return Objects.equals(getTargetClass(), that.getTargetClass())
&& Objects.equals(getFieldsToValues(), that.getFieldsToValues())
&& Objects.equals(root, that.root);
}

@Override
public int hashCode() {
return Objects.hash(getTargetClass(), getFieldsToValues(), root);
}
}
Loading