diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..2605b5d32 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,5 @@ +# Reviewers for Dependabot PRs +build.gradle @sebastian-peter @danielfeismann @staudtMarius + +# Reviewers for CI/CD related PRs +.github/workflows/ @sebastian-peter @PhilippSchmelter diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 467a2f6b8..4dd23974a 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -7,12 +7,6 @@ updates: time: "04:00" open-pull-requests-limit: 10 target-branch: dev - reviewers: - - t-ober - - staudtMarius - - sebastian-peter - - danielfeismann - - jo-bao - package-ecosystem: pip directory: "/docs/readthedocs" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 053b6e14d..07dc94b71 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -79,7 +79,7 @@ jobs: ./gradlew sonar \ -Dsonar.projectKey=${{ vars.SONAR_PROJECT_KEY }} \ -Dsonar.host.url=${{ vars.SONAR_HOST_URL }} \ - -Dsonar.login=${{ secrets.SONAR_TOKEN }} \ + -Dsonar.token="${{ secrets.SONAR_TOKEN }}" \ -Dsonar.qualitygate.wait=true #Deployment diff --git a/.github/workflows/dependabot-auto-merge.yml b/.github/workflows/dependabot-auto-merge.yml index aa7c41713..5ed781fd6 100644 --- a/.github/workflows/dependabot-auto-merge.yml +++ b/.github/workflows/dependabot-auto-merge.yml @@ -16,6 +16,19 @@ jobs: with: github-token: "${{ secrets.GITHUB_TOKEN }}" + - name: Check Snapshot + if: contains(steps.metadata.outputs.new-version, 'snap') + run: | + echo "::error::Snapshot versions are not allowed – workflow stopped." + exit 1 + + - name: Approve the PR + if: steps.metadata.outputs.update-type == 'version-update:semver-patch' + run: gh pr review --approve "$PR_URL" + env: + PR_URL: ${{github.event.pull_request.html_url}} + GH_TOKEN: ${{secrets.GITHUB_TOKEN}} + - name: Enable auto-merge for Dependabot PRs if: steps.metadata.outputs.update-type == 'version-update:semver-patch' run: gh pr merge --auto --merge "$PR_URL" diff --git a/CHANGELOG.md b/CHANGELOG.md index 064b97b1b..1d07c6166 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased/Snapshot] +### Added + +### Fixed + +### Changed + +## [8.0.0] - 2025-07-17 + +### Added +- Extend Validation to EnergyManagement Systems. [#1356](https://github.com/ie3-institute/PowerSystemDataModel/issues/1356) + +### Fixed +- Fixed handling of `CongestionResult.InputModelType` in `EntityProcessor` [#1325](https://github.com/ie3-institute/PowerSystemDataModel/issues/1325) +- Fixed em fields in input models [#1331](https://github.com/ie3-institute/PowerSystemDataModel/issues/1331) +- Fixed valid fields for `EmInput` [#1360](https://github.com/ie3-institute/PowerSystemDataModel/issues/1360) + +### Changed +- Updated dependabot workflow and added CODEOWNERS [#1328](https://github.com/ie3-institute/PowerSystemDataModel/issues/1328) +- Extend azimuth angle range to [-180°, 180°] for PV inputs [#1330](https://github.com/ie3-institute/PowerSystemDataModel/issues/1330) +- Improved error messages when reading and validating an invalid grid [#1354](https://github.com/ie3-institute/PowerSystemDataModel/issues/1354) +- Changed `SubgridContainer` to represent galvanically seperated grids [#1226](https://github.com/ie3-institute/PowerSystemDataModel/issues/1226) + ## [7.0.0] - 2025-05-08 ### Added @@ -357,7 +379,8 @@ coordinates or multiple exactly equal coordinates possible - CsvDataSource now stops trying to get an operator for empty operator uuid field in entities - CsvDataSource now parsing multiple geoJson strings correctly -[Unreleased/Snapshot]: https://github.com/ie3-institute/powersystemdatamodel/compare/7.0.0...HEAD +[Unreleased/Snapshot]: +[8.0.0]: https://github.com/ie3-institute/powersystemdatamodel/compare/7.0.0...8.0.0 [7.0.0]: https://github.com/ie3-institute/powersystemdatamodel/compare/6.0.0...7.0.0 [6.0.0]: https://github.com/ie3-institute/powersystemdatamodel/compare/5.1.0...6.0.0 [5.1.0]: https://github.com/ie3-institute/powersystemdatamodel/compare/5.0.1...5.1.0 diff --git a/build.gradle b/build.gradle index c7ac9e64d..d8752419e 100644 --- a/build.gradle +++ b/build.gradle @@ -4,12 +4,12 @@ plugins { id 'maven-publish' id 'signing' id 'pmd' // code check, working on source code - id 'com.diffplug.spotless' version '7.0.3' //code format - id 'com.github.spotbugs' version '6.1.11' // code check, working on byte code + id 'com.diffplug.spotless' version '7.1.0' //code format + id 'com.github.spotbugs' version '6.2.2' // code check, working on byte code id 'de.undercouch.download' version '5.6.0' id 'kr.motd.sphinx' version '2.10.1' // documentation generation id 'jacoco' // java code coverage plugin - id "org.sonarqube" version "6.1.0.5360" // sonarqube + id "org.sonarqube" version "6.2.0.5505" // sonarqube id 'net.thauvin.erik.gradle.semver' version '1.0.4' // semantic versioning id "com.github.johnrengelman.shadow" version "8.1.1" // fat jar } @@ -18,10 +18,10 @@ ext { //version (changing these should be considered thoroughly!) javaVersion = JavaVersion.VERSION_17 groovyVersion = "4.0" - groovyBinaryVersion = "4.0.26" + groovyBinaryVersion = "4.0.27" junitVersion = '1.12.0' - testcontainersVersion = '1.21.0' + testcontainersVersion = '1.21.3' scriptsLocation = 'gradle' + File.separator + 'scripts' + File.separator //location of script plugins } @@ -81,7 +81,7 @@ dependencies { testImplementation "org.junit.jupiter:junit-jupiter:$junitVersion" testImplementation "org.spockframework:spock-core:2.3-groovy-$groovyVersion" testImplementation 'org.objenesis:objenesis:3.4' // Mock creation with constructor parameters - testImplementation 'net.bytebuddy:byte-buddy:1.17.5' // Mocks of classes + testImplementation 'net.bytebuddy:byte-buddy:1.17.6' // Mocks of classes // testcontainers (docker framework for testing) testImplementation "org.testcontainers:testcontainers:$testcontainersVersion" @@ -91,15 +91,15 @@ dependencies { testImplementation "org.testcontainers:couchbase:$testcontainersVersion" // logging - implementation platform('org.apache.logging.log4j:log4j-bom:2.24.3') + implementation platform('org.apache.logging.log4j:log4j-bom:2.25.1') implementation 'org.apache.logging.log4j:log4j-api' // log4j implementation 'org.apache.logging.log4j:log4j-core' // log4j implementation 'org.apache.logging.log4j:log4j-slf4j-impl' // log4j -> slf4j // Databases implementation 'org.influxdb:influxdb-java:2.25' - implementation 'com.couchbase.client:java-client:3.8.0' - runtimeOnly 'org.postgresql:postgresql:42.7.5' // postgresql jdbc driver required during runtime + implementation 'com.couchbase.client:java-client:3.8.3' + runtimeOnly 'org.postgresql:postgresql:42.7.7' // postgresql jdbc driver required during runtime implementation 'commons-io:commons-io:2.19.0' // I/O functionalities implementation 'commons-codec:commons-codec:1.18.0' // needed by commons-compress diff --git a/docs/readthedocs/_static/figures/transformerWithSwitchGear.png b/docs/readthedocs/_static/figures/transformerWithSwitchGear.png index 310ccf99f..0ad8468fc 100644 Binary files a/docs/readthedocs/_static/figures/transformerWithSwitchGear.png and b/docs/readthedocs/_static/figures/transformerWithSwitchGear.png differ diff --git a/docs/readthedocs/_static/figures/transformerWithSwitchGear.tex b/docs/readthedocs/_static/figures/transformerWithSwitchGear.tex index 8ca4ed98a..ac2d44160 100644 --- a/docs/readthedocs/_static/figures/transformerWithSwitchGear.tex +++ b/docs/readthedocs/_static/figures/transformerWithSwitchGear.tex @@ -159,9 +159,9 @@ \begin{tikzpicture} % === Anschlüsse === \node[circle, draw = tuGreen, fill = tuGreen, inner sep = 0, minimum height = 1.5mm] (port_a) at (0,0){}; - \node[circle, draw = tuOrange, fill = tuOrange, inner sep = 0, minimum height = 1.5mm] (port_b) at (15mm,0){}; - \node[circle, draw = tuOrange, fill = tuOrange, inner sep = 0, minimum height = 1.5mm] (port_c) at (30mm,0){}; - \node[circle, draw = tuOrange, fill = tuOrange, inner sep = 0, minimum height = 1.5mm] (port_d) at (45mm,0){}; + \node[circle, draw = tuOrange, fill = tuGreen, inner sep = 0, minimum height = 1.5mm] (port_b) at (15mm,0){}; + \node[circle, draw = tuOrange, fill = tuGreen, inner sep = 0, minimum height = 1.5mm] (port_c) at (30mm,0){}; + \node[circle, draw = tuOrange, fill = tuGreen, inner sep = 0, minimum height = 1.5mm] (port_d) at (45mm,0){}; \node[circle, draw = tuOrange, fill = tuOrange, inner sep = 0, minimum height = 1.5mm] (port_e) at (62.5mm,0){}; \draw (port_a.west) -- ++(-3mm, -1mm) -- ++(0mm, -2mm) edge[densely dotted] ++(0mm, -1.8mm); @@ -176,9 +176,9 @@ \draw (port_d.east) -- (winding_a.west) (winding_b.east) -- (port_e.west); \node[tuGreen, anchor = north, inner sep = 2mm, text width = 10mm, align = center] at (port_a.south) {A \\ \SI{110}{\kV} \\ 1}; - \node[tuOrange, anchor = north, inner sep = 2mm, text width = 10mm, align = center] at (port_b.south) {B \\ \SI{110}{\kV} \\ 2}; - \node[tuOrange, anchor = north, inner sep = 2mm, text width = 10mm, align = center] at (port_c.south) {C \\ \SI{110}{\kV} \\ 2}; - \node[tuOrange, anchor = north, inner sep = 2mm, text width = 10mm, align = center] at (port_d.south) {D \\ \SI{110}{\kV} \\ 2}; + \node[tuOrange, anchor = north, inner sep = 2mm, text width = 10mm, align = center] at (port_b.south) {B \\ \SI{110}{\kV} \\ 1}; + \node[tuOrange, anchor = north, inner sep = 2mm, text width = 10mm, align = center] at (port_c.south) {C \\ \SI{110}{\kV} \\ 1}; + \node[tuOrange, anchor = north, inner sep = 2mm, text width = 10mm, align = center] at (port_d.south) {D \\ \SI{110}{\kV} \\ 1}; \node[tuOrange, anchor = north, inner sep = 2mm, text width = 10mm, align = center] at (port_e.south) {E \\ \SI{10}{\kV} \\ 2}; \end{tikzpicture} \end{document} \ No newline at end of file diff --git a/docs/readthedocs/models/input/em.md b/docs/readthedocs/models/input/em.md index cbb562109..1e875e09f 100644 --- a/docs/readthedocs/models/input/em.md +++ b/docs/readthedocs/models/input/em.md @@ -37,7 +37,7 @@ Participants are connected to an EM each via their `em` field. - - String representation (e.g. name) of a control strategy - * - parentEm + * - controllingEm - - Reference to a superior Energy Management Unit that is controlling this EM. Field can be empty or missing, if this EM itself is not controlled. diff --git a/docs/readthedocs/models/input/grid/gridcontainer.md b/docs/readthedocs/models/input/grid/gridcontainer.md index 24f8e66c4..9c8eebd44 100644 --- a/docs/readthedocs/models/input/grid/gridcontainer.md +++ b/docs/readthedocs/models/input/grid/gridcontainer.md @@ -24,14 +24,11 @@ and their higher voltage coupling point. Let's shed a more detailed light on the boundaries of a sub grid as of our definition. This especially is important, if the switchgear of the transformer is modeled in detail. -We defined, that all nodes in upstream direction of the transformer, that are connected by switches *only* (therefore -are within the switchgear) are counted towards the inferior sub grid structure (here "2"), although they belong to a -different voltage level. -This decision is taken, because we assume, that the interest to operate on the given switchgear will most likely be -placed in the inferior grid structure. - -The "real" coupling node A is not comprised in the sub grids node collection, but obviously has reference through the -switch between nodes A and B. +We defined, that all nodes in upstream direction of the transformer, including those, which are within the switchgear are +counted towards the superior sub grid structure (here "1"), because they belong to a different voltage level. +If a switchgear should be operated by the inferior grid, one can set the operator, that is used in the inferior grid, for +the switchgear. This can be necessary, if we assume, that the interest to operate on the given switchgear will most likely +be placed in the inferior grid structure. A synoptic overview of both classes' attributes is given here: diff --git a/docs/readthedocs/models/input/participant/bm.md b/docs/readthedocs/models/input/participant/bm.md index f75407f12..57af584c8 100644 --- a/docs/readthedocs/models/input/participant/bm.md +++ b/docs/readthedocs/models/input/participant/bm.md @@ -107,7 +107,7 @@ Model of a biomass power plant. - € / MWh - Fixed feed in tariff - * - em + * - controllingEm - - UUID reference to an [Energy Management Unit](#em_model) that is controlling this system participant. Field can be empty or missing, if this participant diff --git a/docs/readthedocs/models/input/participant/chp.md b/docs/readthedocs/models/input/participant/chp.md index 9be96519d..ed1898998 100644 --- a/docs/readthedocs/models/input/participant/chp.md +++ b/docs/readthedocs/models/input/participant/chp.md @@ -114,7 +114,7 @@ Combined heat and power plant. - Whether to adapt output based on (volatile) market price or not - * - em + * - controllingEm - - UUID reference to an [Energy Management Unit](em_model) that is controlling this system participant. Field can be empty or missing, if this participant diff --git a/docs/readthedocs/models/input/participant/ev.md b/docs/readthedocs/models/input/participant/ev.md index b9669eed6..21c191200 100644 --- a/docs/readthedocs/models/input/participant/ev.md +++ b/docs/readthedocs/models/input/participant/ev.md @@ -97,7 +97,7 @@ Model of an electric vehicle, that is occasionally connected to the grid via an - - - * - em + * - controllingEm - - UUID reference to an [Energy Management Unit](#em_model) that is controlling this system participant. Field can be empty or missing, if this participant diff --git a/docs/readthedocs/models/input/participant/evcs.md b/docs/readthedocs/models/input/participant/evcs.md index 83d3218a7..7f187be02 100644 --- a/docs/readthedocs/models/input/participant/evcs.md +++ b/docs/readthedocs/models/input/participant/evcs.md @@ -63,7 +63,7 @@ station and has some limitations outlined below. - Boolean - Vehicle to grid (V2G) support, true if the charging station supports feed in. - * - em + * - controllingEm - - UUID reference to an [Energy Management Unit](#em_model) that is controlling this system participant. Field can be empty or missing, if this participant diff --git a/docs/readthedocs/models/input/participant/fixedfeedin.md b/docs/readthedocs/models/input/participant/fixedfeedin.md index c83570a04..3c17a23e9 100644 --- a/docs/readthedocs/models/input/participant/fixedfeedin.md +++ b/docs/readthedocs/models/input/participant/fixedfeedin.md @@ -49,7 +49,7 @@ model can be derived. - - Rated power factor - * - em + * - controllingEm - - UUID reference to an [Energy Management Unit](#em_model) that is controlling this system participant. Field can be empty or missing, if this participant diff --git a/docs/readthedocs/models/input/participant/hp.md b/docs/readthedocs/models/input/participant/hp.md index 2559c79c5..61c577916 100644 --- a/docs/readthedocs/models/input/participant/hp.md +++ b/docs/readthedocs/models/input/participant/hp.md @@ -93,7 +93,7 @@ Model of a heat pump. - - - * - em + * - controllingEm - - UUID reference to an [Energy Management Unit](#em_model) that is controlling this system participant. Field can be empty or missing, if this participant diff --git a/docs/readthedocs/models/input/participant/load.md b/docs/readthedocs/models/input/participant/load.md index 4ad7f4667..f774f9b87 100644 --- a/docs/readthedocs/models/input/participant/load.md +++ b/docs/readthedocs/models/input/participant/load.md @@ -56,7 +56,7 @@ Model of (mainly) domestic loads. - - Rated power factor - * - em + * - controllingEm - - UUID reference to an [Energy Management Unit](#em_model) that is controlling this system participant. Field can be empty or missing, if this participant diff --git a/docs/readthedocs/models/input/participant/pv.md b/docs/readthedocs/models/input/participant/pv.md index f91f1801b..ffa2db4e5 100644 --- a/docs/readthedocs/models/input/participant/pv.md +++ b/docs/readthedocs/models/input/participant/pv.md @@ -44,8 +44,7 @@ Detailed model of a photovoltaic power plant. * - azimuth - ° - - Inclination in a compass direction - South = 0°, West = 90°, East = -90° + - South = 0°, West = 90°, East = -90°, North = +/- 180° * - etaConv - % @@ -76,7 +75,7 @@ Detailed model of a photovoltaic power plant. - - Rated power factor - * - em + * - controllingEm - - UUID reference to an [Energy Management Unit](#em_model) that is controlling this system participant. Field can be empty or missing, if this participant diff --git a/docs/readthedocs/models/input/participant/storage.md b/docs/readthedocs/models/input/participant/storage.md index 51c25f359..952995c5d 100644 --- a/docs/readthedocs/models/input/participant/storage.md +++ b/docs/readthedocs/models/input/participant/storage.md @@ -107,7 +107,7 @@ Model of an ideal electrical battery energy storage. - Foreseen operation strategy of the storage. Eligible input: *"market"*, *"grid"*, *"self"* - * - em + * - controllingEm - - UUID reference to an [Energy Management Unit](#em_model) that is controlling this system participant. Field can be empty or missing, if this participant diff --git a/docs/readthedocs/models/input/participant/wec.md b/docs/readthedocs/models/input/participant/wec.md index b7d62498c..9ea86fdde 100644 --- a/docs/readthedocs/models/input/participant/wec.md +++ b/docs/readthedocs/models/input/participant/wec.md @@ -106,7 +106,7 @@ Model of a wind energy converter. - Whether to adapt output based on (volatile) market price or not - * - em + * - controllingEm - - UUID reference to an [Energy Management Unit](#em_model) that is controlling this system participant. Field can be empty or missing, if this participant diff --git a/src/main/java/edu/ie3/datamodel/exceptions/DuplicateEntitiesException.java b/src/main/java/edu/ie3/datamodel/exceptions/DuplicateEntitiesException.java index f2a46bce0..eee2942f1 100644 --- a/src/main/java/edu/ie3/datamodel/exceptions/DuplicateEntitiesException.java +++ b/src/main/java/edu/ie3/datamodel/exceptions/DuplicateEntitiesException.java @@ -19,7 +19,7 @@ public DuplicateEntitiesException( this( "The following exception(s) occurred while checking the uniqueness of '" + entityName - + "' entities: " - + ExceptionUtils.getMessages(exceptions)); + + "' entities: \n" + + ExceptionUtils.combineExceptions(exceptions)); } } diff --git a/src/main/java/edu/ie3/datamodel/exceptions/FailedValidationException.java b/src/main/java/edu/ie3/datamodel/exceptions/FailedValidationException.java index b1cc6386b..25e1aa4de 100644 --- a/src/main/java/edu/ie3/datamodel/exceptions/FailedValidationException.java +++ b/src/main/java/edu/ie3/datamodel/exceptions/FailedValidationException.java @@ -23,7 +23,6 @@ public FailedValidationException(String message) { /** @param exceptions List of exceptions, which must not be empty */ public FailedValidationException(List exceptions) { - super( - "Validation failed due to: \n" + ExceptionUtils.getMessages(exceptions), exceptions.get(0)); + super("Validation failed due to:\n " + ExceptionUtils.combineExceptions(exceptions)); } } diff --git a/src/main/java/edu/ie3/datamodel/exceptions/InvalidEntityException.java b/src/main/java/edu/ie3/datamodel/exceptions/InvalidEntityException.java index 744e08c25..162acd0b1 100644 --- a/src/main/java/edu/ie3/datamodel/exceptions/InvalidEntityException.java +++ b/src/main/java/edu/ie3/datamodel/exceptions/InvalidEntityException.java @@ -13,13 +13,12 @@ public class InvalidEntityException extends ValidationException { private static final long serialVersionUID = 809496087520306374L; public InvalidEntityException(String faultDescription, UniqueEntity invalidEntity) { - super("Entity is invalid because of: \n" + faultDescription + " [" + invalidEntity + "]"); + super("Entity is invalid because of: " + faultDescription + " [" + invalidEntity + "]"); } public InvalidEntityException( String faultDescription, Throwable cause, UniqueEntity invalidEntity) { - super( - "Entity is invalid because of: \n" + faultDescription + " [" + invalidEntity + "]", cause); + super("Entity is invalid because of: " + faultDescription + " [" + invalidEntity + "]", cause); } public InvalidEntityException(String message, Throwable cause) { diff --git a/src/main/java/edu/ie3/datamodel/exceptions/SourceException.java b/src/main/java/edu/ie3/datamodel/exceptions/SourceException.java index 2a5a19030..623dc801b 100644 --- a/src/main/java/edu/ie3/datamodel/exceptions/SourceException.java +++ b/src/main/java/edu/ie3/datamodel/exceptions/SourceException.java @@ -32,6 +32,6 @@ public SourceException(final String message) { } public SourceException(String message, List exceptions) { - super(message + " " + ExceptionUtils.getMessages(exceptions), exceptions.get(0)); + super(message + "\n " + ExceptionUtils.combineExceptions(exceptions)); } } diff --git a/src/main/java/edu/ie3/datamodel/io/factory/Factory.java b/src/main/java/edu/ie3/datamodel/io/factory/Factory.java index 9daff0c2d..c5da1cd14 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/Factory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/Factory.java @@ -73,7 +73,7 @@ public Try get(D data) { * {@link Failure} */ public Try get(Try data) { - return data.transformF(FactoryException::new).flatMap(this::get); + return data.transformF(e -> new FactoryException(e.getMessage(), e)).flatMap(this::get); } /** diff --git a/src/main/java/edu/ie3/datamodel/io/factory/input/AssetInputEntityFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/input/AssetInputEntityFactory.java index b9a104137..9670eca99 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/input/AssetInputEntityFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/input/AssetInputEntityFactory.java @@ -24,8 +24,9 @@ public abstract class AssetInputEntityFactory extends UniqueEntityFactory { - private static final String OPERATES_FROM = "operatesFrom"; - private static final String OPERATES_UNTIL = "operatesUntil"; + protected static final String OPERATOR = "operator"; + protected static final String OPERATES_FROM = "operatesFrom"; + protected static final String OPERATES_UNTIL = "operatesUntil"; @SafeVarargs protected AssetInputEntityFactory(Class... allowedClasses) { @@ -48,14 +49,33 @@ protected List> getFields(Class entityClass) { Set constructorParamsUntil = expandSet(constructorParamsMin, OPERATES_UNTIL); Set constructorParamsBoth = expandSet(constructorParamsFrom, OPERATES_UNTIL); + // with operator field + Set constructorParamsOperator = expandSet(constructorParamsMin, OPERATOR); + Set constructorParamsOperatorFrom = expandSet(constructorParamsFrom, OPERATOR); + Set constructorParamsOperatorUntil = expandSet(constructorParamsUntil, OPERATOR); + Set constructorParamsOperatorBoth = expandSet(constructorParamsBoth, OPERATOR); + final String[] additionalFields = getAdditionalFields(); constructorParamsMin = expandSet(constructorParamsMin, additionalFields); constructorParamsFrom = expandSet(constructorParamsFrom, additionalFields); constructorParamsUntil = expandSet(constructorParamsUntil, additionalFields); constructorParamsBoth = expandSet(constructorParamsBoth, additionalFields); + + constructorParamsOperator = expandSet(constructorParamsOperator, additionalFields); + constructorParamsOperatorFrom = expandSet(constructorParamsOperatorFrom, additionalFields); + constructorParamsOperatorUntil = expandSet(constructorParamsOperatorUntil, additionalFields); + constructorParamsOperatorBoth = expandSet(constructorParamsOperatorBoth, additionalFields); + return Arrays.asList( - constructorParamsMin, constructorParamsFrom, constructorParamsUntil, constructorParamsBoth); + constructorParamsMin, + constructorParamsFrom, + constructorParamsUntil, + constructorParamsBoth, + constructorParamsOperator, + constructorParamsOperatorFrom, + constructorParamsOperatorUntil, + constructorParamsOperatorBoth); } /** diff --git a/src/main/java/edu/ie3/datamodel/io/factory/input/EmAssetInputEntityData.java b/src/main/java/edu/ie3/datamodel/io/factory/input/EmAssetInputEntityData.java index d001c405e..a51835568 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/input/EmAssetInputEntityData.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/input/EmAssetInputEntityData.java @@ -19,23 +19,23 @@ */ public class EmAssetInputEntityData extends AssetInputEntityData { - private final EmInput emUnit; + private final EmInput controllingEm; public EmAssetInputEntityData( Map fieldsToAttributes, Class entityClass, - EmInput emUnit) { + EmInput controllingEm) { super(fieldsToAttributes, entityClass); - this.emUnit = emUnit; + this.controllingEm = controllingEm; } public EmAssetInputEntityData( Map fieldsToAttributes, Class entityClass, OperatorInput operator, - EmInput emUnit) { + EmInput controllingEm) { super(fieldsToAttributes, entityClass, operator); - this.emUnit = emUnit; + this.controllingEm = controllingEm; } /** @@ -43,15 +43,15 @@ public EmAssetInputEntityData( * object and given em unit * * @param entityData The entity data object to use attributes of - * @param emUnit The em input to use + * @param controllingEm The controlling em input to use */ - public EmAssetInputEntityData(AssetInputEntityData entityData, EmInput emUnit) { + public EmAssetInputEntityData(AssetInputEntityData entityData, EmInput controllingEm) { super(entityData, entityData.getOperatorInput()); - this.emUnit = emUnit; + this.controllingEm = controllingEm; } - public EmInput getEmUnit() { - return emUnit; + public EmInput getControllingEm() { + return controllingEm; } @Override @@ -60,11 +60,11 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) return false; if (!super.equals(o)) return false; EmAssetInputEntityData that = (EmAssetInputEntityData) o; - return Objects.equals(emUnit, that.emUnit); + return Objects.equals(controllingEm, that.controllingEm); } @Override public int hashCode() { - return Objects.hash(super.hashCode(), emUnit); + return Objects.hash(super.hashCode(), controllingEm); } } diff --git a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/EmInputFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/input/EmInputFactory.java similarity index 55% rename from src/main/java/edu/ie3/datamodel/io/factory/input/participant/EmInputFactory.java rename to src/main/java/edu/ie3/datamodel/io/factory/input/EmInputFactory.java index 3c4590d6e..85e15822d 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/EmInputFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/input/EmInputFactory.java @@ -3,43 +3,26 @@ * Institute of Energy Systems, Energy Efficiency and Energy Economics, * Research group Distribution grid planning and operation */ -package edu.ie3.datamodel.io.factory.input.participant; +package edu.ie3.datamodel.io.factory.input; -import edu.ie3.datamodel.io.factory.input.AssetInputEntityFactory; -import edu.ie3.datamodel.io.factory.input.EmAssetInputEntityData; import edu.ie3.datamodel.models.OperationTime; import edu.ie3.datamodel.models.input.EmInput; import edu.ie3.datamodel.models.input.OperatorInput; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.UUID; +import java.util.*; public class EmInputFactory extends AssetInputEntityFactory { private static final String CONTROL_STRATEGY = "controlStrategy"; - public static final String PARENT_EM = "parentem"; + public static final String CONTROLLING_EM = "controllingEm"; public EmInputFactory() { super(EmInput.class); } - @Override - protected List> getFields(Class entityClass) { - List> fields = new ArrayList<>(super.getFields(entityClass)); - - List> withEm = - fields.stream().map(f -> (Set) expandSet(f, PARENT_EM)).toList(); - - fields.addAll(withEm); - - return fields; - } - @Override protected String[] getAdditionalFields() { - return new String[] {CONTROL_STRATEGY}; + return new String[] {CONTROL_STRATEGY, CONTROLLING_EM}; } @Override @@ -51,7 +34,7 @@ protected EmInput buildModel( OperationTime operationTime) { String controlStrategy = data.getField(CONTROL_STRATEGY); - EmInput parentEm = data.getEmUnit(); + EmInput parentEm = data.getControllingEm(); return new EmInput(uuid, id, operator, operationTime, controlStrategy, parentEm); } diff --git a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/BmInputFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/BmInputFactory.java index 8a1c58b9e..dd17b0fb0 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/BmInputFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/BmInputFactory.java @@ -42,7 +42,7 @@ protected BmInput buildModel( ReactivePowerCharacteristic qCharacteristics, OperatorInput operator, OperationTime operationTime) { - final EmInput em = data.getEm().orElse(null); + final EmInput em = data.getControllingEm().orElse(null); final BmTypeInput typeInput = data.getTypeInput(); final boolean marketReaction = data.getBoolean(MARKET_REACTION); final boolean costControlled = data.getBoolean(COST_CONTROLLED); diff --git a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/ChpInputFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/ChpInputFactory.java index d398f5a59..db7bb3cdf 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/ChpInputFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/ChpInputFactory.java @@ -35,7 +35,7 @@ protected ChpInput buildModel( ReactivePowerCharacteristic qCharacteristics, OperatorInput operator, OperationTime operationTime) { - final EmInput em = data.getEm().orElse(null); + final EmInput em = data.getControllingEm().orElse(null); final boolean marketReaction = data.getBoolean(MARKET_REACTION); return new ChpInput( diff --git a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/EvInputFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/EvInputFactory.java index b2d492ce5..a24abad06 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/EvInputFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/EvInputFactory.java @@ -36,7 +36,7 @@ protected EvInput buildModel( ReactivePowerCharacteristic qCharacteristics, OperatorInput operator, OperationTime operationTime) { - final EmInput em = data.getEm().orElse(null); + final EmInput em = data.getControllingEm().orElse(null); return new EvInput( uuid, id, operator, operationTime, node, qCharacteristics, em, data.getTypeInput()); diff --git a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/EvcsInputFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/EvcsInputFactory.java index a0bc9e9c0..46b75a9f9 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/EvcsInputFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/EvcsInputFactory.java @@ -54,7 +54,7 @@ protected EvcsInput buildModel( ReactivePowerCharacteristic qCharacteristics, OperatorInput operator, OperationTime operationTime) { - final EmInput em = data.getEm().orElse(null); + final EmInput em = data.getControllingEm().orElse(null); final ChargingPointType type; try { type = ChargingPointTypeUtils.parse(data.getField(TYPE)); diff --git a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/FixedFeedInInputFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/FixedFeedInInputFactory.java index f0b6e28a9..257c40974 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/FixedFeedInInputFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/FixedFeedInInputFactory.java @@ -40,7 +40,7 @@ protected FixedFeedInInput buildModel( ReactivePowerCharacteristic qCharacteristics, OperatorInput operator, OperationTime operationTime) { - final EmInput em = data.getEm().orElse(null); + final EmInput em = data.getControllingEm().orElse(null); final ComparableQuantity sRated = data.getQuantity(S_RATED, StandardUnits.S_RATED); final double cosPhiRated = data.getDouble(COSPHI_RATED); diff --git a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/HpInputFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/HpInputFactory.java index b01ede298..d075d64a3 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/HpInputFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/HpInputFactory.java @@ -34,7 +34,7 @@ protected HpInput buildModel( ReactivePowerCharacteristic qCharacteristics, OperatorInput operator, OperationTime operationTime) { - final EmInput em = data.getEm().orElse(null); + final EmInput em = data.getControllingEm().orElse(null); return new HpInput( uuid, diff --git a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/LoadInputFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/LoadInputFactory.java index c66cec08f..71af7c515 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/LoadInputFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/LoadInputFactory.java @@ -58,7 +58,7 @@ protected LoadInput buildModel( id); loadProfile = LoadProfile.DefaultLoadProfiles.NO_LOAD_PROFILE; } - final EmInput em = data.getEm().orElse(null); + final EmInput em = data.getControllingEm().orElse(null); final ComparableQuantity eConsAnnual = data.getQuantity(E_CONS_ANNUAL, StandardUnits.ENERGY_IN); diff --git a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/PvInputFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/PvInputFactory.java index 6cb13b79f..70f7253fc 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/PvInputFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/PvInputFactory.java @@ -50,7 +50,7 @@ protected PvInput buildModel( ReactivePowerCharacteristic qCharacteristics, OperatorInput operator, OperationTime operationTime) { - final EmInput em = data.getEm().orElse(null); + final EmInput em = data.getControllingEm().orElse(null); final double albedo = data.getDouble(ALBEDO); final ComparableQuantity azimuth = data.getQuantity(AZIMUTH, StandardUnits.AZIMUTH); final ComparableQuantity etaConv = diff --git a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/StorageInputFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/StorageInputFactory.java index aea43ba85..4b9149525 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/StorageInputFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/StorageInputFactory.java @@ -36,7 +36,7 @@ protected StorageInput buildModel( ReactivePowerCharacteristic qCharacteristics, OperatorInput operator, OperationTime operationTime) { - final EmInput em = data.getEm().orElse(null); + final EmInput em = data.getControllingEm().orElse(null); final StorageTypeInput typeInput = data.getTypeInput(); return new StorageInput( uuid, id, operator, operationTime, node, qCharacteristics, em, typeInput); diff --git a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/SystemParticipantEntityData.java b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/SystemParticipantEntityData.java index 971832be4..5304124f2 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/SystemParticipantEntityData.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/SystemParticipantEntityData.java @@ -22,7 +22,7 @@ public class SystemParticipantEntityData extends NodeAssetInputEntityData { /** Energy management unit that is managing the system participant. Can be null. */ - private final EmInput em; + private final EmInput controllingEm; /** * Creates a new SystemParticipantEntityData object for an operated, always on system participant @@ -31,20 +31,20 @@ public class SystemParticipantEntityData extends NodeAssetInputEntityData { * @param fieldsToAttributes attribute map: field name to value * @param entityClass class of the entity to be created with this data * @param node input node - * @param em The energy management unit that is managing the system participant. Null, if the - * system participant is not managed. + * @param controllingEm The energy management unit that is managing the system participant. Null, + * if the system participant is not managed. */ public SystemParticipantEntityData( Map fieldsToAttributes, Class entityClass, NodeInput node, - EmInput em) { + EmInput controllingEm) { super(fieldsToAttributes, entityClass, node); - this.em = em; + this.controllingEm = controllingEm; } - public Optional getEm() { - return Optional.ofNullable(em); + public Optional getControllingEm() { + return Optional.ofNullable(controllingEm); } /** @@ -54,17 +54,17 @@ public Optional getEm() { * @param entityClass class of the entity to be created with this data * @param operator operator input * @param node input node - * @param em The energy management unit that is managing the system participant. Null, if the - * system participant is not managed. + * @param controllingEm The energy management unit that is managing the system participant. Null, + * if the system participant is not managed. */ public SystemParticipantEntityData( Map fieldsToAttributes, Class entityClass, OperatorInput operator, NodeInput node, - EmInput em) { + EmInput controllingEm) { super(fieldsToAttributes, entityClass, operator, node); - this.em = em; + this.controllingEm = controllingEm; } /** @@ -72,20 +72,20 @@ public SystemParticipantEntityData( * NodeAssetInputEntityData} object and given energy management unit * * @param nodeAssetInputEntityData The node asset entity data object to use attributes of - * @param em The energy management unit that is managing the system participant. Null, if the - * system participant is not managed. + * @param controllingEm The energy management unit that is managing the system participant. Null, + * if the system participant is not managed. */ public SystemParticipantEntityData( - NodeAssetInputEntityData nodeAssetInputEntityData, EmInput em) { + NodeAssetInputEntityData nodeAssetInputEntityData, EmInput controllingEm) { super(nodeAssetInputEntityData, nodeAssetInputEntityData.getNode()); - this.em = em; + this.controllingEm = controllingEm; } @Override public String toString() { return "SystemParticipantEntityData{" + "em=" - + getEm().map(EmInput::toString).orElse("") + + getControllingEm().map(EmInput::toString).orElse("") + ", node=" + getNode().getUuid() + ", operatorInput=" @@ -103,11 +103,11 @@ public boolean equals(Object o) { if (o == null || getClass() != o.getClass()) return false; if (!super.equals(o)) return false; SystemParticipantEntityData that = (SystemParticipantEntityData) o; - return getEm().equals(that.getEm()); + return getControllingEm().equals(that.getControllingEm()); } @Override public int hashCode() { - return Objects.hash(super.hashCode(), getEm()); + return Objects.hash(super.hashCode(), getControllingEm()); } } diff --git a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/SystemParticipantInputEntityFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/SystemParticipantInputEntityFactory.java index 298bdfe92..d3a1939c6 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/SystemParticipantInputEntityFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/SystemParticipantInputEntityFactory.java @@ -32,7 +32,7 @@ public abstract class SystemParticipantInputEntityFactory< private static final String Q_CHARACTERISTICS = "qCharacteristics"; - public static final String EM = "em"; + public static final String CONTROLLING_EM = "controllingEm"; protected SystemParticipantInputEntityFactory(Class... allowedClasses) { super(allowedClasses); @@ -43,7 +43,8 @@ protected List> getFields(Class entityClass) { List> fields = new ArrayList<>(super.getFields(entityClass)); for (Set set : fields) set.add(Q_CHARACTERISTICS); - List> withEm = fields.stream().map(f -> (Set) expandSet(f, EM)).toList(); + List> withEm = + fields.stream().map(f -> (Set) expandSet(f, CONTROLLING_EM)).toList(); fields.addAll(withEm); diff --git a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/SystemParticipantTypedEntityData.java b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/SystemParticipantTypedEntityData.java index ab0bbe4b3..a57d814ed 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/SystemParticipantTypedEntityData.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/SystemParticipantTypedEntityData.java @@ -80,7 +80,7 @@ public SystemParticipantTypedEntityData( */ public SystemParticipantTypedEntityData( SystemParticipantEntityData systemParticipantEntityData, T typeInput) { - super(systemParticipantEntityData, systemParticipantEntityData.getEm().orElse(null)); + super(systemParticipantEntityData, systemParticipantEntityData.getControllingEm().orElse(null)); this.typeInput = typeInput; } @@ -94,7 +94,7 @@ public String toString() { + "typeInput=" + typeInput.getUuid() + ", em=" - + getEm().map(EmInput::toString).orElse("") + + getControllingEm().map(EmInput::toString).orElse("") + ", node=" + getNode().getUuid() + ", operatorInput=" diff --git a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/WecInputFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/WecInputFactory.java index 5d8fbca71..a1724fcac 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/input/participant/WecInputFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/input/participant/WecInputFactory.java @@ -38,7 +38,7 @@ protected WecInput buildModel( OperatorInput operator, OperationTime operationTime) { WecTypeInput typeInput = data.getTypeInput(); - EmInput em = data.getEm().orElse(null); + EmInput em = data.getControllingEm().orElse(null); final boolean marketReaction = data.getBoolean(MARKET_REACTION); return new WecInput( diff --git a/src/main/java/edu/ie3/datamodel/io/processor/Processor.java b/src/main/java/edu/ie3/datamodel/io/processor/Processor.java index 194edd8f7..a97e20232 100644 --- a/src/main/java/edu/ie3/datamodel/io/processor/Processor.java +++ b/src/main/java/edu/ie3/datamodel/io/processor/Processor.java @@ -15,6 +15,7 @@ import edu.ie3.datamodel.models.input.connector.SwitchInput; import edu.ie3.datamodel.models.input.system.characteristic.CharacteristicInput; import edu.ie3.datamodel.models.profile.LoadProfile; +import edu.ie3.datamodel.models.result.CongestionResult; import edu.ie3.datamodel.models.voltagelevels.VoltageLevel; import edu.ie3.datamodel.utils.Try; import edu.ie3.datamodel.utils.Try.*; @@ -293,6 +294,8 @@ protected String processMethodResult(Object methodReturnObject, Method method, S "ReactivePowerCharacteristic", "CharacteristicInput" -> resultStringBuilder.append( ((CharacteristicInput) methodReturnObject).serialize()); + case "InputModelType" -> resultStringBuilder.append( + ((CongestionResult.InputModelType) methodReturnObject).type); default -> throw new EntityProcessorException( "Unable to process value for attribute/field '" + fieldName diff --git a/src/main/java/edu/ie3/datamodel/io/processor/ProcessorProvider.java b/src/main/java/edu/ie3/datamodel/io/processor/ProcessorProvider.java index f1858c44b..9cb9ee5a0 100644 --- a/src/main/java/edu/ie3/datamodel/io/processor/ProcessorProvider.java +++ b/src/main/java/edu/ie3/datamodel/io/processor/ProcessorProvider.java @@ -6,7 +6,6 @@ package edu.ie3.datamodel.io.processor; import edu.ie3.datamodel.exceptions.EntityProcessorException; -import edu.ie3.datamodel.exceptions.FailureException; import edu.ie3.datamodel.exceptions.ProcessorProviderException; import edu.ie3.datamodel.io.processor.input.InputEntityProcessor; import edu.ie3.datamodel.io.processor.result.ResultEntityProcessor; @@ -313,25 +312,22 @@ public static Collection> allResultEntityProce Value, Value>> allTimeSeriesProcessors() throws EntityProcessorException { - try { - return Try.scanStream( - TimeSeriesProcessor.eligibleKeys.stream() - .map( - key -> - Try.of( - () -> - new TimeSeriesProcessor<>( - (Class, Value, Value>>) - key.getTimeSeriesClass(), - (Class>) key.getEntryClass(), - (Class) key.getValueClass()), - EntityProcessorException.class)), - "list of processors") - .getOrThrow() - .collect(Collectors.toMap(TimeSeriesProcessor::getRegisteredKey, Function.identity())); - } catch (FailureException e) { - throw new EntityProcessorException(e.getCause()); - } + return Try.scanStream( + TimeSeriesProcessor.eligibleKeys.stream() + .map( + key -> + Try.of( + () -> + new TimeSeriesProcessor<>( + (Class, Value, Value>>) + key.getTimeSeriesClass(), + (Class>) key.getEntryClass(), + (Class) key.getValueClass()), + EntityProcessorException.class)), + "time series processors", + EntityProcessorException::new) + .getOrThrow() + .collect(Collectors.toMap(TimeSeriesProcessor::getRegisteredKey, Function.identity())); } @SuppressWarnings("unchecked cast") diff --git a/src/main/java/edu/ie3/datamodel/io/source/EnergyManagementSource.java b/src/main/java/edu/ie3/datamodel/io/source/EnergyManagementSource.java index 8a5cce317..5cea8a531 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/EnergyManagementSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/EnergyManagementSource.java @@ -5,13 +5,13 @@ */ package edu.ie3.datamodel.io.source; -import static edu.ie3.datamodel.io.factory.input.participant.EmInputFactory.PARENT_EM; +import static edu.ie3.datamodel.io.factory.input.EmInputFactory.CONTROLLING_EM; import edu.ie3.datamodel.exceptions.SourceException; import edu.ie3.datamodel.exceptions.ValidationException; import edu.ie3.datamodel.io.factory.input.AssetInputEntityData; import edu.ie3.datamodel.io.factory.input.EmAssetInputEntityData; -import edu.ie3.datamodel.io.factory.input.participant.EmInputFactory; +import edu.ie3.datamodel.io.factory.input.EmInputFactory; import edu.ie3.datamodel.models.input.EmInput; import edu.ie3.datamodel.models.input.OperatorInput; import edu.ie3.datamodel.utils.Try; @@ -96,7 +96,8 @@ private static Map createEmInputs( dataTry .map( data -> - data.containsKey(PARENT_EM) && !data.getField(PARENT_EM).isBlank()) + data.containsKey(CONTROLLING_EM) + && !data.getField(CONTROLLING_EM).isBlank()) .getOrElse(() -> true))); List> rootEmsEntityData = split.get(false); @@ -129,7 +130,7 @@ private static Map createEmInputs( data -> { // we already filtered out those entities that do not have a parent, // so the field should exist - String uuidString = data.getField(PARENT_EM); + String uuidString = data.getField(CONTROLLING_EM); return Try.of( () -> UUID.fromString(uuidString), IllegalArgumentException.class) @@ -138,7 +139,7 @@ private static Map createEmInputs( new SourceException( String.format( "Exception while trying to parse UUID of field \"%s\" with value \"%s\"", - PARENT_EM, uuidString), + CONTROLLING_EM, uuidString), iae)) // failed UUID parses are filtered out at this point. We save // the parsed UUID with the asset data @@ -199,7 +200,7 @@ private static Map createHierarchicalEmInputs( /** * Helper data record that holds an {@link AssetInputEntityData} and the UUID successfully parsed - * from {@link EmInputFactory#PARENT_EM} field + * from {@link EmInputFactory#CONTROLLING_EM} field */ private record AssetDataAndValidParentUuid(AssetInputEntityData entityData, UUID parentEm) {} } diff --git a/src/main/java/edu/ie3/datamodel/io/source/EntitySource.java b/src/main/java/edu/ie3/datamodel/io/source/EntitySource.java index be0cdea31..0c4d9c1d6 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/EntitySource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/EntitySource.java @@ -204,14 +204,12 @@ protected static Stream getEntities( * @return a stream of the entity data wrapped in a {@link Try} */ protected static Stream> buildEntityData( - Class entityClass, DataSource dataSource) { - return Try.of(() -> dataSource.getSourceData(entityClass), SourceException.class) - .convert( - data -> - data.map( - fieldsToAttributes -> - new Try.Success<>(new EntityData(fieldsToAttributes, entityClass))), - exception -> Stream.of(Failure.of(exception))); + Class entityClass, DataSource dataSource) throws SourceException { + return dataSource + .getSourceData(entityClass) + .map( + fieldsToAttributes -> + new Try.Success<>(new EntityData(fieldsToAttributes, entityClass))); } /** @@ -227,7 +225,8 @@ protected static Stream> buildEntityData( protected static Stream> buildEntityData( Class entityClass, DataSource dataSource, - WrappedFunction converter) { + WrappedFunction converter) + throws SourceException { return buildEntityData(entityClass, dataSource).map(converter); } @@ -356,9 +355,7 @@ Function, R> enrichFunction( */ protected static Stream unpack( Stream> inputStream, Class clazz) throws SourceException { - return Try.scanStream(inputStream, clazz.getSimpleName()) - .transformF(SourceException::new) - .getOrThrow(); + return Try.scanStream(inputStream, clazz.getSimpleName(), SourceException::new).getOrThrow(); } /** @@ -376,16 +373,14 @@ protected static Try extractFuncti return entityData.flatMap( data -> Try.of(() -> data.getUUID(fieldName), FactoryException.class) + .flatMap(entityUuid -> extractFunction(entityUuid, entities)) .transformF( exception -> new SourceException( - "Extracting UUID field " + "Extracting UUID for field '" + fieldName - + " from entity data " - + entityData - + " failed.", - exception)) - .flatMap(entityUuid -> extractFunction(entityUuid, entities))); + + "' failed. Caused by: " + + exception.getMessage()))); } /** @@ -396,13 +391,13 @@ protected static Try extractFuncti * @return a try of the {@link Entity} * @param type of entity */ - protected static Try extractFunction(UUID uuid, Map entityMap) { + protected static Try extractFunction(UUID uuid, Map entityMap) { return Optional.ofNullable(entityMap.get(uuid)) // We either find a matching entity for given UUID, thus return a success - .map(entity -> Try.of(() -> entity, SourceException.class)) + .map(entity -> Try.of(() -> entity, FactoryException.class)) // ... or find no matching entity, returning a failure. .orElse( - new Failure<>(new SourceException("Entity with uuid " + uuid + " was not provided."))); + new Failure<>(new FactoryException("Entity with uuid " + uuid + " was not provided."))); } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= diff --git a/src/main/java/edu/ie3/datamodel/io/source/GraphicSource.java b/src/main/java/edu/ie3/datamodel/io/source/GraphicSource.java index 339f3f638..904e0a42d 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/GraphicSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/GraphicSource.java @@ -59,8 +59,8 @@ public void validate() throws ValidationException { Stream.of( validate(NodeGraphicInput.class, dataSource, nodeGraphicInputFactory), validate(LineGraphicInput.class, dataSource, lineGraphicInputFactory)), - "Validation") - .transformF(FailedValidationException::new) + "Validation", + FailedValidationException::new) .getOrThrow(); } @@ -95,11 +95,13 @@ public GraphicElements getGraphicElements(Map nodes, Map, SourceException> lineGraphics = Try.of(() -> getLineGraphicInput(lines), SourceException.class); - List exceptions = Try.getExceptions(List.of(nodeGraphics, lineGraphics)); + List exceptions = Try.getExceptions(nodeGraphics, lineGraphics); if (!exceptions.isEmpty()) { throw new GraphicSourceException( - exceptions.size() + " error(s) occurred while initializing graphic elements. ", + "Exception(s) occurred in " + + exceptions.size() + + " input file(s) while initializing graphic elements. ", exceptions); } else { // if everything is fine, return a GraphicElements instance diff --git a/src/main/java/edu/ie3/datamodel/io/source/RawGridSource.java b/src/main/java/edu/ie3/datamodel/io/source/RawGridSource.java index 46d9432b5..0fde7ede6 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/RawGridSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/RawGridSource.java @@ -5,11 +5,19 @@ */ package edu.ie3.datamodel.io.source; -import edu.ie3.datamodel.exceptions.*; +import edu.ie3.datamodel.exceptions.FailedValidationException; +import edu.ie3.datamodel.exceptions.RawGridException; +import edu.ie3.datamodel.exceptions.SourceException; +import edu.ie3.datamodel.exceptions.ValidationException; import edu.ie3.datamodel.io.factory.EntityData; import edu.ie3.datamodel.io.factory.input.*; -import edu.ie3.datamodel.models.input.*; -import edu.ie3.datamodel.models.input.connector.*; +import edu.ie3.datamodel.models.input.MeasurementUnitInput; +import edu.ie3.datamodel.models.input.NodeInput; +import edu.ie3.datamodel.models.input.OperatorInput; +import edu.ie3.datamodel.models.input.connector.LineInput; +import edu.ie3.datamodel.models.input.connector.SwitchInput; +import edu.ie3.datamodel.models.input.connector.Transformer2WInput; +import edu.ie3.datamodel.models.input.connector.Transformer3WInput; import edu.ie3.datamodel.models.input.connector.type.LineTypeInput; import edu.ie3.datamodel.models.input.connector.type.Transformer2WTypeInput; import edu.ie3.datamodel.models.input.connector.type.Transformer3WTypeInput; @@ -62,8 +70,8 @@ public void validate() throws ValidationException { validate(Transformer3WInput.class, dataSource, transformer3WInputFactory), validate(SwitchInput.class, dataSource, switchInputFactory), validate(MeasurementUnitInput.class, dataSource, measurementUnitInputFactory)), - "Validation") - .transformF(FailedValidationException::new) + "Validation", + FailedValidationException::new) .getOrThrow(); } @@ -146,12 +154,14 @@ public RawGridElements getGridData( Try.of(() -> getMeasurementUnits(operators, nodes), SourceException.class); List exceptions = - Try.getExceptions( - List.of(transformer2WInputs, transformer3WInputs, switches, measurementUnits)); + Try.getExceptions(transformer2WInputs, transformer3WInputs, switches, measurementUnits); if (!exceptions.isEmpty()) { throw new RawGridException( - exceptions.size() + " error(s) occurred while initializing raw grid. ", exceptions); + "Exception(s) occurred in " + + exceptions.size() + + " input file(s) while initializing raw grid.", + exceptions); } else { /* build and return the grid if it is not empty */ // getOrThrow should not throw an exception in this context, because all exception are diff --git a/src/main/java/edu/ie3/datamodel/io/source/ResultEntitySource.java b/src/main/java/edu/ie3/datamodel/io/source/ResultEntitySource.java index d1889c4bd..1e555cc56 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/ResultEntitySource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/ResultEntitySource.java @@ -105,9 +105,7 @@ public void validate() throws ValidationException { validate(FlexOptionsResult.class, dataSource, flexOptionsResultFactory), validate(CongestionResult.class, dataSource, congestionResultFactory))); - Try.scanCollection(participantResults, Void.class) - .transformF(FailedValidationException::new) - .getOrThrow(); + Try.scanCollection(participantResults, Void.class, FailedValidationException::new).getOrThrow(); } /** diff --git a/src/main/java/edu/ie3/datamodel/io/source/SystemParticipantSource.java b/src/main/java/edu/ie3/datamodel/io/source/SystemParticipantSource.java index 3df433dac..fd4c0f2cc 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/SystemParticipantSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/SystemParticipantSource.java @@ -64,7 +64,7 @@ public class SystemParticipantSource extends AssetEntitySource { .andThen(enrich(NODE, nodes, NodeAssetInputEntityData::new)) .andThen( enrichWithDefault( - SystemParticipantInputEntityFactory.EM, + SystemParticipantInputEntityFactory.CONTROLLING_EM, emUnits, null, SystemParticipantEntityData::new)) @@ -110,8 +110,8 @@ public void validate() throws ValidationException { validate(StorageInput.class, dataSource, storageInputFactory), validate(WecInput.class, dataSource, wecInputFactory), validate(EvcsInput.class, dataSource, evcsInputFactory)), - "Validation") - .transformF(FailedValidationException::new) + "Validation", + FailedValidationException::new) .getOrThrow(); } @@ -212,21 +212,22 @@ public SystemParticipants getSystemParticipants( List exceptions = Try.getExceptions( - List.of( - fixedFeedInInputs, - pvInputs, - loads, - bmInputs, - storages, - wecInputs, - evs, - evcs, - chpInputs, - hpInputs)); + fixedFeedInInputs, + pvInputs, + loads, + bmInputs, + storages, + wecInputs, + evs, + evcs, + chpInputs, + hpInputs); if (!exceptions.isEmpty()) { throw new SystemParticipantsException( - exceptions.size() + " error(s) occurred while initializing system participants. ", + "Exception(s) occurred in " + + exceptions.size() + + " input file(s) while initializing system participants.", exceptions); } else { // if everything is fine, return a system participants container diff --git a/src/main/java/edu/ie3/datamodel/io/source/ThermalSource.java b/src/main/java/edu/ie3/datamodel/io/source/ThermalSource.java index f8d73a0a7..bc955ff82 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/ThermalSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/ThermalSource.java @@ -65,8 +65,8 @@ public void validate() throws ValidationException { dataSource, domesticHotWaterStorageInputFactory), validate(ThermalHouseInput.class, dataSource, thermalHouseInputFactory)), - "Validation") - .transformF(FailedValidationException::new) + "Validation", + FailedValidationException::new) .getOrThrow(); } diff --git a/src/main/java/edu/ie3/datamodel/io/source/TimeSeriesMappingSource.java b/src/main/java/edu/ie3/datamodel/io/source/TimeSeriesMappingSource.java index 15e5b63e4..eeb956b56 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/TimeSeriesMappingSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/TimeSeriesMappingSource.java @@ -38,10 +38,12 @@ public void validate() throws ValidationException { * @return That mapping */ public Map getMapping() throws SourceException { - return Try.scanStream(getMappingSourceData().map(this::createMappingEntry), "MappingEntry") - .transform( - s -> s.collect(Collectors.toMap(MappingEntry::getAsset, MappingEntry::getTimeSeries)), + return Try.scanStream( + getMappingSourceData().map(this::createMappingEntry), + "MappingEntry", SourceException::new) + .transformS( + s -> s.collect(Collectors.toMap(MappingEntry::getAsset, MappingEntry::getTimeSeries))) .getOrThrow(); } diff --git a/src/main/java/edu/ie3/datamodel/io/source/TypeSource.java b/src/main/java/edu/ie3/datamodel/io/source/TypeSource.java index 16b2a9f4f..67f3ecd0b 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/TypeSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/TypeSource.java @@ -74,9 +74,7 @@ public void validate() throws ValidationException { validate(Transformer2WTypeInput.class, dataSource, transformer2WTypeInputFactory), validate(Transformer3WTypeInput.class, dataSource, transformer3WTypeInputFactory))); - Try.scanCollection(participantResults, Void.class) - .transformF(FailedValidationException::new) - .getOrThrow(); + Try.scanCollection(participantResults, Void.class, FailedValidationException::new).getOrThrow(); } /** diff --git a/src/main/java/edu/ie3/datamodel/io/source/WeatherSource.java b/src/main/java/edu/ie3/datamodel/io/source/WeatherSource.java index a7a056d85..94fdbd733 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/WeatherSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/WeatherSource.java @@ -170,8 +170,9 @@ protected List> buildTimeBasedValues( return factory.get( Try.from(data, () -> new SourceException("Missing data in: " + data))); }), - "TimeBasedValue") - .transform(Stream::toList, SourceException::new) + "TimeBasedValue", + SourceException::new) + .transformS(Stream::toList) .getOrThrow(); } } diff --git a/src/main/java/edu/ie3/datamodel/io/source/csv/CsvDataSource.java b/src/main/java/edu/ie3/datamodel/io/source/csv/CsvDataSource.java index 78aa77f75..6879b57eb 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/csv/CsvDataSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/csv/CsvDataSource.java @@ -79,8 +79,19 @@ public Optional> getSourceFields(Class entityClass */ public Optional> getSourceFields(Path filePath) throws SourceException { try (BufferedReader reader = connector.initReader(filePath)) { - return Optional.of( - Arrays.stream(parseCsvRow(reader.readLine(), csvSep)).collect(Collectors.toSet())); + String line = reader.readLine(); + String[] headline = parseCsvRow(line, csvSep); + + if (headline.length <= 1) { + throw new SourceException( + "The given file has less than two columns! (Used separator '" + + csvSep + + "' on headline '" + + line + + "')"); + } + + return Optional.of(Arrays.stream(headline).collect(Collectors.toSet())); } catch (FileNotFoundException e) { // A file not existing can be acceptable in many cases, and is handled elsewhere. log.debug("The source for the given entity couldn't be found! Cause: {}", e.getMessage()); @@ -208,41 +219,45 @@ protected Set getTimeSeriesFilePaths(Pattern pattern) { */ protected Map buildFieldsToAttributes( final String csvRow, final String[] headline) throws SourceException { - - TreeMap insensitiveFieldsToAttributes = - new TreeMap<>(String.CASE_INSENSITIVE_ORDER); - + // parse row String[] fieldVals = parseCsvRow(csvRow, csvSep); - insensitiveFieldsToAttributes.putAll( - IntStream.range(0, Math.min(fieldVals.length, headline.length)) - .boxed() - .collect( - Collectors.toMap( - k -> StringUtils.snakeCaseToCamelCase(headline[k]), v -> fieldVals[v]))); + // check if the number row elements matched the number of headline elements if (fieldVals.length != headline.length) { + String headlineElements = "['" + String.join("', '", headline) + "']"; + String parsedRow = "['" + String.join("', '", fieldVals) + "']"; + throw new SourceException( "The size of the headline (" + headline.length + ") does not fit to the size of the attribute fields (" + fieldVals.length - + ").\nHeadline: " - + String.join(", ", headline) - + "\nRow: " - + csvRow.trim() - + ".\nPlease check:" - + "\n - is the csv separator in the file matching the separator provided in the constructor ('" + + ").\n Headline fields: " + + headlineElements + + "\n Row values: " + + parsedRow + + ".\n Please check:" + + "\n - is the csv separator in the row matching the provided separator '" + csvSep - + "')" - + "\n - does the number of columns match the number of headline fields " - + "\n - are you using a valid RFC 4180 formatted csv row?"); + + "'" + + "\n - does the number of columns match the number of headline fields " + + "\n - are you using a valid RFC 4180 formatted csv row?"); } + TreeMap insensitiveFieldsToAttributes = + new TreeMap<>(String.CASE_INSENSITIVE_ORDER); + insensitiveFieldsToAttributes.putAll( + IntStream.range(0, headline.length) + .boxed() + .collect( + Collectors.toMap( + k -> StringUtils.snakeCaseToCamelCase(headline[k]), v -> fieldVals[v]))); + if (insensitiveFieldsToAttributes.size() != fieldVals.length) { throw new SourceException( - "There might be duplicate headline elements.\nHeadline: " - + String.join(", ", headline) - + ".\nPlease keep in mind that headlines are case-insensitive and underscores from snake case are ignored."); + "There might be duplicate headline elements.\nHeadline fields: ['" + + String.join("', '", headline) + + "'].\nPlease keep in mind that headlines are case-insensitive and underscores from snake case are ignored."); } return insensitiveFieldsToAttributes; @@ -298,7 +313,7 @@ protected Try>, SourceException> buildStreamWithField // is wanted to avoid a lock on the file), but this causes a closing of the stream as well. // As we still want to consume the data at other places, we start a new stream instead of // returning the original one - return csvRowFieldValueMapping(reader, headline); + return csvRowFieldValueMapping(reader, headline, filePath.getFileName()); } catch (FileNotFoundException e) { if (allowFileNotExisting) { log.warn("Unable to find file '{}': {}", filePath, e.getMessage()); @@ -324,10 +339,11 @@ private Try getFilePath(Class entityCla * * @param reader for the file * @param headline of the file + * @param fileName the name of the file, that is read * @return a list of mapping */ protected Try>, SourceException> csvRowFieldValueMapping( - BufferedReader reader, String[] headline) { + BufferedReader reader, String[] headline, Path fileName) { return Try.scanStream( reader .lines() @@ -337,9 +353,8 @@ protected Try>, SourceException> csvRowFieldValueMapp Try.of( () -> buildFieldsToAttributes(csvRow, headline), SourceException.class)), - "Map") - .transform( - stream -> stream.filter(map -> !map.isEmpty()), - e -> new SourceException("Parsing csv row failed.", e)); + fileName.toString(), + SourceException::new) + .transformS(stream -> stream.filter(map -> !map.isEmpty())); } } diff --git a/src/main/java/edu/ie3/datamodel/io/source/csv/CsvIdCoordinateSource.java b/src/main/java/edu/ie3/datamodel/io/source/csv/CsvIdCoordinateSource.java index 199a4925d..59c29d28c 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/csv/CsvIdCoordinateSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/csv/CsvIdCoordinateSource.java @@ -77,8 +77,7 @@ private Map setupIdToCoordinateMap() throws SourceException { fieldToValues -> new SimpleFactoryData(fieldToValues, IdCoordinateInput.class)) .map(factory::get)) - .flatMap( - s -> Try.scanStream(s, "Pair").transformF(SourceException::new)) + .flatMap(s -> Try.scanStream(s, "Pair", SourceException::new)) .getOrThrow() .toList(); @@ -209,7 +208,7 @@ private Collection getCoordinatesInBoundingBox( // is wanted to avoid a lock on the file), but this causes a closing of the stream as well. // As we still want to consume the data at other places, we start a new stream instead of // returning the original one - return dataSource.csvRowFieldValueMapping(reader, headline); + return dataSource.csvRowFieldValueMapping(reader, headline, filePath.getFileName()); } catch (IOException e) { return Failure.of( new SourceException("Cannot read the file for coordinate id to coordinate mapping.", e)); diff --git a/src/main/java/edu/ie3/datamodel/io/source/csv/CsvJointGridContainerSource.java b/src/main/java/edu/ie3/datamodel/io/source/csv/CsvJointGridContainerSource.java index 2fd49c0f1..5796454a8 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/csv/CsvJointGridContainerSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/csv/CsvJointGridContainerSource.java @@ -89,8 +89,7 @@ public static JointGridContainer read( Try.getExceptions(rawGridElements, systemParticipants, graphicElements); if (!exceptions.isEmpty()) { - throw new SourceException( - exceptions.size() + " error(s) occurred while reading sources. ", exceptions); + throw new SourceException("Some exception(s) occurred while reading the grid.", exceptions); } else { // getOrThrow should not throw an exception in this context, because all exception are // filtered and thrown before diff --git a/src/main/java/edu/ie3/datamodel/io/source/csv/CsvLoadProfileSource.java b/src/main/java/edu/ie3/datamodel/io/source/csv/CsvLoadProfileSource.java index f3b271617..e17d07211 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/csv/CsvLoadProfileSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/csv/CsvLoadProfileSource.java @@ -116,8 +116,8 @@ protected LoadProfileTimeSeries buildLoadProfileTimeSeries( .buildStreamWithFieldsToAttributesMap(filePath, false) .flatMap( stream -> - Try.scanStream(stream.map(fieldToValueFunction), "LoadProfileEntry") - .transformF(SourceException::new)) + Try.scanStream( + stream.map(fieldToValueFunction), "LoadProfileEntry", SourceException::new)) .getOrThrow() .collect(Collectors.toSet()); diff --git a/src/main/java/edu/ie3/datamodel/io/source/csv/CsvTimeSeriesSource.java b/src/main/java/edu/ie3/datamodel/io/source/csv/CsvTimeSeriesSource.java index 4b5acd0ba..7b110711b 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/csv/CsvTimeSeriesSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/csv/CsvTimeSeriesSource.java @@ -166,8 +166,10 @@ protected IndividualTimeSeries buildIndividualTimeSeries( .buildStreamWithFieldsToAttributesMap(filePath, false) .flatMap( stream -> - Try.scanStream(stream.map(fieldToValueFunction), "TimeBasedValue") - .transformF(SourceException::new)); + Try.scanStream( + stream.map(fieldToValueFunction), + "TimeBasedValue", + SourceException::new)); return new IndividualTimeSeries<>( timeSeriesUuid, new HashSet<>(timeBasedValues.getOrThrow().toList())); } diff --git a/src/main/java/edu/ie3/datamodel/io/source/csv/CsvWeatherSource.java b/src/main/java/edu/ie3/datamodel/io/source/csv/CsvWeatherSource.java index ab565db80..241442725 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/csv/CsvWeatherSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/csv/CsvWeatherSource.java @@ -177,9 +177,11 @@ private Map> readWeatherTimeSeries( this::buildWeatherValue; /* Reading in weather time series */ for (CsvIndividualTimeSeriesMetaInformation data : weatherMetaInformation) { + Path path = data.getFullFilePath(); + // we need a reader for each file - try (BufferedReader reader = connector.initReader(data.getFullFilePath())) { - buildStreamWithFieldsToAttributesMap(reader) + try (BufferedReader reader = connector.initReader(path)) { + buildStreamWithFieldsToAttributesMap(reader, path.getFileName()) .getOrThrow() .map(fieldToValueFunction) .flatMap(Optional::stream) @@ -222,12 +224,12 @@ private Map> readWeatherTimeSeries( if (exceptions.isEmpty()) { return weatherTimeSeries; } else { - throw new SourceException("Due to: " + ExceptionUtils.getMessages(exceptions)); + throw new SourceException("Due to: " + ExceptionUtils.combineExceptions(exceptions)); } } private Try>, SourceException> buildStreamWithFieldsToAttributesMap( - BufferedReader bufferedReader) throws ValidationException { + BufferedReader bufferedReader, Path fileName) throws ValidationException { Class entityClass = TimeBasedValue.class; try (BufferedReader reader = bufferedReader) { @@ -240,7 +242,7 @@ private Try>, SourceException> buildStreamWithFieldsT // is wanted to avoid a lock on the file), but this causes a closing of the stream as well. // As we still want to consume the data at other places, we start a new stream instead of // returning the original one - return dataSource.csvRowFieldValueMapping(reader, headline); + return dataSource.csvRowFieldValueMapping(reader, headline, fileName); } catch (IOException e) { return Failure.of( new SourceException( diff --git a/src/main/java/edu/ie3/datamodel/utils/ContainerUtils.java b/src/main/java/edu/ie3/datamodel/utils/ContainerUtils.java index 5033221a2..522dfeaa4 100644 --- a/src/main/java/edu/ie3/datamodel/utils/ContainerUtils.java +++ b/src/main/java/edu/ie3/datamodel/utils/ContainerUtils.java @@ -426,41 +426,11 @@ public static GraphicElements filterForSubnet(GraphicElements input, int subnet) */ public static VoltageLevel determinePredominantVoltLvl(RawGridElements rawGrid, int subnet) throws InvalidGridException { - /* Exclude all nodes, that are at the high voltage side of the transformer */ - Set gridNodes = new HashSet<>(rawGrid.getNodes()); - gridNodes.removeAll( - /* Remove all nodes, that are upstream of transformers, this comprises all those, that are connected by - * switches */ - rawGrid.getTransformer2Ws().stream() - .flatMap( - transformer -> - ContainerUtils.traverseAlongSwitchChain(transformer.getNodeA(), rawGrid) - .stream()) - .collect(Collectors.toSet())); - gridNodes.removeAll( - rawGrid.getTransformer3Ws().stream() - .flatMap( - transformer -> { - if (transformer.getNodeA().getSubnet() == subnet) - return Stream.of(transformer.getNodeB(), transformer.getNodeC()); - else if (transformer.getNodeB().getSubnet() == subnet) - return Stream.concat( - ContainerUtils.traverseAlongSwitchChain(transformer.getNodeA(), rawGrid) - .stream(), - Stream.of(transformer.getNodeC(), transformer.getNodeInternal())); - else - return Stream.concat( - ContainerUtils.traverseAlongSwitchChain(transformer.getNodeA(), rawGrid) - .stream(), - Stream.of(transformer.getNodeB(), transformer.getNodeInternal())); - }) - .collect(Collectors.toSet())); - /* Build a mapping, which voltage level appears how often */ Map voltageLevelCount = - gridNodes.stream() - .map(NodeInput::getVoltLvl) - .collect(Collectors.groupingBy(voltLvl -> voltLvl, Collectors.counting())); + rawGrid.getNodes().stream() + .filter(n -> n.getSubnet() == subnet) + .collect(Collectors.groupingBy(NodeInput::getVoltLvl, Collectors.counting())); /* At this point only one voltage level should be apparent */ int amountOfVoltLvl = voltageLevelCount.size(); @@ -677,14 +647,8 @@ private static TransformerSubGridContainers getSubGridContainers( RawGridElements rawGridElements, Map subGrids) throws TopologyException { - /* Get the sub grid container at port A - travel upstream as long as nodes are connected - * _only_ by switches */ - NodeInput topNode = traverseAlongSwitchChain(transformer.getNodeA(), rawGridElements).getLast(); - if (Objects.isNull(topNode)) - throw new TopologyException( - "Cannot find most upstream node of transformer '" + transformer + "'"); - - SubGridContainer containerA = subGrids.get(topNode.getSubnet()); + /* Get the sub grid container at port A */ + SubGridContainer containerA = subGrids.get(transformer.getNodeA().getSubnet()); /* Get the sub grid container at port B */ SubGridContainer containerB = subGrids.get(transformer.getNodeB().getSubnet()); @@ -696,81 +660,6 @@ private static TransformerSubGridContainers getSubGridContainers( } else return new TransformerSubGridContainers(containerA, containerB); } - /** - * Traversing along a chain of switches and return the traveled nodes. The end thereby is defined - * by a node, that either is a dead end or is connected to any other type of connector (e.g. - * lines, transformers) and therefore leads to other parts of a "real" grid. If the starting node - * is not part of any switch, the starting node is returned. - * - * @param startNode Node that is meant to be the start of the switch chain - * @param rawGridElements Elements of the pure grid structure. - * @return The end node of the switch chain - */ - public static LinkedList traverseAlongSwitchChain( - NodeInput startNode, RawGridElements rawGridElements) { - Set possibleJunctions = - Stream.concat( - Stream.concat( - rawGridElements.getLines().parallelStream(), - rawGridElements.getTransformer2Ws().parallelStream()), - rawGridElements.getTransformer3Ws().parallelStream()) - .flatMap(connector -> connector.allNodes().parallelStream()) - .collect(Collectors.toSet()); - return traverseAlongSwitchChain(startNode, rawGridElements.getSwitches(), possibleJunctions); - } - - /** - * Traversing along a chain of switches and return the traveled nodes. The end thereby is defined - * by a node, that either is a dead end or part of the provided node set. If the starting node is - * not part of any switch, the starting node is returned. - * - * @param startNode Node that is meant to be the start of the switch chain - * @param switches Set of available switches - * @param possibleJunctions Set of nodes that denote possible junctions to "real" grid - * @return The end node of the switch chain - */ - private static LinkedList traverseAlongSwitchChain( - NodeInput startNode, Set switches, Set possibleJunctions) { - LinkedList traveledNodes = new LinkedList<>(); - traveledNodes.addFirst(startNode); - - /* Get the switch, that is connected to the starting node and determine the next node */ - List nextSwitches = - switches.stream().filter(switcher -> switcher.allNodes().contains(startNode)).toList(); - switch (nextSwitches.size()) { - case 0: - /* No further switch found -> Return the starting node */ - break; - case 1: - /* One next switch has been found -> Travel in this direction */ - SwitchInput nextSwitch = nextSwitches.get(0); - Optional candidateNodes = - nextSwitch.allNodes().stream().filter(node -> node != startNode).findFirst(); - NodeInput nextNode = - candidateNodes.orElseThrow( - () -> - new IllegalArgumentException( - "There is no further node available at switch " + nextSwitch)); - if (possibleJunctions.contains(nextNode)) { - /* This is a junction, leading to another Connector than a switch */ - traveledNodes.addLast(nextNode); - } else { - /* Add the traveled nodes to the nodes to be excluded, to avoid endless loops in cyclic switch topologies */ - HashSet newNodesToExclude = new HashSet<>(possibleJunctions); - newNodesToExclude.add(nextNode); - HashSet newSwitches = new HashSet<>(switches); - newSwitches.remove(nextSwitch); - traveledNodes.addAll(traverseAlongSwitchChain(nextNode, newSwitches, newNodesToExclude)); - } - break; - default: - throw new IllegalArgumentException( - "Cannot traverse along switch chain, as there is a junction included at node " - + startNode); - } - return traveledNodes; - } - /** * Combines a given collection of sub grid containers to a joint model. If the single models do * not fit together, exceptions are thrown. diff --git a/src/main/java/edu/ie3/datamodel/utils/ExceptionUtils.java b/src/main/java/edu/ie3/datamodel/utils/ExceptionUtils.java index df8f03947..cb4ba7d60 100644 --- a/src/main/java/edu/ie3/datamodel/utils/ExceptionUtils.java +++ b/src/main/java/edu/ie3/datamodel/utils/ExceptionUtils.java @@ -5,11 +5,8 @@ */ package edu.ie3.datamodel.utils; -import edu.ie3.datamodel.models.Entity; -import java.util.Arrays; -import java.util.Collection; import java.util.List; -import java.util.stream.Collectors; +import java.util.function.Function; public class ExceptionUtils { private ExceptionUtils() { @@ -22,45 +19,30 @@ private ExceptionUtils() { * @param exceptions list of exceptions * @return str containing the messages */ - public static String getMessages(List exceptions) { - return exceptions.stream() - .map(Throwable::getMessage) - .reduce("", (a, b) -> a + "\n " + b) - .replaceFirst("\n ", ""); - } + public static String combineExceptions(List exceptions) { + String messageSeparator = "\n "; - /** - * Creates a string containing multiple exception messages. - * - * @param exceptions list of exceptions - * @return str containing the messages - */ - public static String getFullMessages(List exceptions) { - return exceptions.stream() - .map(e -> e.getMessage() + printStackTrace(e.getStackTrace())) - .reduce("", (a, b) -> a + "\n " + b) - .replaceFirst("\n ", ""); - } + // function to convert an exception into a string + Function converter = + e -> { + String message = e.getMessage(); + Throwable cause = e.getCause(); - /** - * Combines multiple {@link Entity} into a string. - * - * @param entities to be combined - * @return a string - */ - public static String combine(Collection entities) { - return "{" + entities.stream().map(Entity::toString).collect(Collectors.joining(", ")) + "}"; - } + if (cause != null) { + String causeMessage = cause.getMessage(); - /** - * Method for combining {@link StackTraceElement}s. - * - * @param elements to be combined - * @return a string - */ - public static String printStackTrace(StackTraceElement... elements) { - return Arrays.stream(elements) - .map(StackTraceElement::toString) - .collect(Collectors.joining("\n ")); + if (!message.equalsIgnoreCase(causeMessage)) { + message += " Caused by: " + cause.getMessage(); + } + } + + return message; + }; + + String messages = + exceptions.stream().map(converter).reduce("", (a, b) -> a + messageSeparator + b); + + // some formating + return messages.replace("\n", "\n ").replaceFirst(messageSeparator, ""); } } diff --git a/src/main/java/edu/ie3/datamodel/utils/Try.java b/src/main/java/edu/ie3/datamodel/utils/Try.java index ffe006407..c03d0ea5e 100644 --- a/src/main/java/edu/ie3/datamodel/utils/Try.java +++ b/src/main/java/edu/ie3/datamodel/utils/Try.java @@ -7,7 +7,6 @@ import static java.util.stream.Collectors.partitioningBy; -import edu.ie3.datamodel.exceptions.FailureException; import edu.ie3.datamodel.exceptions.TryException; import java.util.*; import java.util.function.BiFunction; @@ -35,7 +34,7 @@ public static Try of(TrySupplier supplier, return new Success<>(supplier.get()); } catch (Exception e) { // this is necessary because we only want to catch exceptions that are of type E - if (e.getClass().isAssignableFrom(clazz)) { + if (clazz.isAssignableFrom(e.getClass())) { return new Failure<>((E) e); } else { throw new TryException("Wrongly caught exception: ", e); @@ -67,6 +66,20 @@ public static Try ofVoid( } } + /** + * Method to create multiple {@link Try} object easily. + * + * @param suppliers that either return no data or throw an exception + * @param clazz class of the exception + * @return a collection of try objects + * @param type of exception that could be thrown + */ + @SafeVarargs + public static Collection> ofVoids( + Class clazz, VoidSupplier... suppliers) { + return Arrays.stream(suppliers).map(supplier -> ofVoid(supplier, clazz)).toList(); + } + /** * Method to create a {@link Try} object easily. * @@ -119,8 +132,7 @@ public static Try from( * @param tries collection of {@link Try} objects * @return a list of {@link Exception}'s */ - public static List getExceptions( - Collection> tries) { + public static List getExceptions(Collection> tries) { return getExceptions(tries.stream()); } @@ -130,7 +142,7 @@ public static List getExceptions( * @param tries stream of {@link Try} objects * @return a list of {@link Exception}'s */ - public static List getExceptions(Stream> tries) { + public static List getExceptions(Stream> tries) { return tries.filter(Try::isFailure).map(t -> ((Failure) t).get()).toList(); } @@ -149,13 +161,15 @@ public static List getExceptions(Try * Method to scan a collection of {@link Try} objects for {@link Failure}'s. * * @param c collection of {@link Try} objects - * @param typeOfData type of data + * @param typeOfData information added to exception to help identify the place, that needs to be + * fixed + * @param exceptionBuilder function to build the failure message * @return a {@link Success} if no {@link Failure}'s are found in the collection * @param type of data */ - public static Try, FailureException> scanCollection( - Collection> c, Class typeOfData) { - return scanStream(c.stream(), typeOfData.getSimpleName()) + public static Try, R> scanCollection( + Collection> c, Class typeOfData, Function exceptionBuilder) { + return scanStream(c.stream(), typeOfData.getSimpleName(), exceptionBuilder) .transformS(stream -> stream.collect(Collectors.toSet())); } @@ -163,11 +177,14 @@ public static Try, FailureException> scanCollect * Method to scan a stream of {@link Try} objects for {@link Failure}'s. * * @param stream of {@link Try} objects + * @param typeOfData information added to exception to help identify the place, that needs to be + * fixed + * @param exceptionBuilder function to build the failure message * @return a {@link Success} if no {@link Failure}'s are found in the stream * @param type of data */ - public static Try, FailureException> scanStream( - Stream> stream, String typeOfData) { + public static Try, R> scanStream( + Stream> stream, String typeOfData, Function exceptionBuilder) { Map>> map = stream.collect(partitioningBy(Try::isSuccess)); List> successes = map.get(true); @@ -177,16 +194,15 @@ public static Try, FailureException> scanStre assert successes != null && failures != null; if (!failures.isEmpty()) { - E first = ((Failure) failures.get(0)).exception; + List exceptions = failures.stream().map(f -> ((Failure) f).exception).toList(); return new Failure<>( - new FailureException( - failures.size() + exceptionBuilder.apply( + exceptions.size() + " exception(s) occurred within \"" + typeOfData - + "\" data, one is: " - + first, - first.getCause())); + + "\" data: \n " + + ExceptionUtils.combineExceptions(exceptions))); } else { return new Success<>(successes.stream().map(t -> ((Success) t).data)); } diff --git a/src/main/java/edu/ie3/datamodel/utils/validation/EnergyManagementValidationUtils.java b/src/main/java/edu/ie3/datamodel/utils/validation/EnergyManagementValidationUtils.java new file mode 100644 index 000000000..9b2894cca --- /dev/null +++ b/src/main/java/edu/ie3/datamodel/utils/validation/EnergyManagementValidationUtils.java @@ -0,0 +1,48 @@ +/* + * © 2021. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation +*/ +package edu.ie3.datamodel.utils.validation; + +import edu.ie3.datamodel.exceptions.InvalidEntityException; +import edu.ie3.datamodel.exceptions.ValidationException; +import edu.ie3.datamodel.models.input.EmInput; +import edu.ie3.datamodel.utils.Try; +import java.util.ArrayList; +import java.util.List; + +public class EnergyManagementValidationUtils extends ValidationUtils { + + /** Private Constructor as this class is not meant to be instantiated */ + private EnergyManagementValidationUtils() { + throw new IllegalStateException("Don't try and instantiate a Utility class."); + } + + /** + * Validates a energy management unit if: + * + *
    + *
  • its control strategy is not null + *
+ * + * A "distribution" method, that forwards the check request to specific implementations to fulfill + * the checking task, based on the class of the given object. + * + * @param energyManagement EmInput to validate + * @return a list of try objects either containing an {@link ValidationException} or an empty + * Success + */ + protected static List> check(EmInput energyManagement) { + List> exceptions = new ArrayList<>(); + + exceptions.add( + Try.ofVoid( + energyManagement.getControlStrategy() == null, + () -> + new InvalidEntityException( + "No control strategy of energy management defined for", energyManagement))); + + return exceptions; + } +} diff --git a/src/main/java/edu/ie3/datamodel/utils/validation/GridContainerValidationUtils.java b/src/main/java/edu/ie3/datamodel/utils/validation/GridContainerValidationUtils.java index 7d9e9b26b..0c4ecac7a 100644 --- a/src/main/java/edu/ie3/datamodel/utils/validation/GridContainerValidationUtils.java +++ b/src/main/java/edu/ie3/datamodel/utils/validation/GridContainerValidationUtils.java @@ -20,7 +20,6 @@ import edu.ie3.datamodel.models.input.container.*; import edu.ie3.datamodel.models.input.graphics.GraphicInput; import edu.ie3.datamodel.models.input.system.SystemParticipantInput; -import edu.ie3.datamodel.utils.ContainerUtils; import edu.ie3.datamodel.utils.Try; import edu.ie3.datamodel.utils.Try.Failure; import edu.ie3.datamodel.utils.Try.Success; @@ -28,7 +27,6 @@ import java.util.*; import java.util.function.Predicate; import java.util.stream.Collectors; -import java.util.stream.Stream; import org.jgrapht.Graph; import org.jgrapht.alg.connectivity.ConnectivityInspector; import org.jgrapht.graph.DefaultEdge; @@ -99,10 +97,15 @@ private GridContainerValidationUtils() { /* sanity check to ensure uniqueness */ List> exceptions = new ArrayList<>(); - exceptions.add( - Try.ofVoid( - () -> checkAssetUniqueness(rawGridElements.allEntitiesAsList()), - DuplicateEntitiesException.class)); + exceptions.addAll( + Try.ofVoids( + DuplicateEntitiesException.class, + () -> checkAssetUniqueness(rawGridElements.getNodes()), + () -> checkAssetUniqueness(rawGridElements.getLines()), + () -> checkAssetUniqueness(rawGridElements.getSwitches()), + () -> checkAssetUniqueness(rawGridElements.getTransformer2Ws()), + () -> checkAssetUniqueness(rawGridElements.getTransformer3Ws()), + () -> checkAssetUniqueness(rawGridElements.getMeasurementUnits()))); /* Checking nodes */ Set nodes = rawGridElements.getNodes(); @@ -135,26 +138,12 @@ private GridContainerValidationUtils() { exceptions.addAll(ConnectorValidationUtils.check(transformer)); }); - /* Checking switches - * Because of the fact, that a transformer with switch gear in "upstream" direction has its corresponding node in - * upper grid connected to a switch, instead of to the transformer directly: Collect all nodes at the end of the - * upstream switch chain and add them to the set of allowed nodes */ - HashSet validSwitchNodes = new HashSet<>(nodes); - validSwitchNodes.addAll( - Stream.of(rawGridElements.getTransformer2Ws(), rawGridElements.getTransformer2Ws()) - .flatMap(Set::stream) - .parallel() - .map( - transformer -> - ContainerUtils.traverseAlongSwitchChain(transformer.getNodeA(), rawGridElements) - .getLast()) - .toList()); - + /* Checking switches */ rawGridElements .getSwitches() .forEach( switcher -> { - exceptions.add(checkNodeAvailability(switcher, validSwitchNodes)); + exceptions.add(checkNodeAvailability(switcher, nodes)); exceptions.addAll(ConnectorValidationUtils.check(switcher)); }); @@ -287,10 +276,6 @@ protected static Try checkConnectivity( /* sanity check to ensure uniqueness */ List> exceptions = new ArrayList<>(); - exceptions.add( - Try.ofVoid( - () -> checkAssetUniqueness(systemParticipants.allEntitiesAsList()), - DuplicateEntitiesException.class)); exceptions.addAll(checkSystemParticipants(systemParticipants.getBmPlants(), nodes)); exceptions.addAll(checkSystemParticipants(systemParticipants.getChpPlants(), nodes)); @@ -306,8 +291,8 @@ protected static Try checkConnectivity( } /** - * Checks the validity of specific system participant. Moreover, it checks, if the systems are - * connected to a node that is not in the provided set + * Checks the validity and uniqueness of specific system participant. Moreover, it checks, if the + * systems are connected to a node that is not in the provided set * * @param participants a set of specific system participants * @param nodes Set of already known nodes @@ -316,18 +301,17 @@ protected static Try checkConnectivity( */ protected static List> checkSystemParticipants( Set participants, Set nodes) { - return participants.stream() - .map( - entity -> { - List> exceptions = new ArrayList<>(); - - exceptions.add(checkNodeAvailability(entity, nodes)); - exceptions.addAll(SystemParticipantValidationUtils.check(entity)); - - return exceptions; - }) - .flatMap(List::stream) - .toList(); + List> exceptions = new ArrayList<>(); + exceptions.add( + Try.ofVoid(() -> checkAssetUniqueness(participants), DuplicateEntitiesException.class)); + + participants.forEach( + participant -> { + exceptions.add(checkNodeAvailability(participant, nodes)); + exceptions.addAll(SystemParticipantValidationUtils.check(participant)); + }); + + return exceptions; } /** diff --git a/src/main/java/edu/ie3/datamodel/utils/validation/SystemParticipantValidationUtils.java b/src/main/java/edu/ie3/datamodel/utils/validation/SystemParticipantValidationUtils.java index 790bca28b..c68db81f1 100644 --- a/src/main/java/edu/ie3/datamodel/utils/validation/SystemParticipantValidationUtils.java +++ b/src/main/java/edu/ie3/datamodel/utils/validation/SystemParticipantValidationUtils.java @@ -393,7 +393,7 @@ private static List> checkLoad(LoadInput loadI *
    *
  • its rated apparent power is not negative *
  • its albedo value of the plant's surrounding is between 0 and 1 - *
  • its inclination in a compass direction (azimuth) is between -90° and 90° + *
  • its inclination in a compass direction (azimuth) is between -180° and 180° *
  • its efficiency of the asset's inverter (etaConv) is between 0% and 100% *
  • its tilted inclination from horizontal (elevation angle) is between 0° and 90° *
  • its rated power factor is between 0 and 1 @@ -431,17 +431,17 @@ private static void checkAlbedo(PvInput pvInput) throws InvalidEntityException { } /** - * Check if azimuth angle of pvInput is between -90° and 90° + * Check if azimuth angle of pvInput is between -180° and 180° * * @param pvInput PvInput to validate */ private static void checkAzimuth(PvInput pvInput) throws InvalidEntityException { - if (pvInput.getAzimuth().isLessThan(Quantities.getQuantity(-90d, AZIMUTH)) - || pvInput.getAzimuth().isGreaterThan(Quantities.getQuantity(90d, AZIMUTH))) + if (pvInput.getAzimuth().isLessThan(Quantities.getQuantity(-180d, AZIMUTH)) + || pvInput.getAzimuth().isGreaterThan(Quantities.getQuantity(180d, AZIMUTH))) throw new InvalidEntityException( "Azimuth angle of " + pvInput.getClass().getSimpleName() - + " must be between -90° (east) and 90° (west)", + + " must be between -180° and 180°", pvInput); } diff --git a/src/main/java/edu/ie3/datamodel/utils/validation/UniquenessValidationUtils.java b/src/main/java/edu/ie3/datamodel/utils/validation/UniquenessValidationUtils.java index cdf980fad..031ee0aad 100644 --- a/src/main/java/edu/ie3/datamodel/utils/validation/UniquenessValidationUtils.java +++ b/src/main/java/edu/ie3/datamodel/utils/validation/UniquenessValidationUtils.java @@ -24,10 +24,11 @@ public class UniquenessValidationUtils extends ValidationUtils { // default field set supplier - protected static final FieldSetSupplier uuidFieldSupplier = + protected static final FieldSetSupplier uuidFieldSupplier = entity -> Set.of(entity.getUuid()); - protected static final FieldSetSupplier idFieldSupplier = e -> Set.of(e.getId()); - protected static final FieldSetSupplier resultFieldSupplier = + protected static final FieldSetSupplier idFieldSupplier = + e -> Set.of(e.getId()); + protected static final FieldSetSupplier resultFieldSupplier = entity -> Set.of(entity.getTime(), entity.getInputModel()); protected static final FieldSetSupplier mappingFieldSupplier = entity -> Set.of(entity.getAsset()); @@ -44,9 +45,10 @@ public class UniquenessValidationUtils extends ValidationUtils { * @param entities to be checked * @throws DuplicateEntitiesException if uniqueness is violated */ - public static void checkUniqueEntities(Collection entities) + @SuppressWarnings("unchecked") + public static void checkUniqueEntities(Collection entities) throws DuplicateEntitiesException { - checkUniqueness(entities, uuidFieldSupplier).getOrThrow(); + checkUniqueness(entities, (FieldSetSupplier) uuidFieldSupplier).getOrThrow(); } /** @@ -55,13 +57,14 @@ public static void checkUniqueEntities(Collection entiti * @param entities to be checked * @throws DuplicateEntitiesException if uniqueness is violated */ - public static void checkAssetUniqueness(Collection entities) + @SuppressWarnings("unchecked") + public static void checkAssetUniqueness(Collection entities) throws DuplicateEntitiesException { List exceptions = Try.getExceptions( Try.ofVoid(() -> checkUniqueEntities(entities), DuplicateEntitiesException.class), - checkUniqueness(entities, idFieldSupplier)); + checkUniqueness(entities, (FieldSetSupplier) idFieldSupplier)); if (!exceptions.isEmpty()) { throw new DuplicateEntitiesException("AssetInput", exceptions); @@ -74,9 +77,10 @@ public static void checkAssetUniqueness(Collection entitie * @param entities to be checked * @throws DuplicateEntitiesException if uniqueness is violated */ - public static void checkResultUniqueness(Collection entities) + @SuppressWarnings("unchecked") + public static void checkResultUniqueness(Collection entities) throws DuplicateEntitiesException { - checkUniqueness(entities, resultFieldSupplier).getOrThrow(); + checkUniqueness(entities, (FieldSetSupplier) resultFieldSupplier).getOrThrow(); } /** @@ -122,33 +126,46 @@ public static void checkWeatherUniqueness(Collection Try checkUniqueness( Collection entities, FieldSetSupplier supplier) { + Optional option = entities.stream().findAny().map(e -> e.getClass().getSimpleName()); + if (option.isPresent()) { + return checkUniqueness(entities, supplier, option.get()); + } else { + return Try.Success.empty(); + } + } + + /** + * Checking the uniqueness for a given {@link Entity}. + * + * @param entities to be checked + * @param supplier for the field set + * @param entityName name of the class of the entity + * @return a try object + * @param type of entity + */ + private static Try checkUniqueness( + Collection entities, FieldSetSupplier supplier, String entityName) { if (entities.size() < 2) { return Success.empty(); } - return entities.stream() - .findAny() - .map( - entity -> { - List> elements = entities.stream().map(supplier::getFieldSets).toList(); - Set> uniqueElements = new HashSet<>(elements); - - return Try.ofVoid( - elements.size() != uniqueElements.size(), - () -> buildDuplicationException(entity.getClass(), elements)); - }) - .orElse(Success.empty()); + List> elements = entities.stream().map(supplier::getFieldSets).toList(); + Set> uniqueElements = new HashSet<>(elements); + + return Try.ofVoid( + elements.size() != uniqueElements.size(), + () -> buildDuplicationException(entityName, elements)); } /** * Method for building a {@link DuplicateEntitiesException}. * - * @param entityClass class of the entity + * @param entityClass name of the class of the entity * @param notUniqueElements list of not unique elements * @return a {@link DuplicateEntitiesException} */ protected static DuplicateEntitiesException buildDuplicationException( - Class entityClass, List> notUniqueElements) { + String entityClass, List> notUniqueElements) { String fieldName = notUniqueElements.get(0).stream() .map(f -> f.getClass().getSimpleName()) @@ -167,7 +184,7 @@ protected static DuplicateEntitiesException buildDuplicationException( return new DuplicateEntitiesException( "'" - + entityClass.getSimpleName() + + entityClass + "' entities with duplicated " + fieldName + " key, but different field " diff --git a/src/test/groovy/edu/ie3/datamodel/io/factory/input/AssetInputEntityFactoryTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/factory/input/AssetInputEntityFactoryTest.groovy index f6fa90645..a468dfc4e 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/factory/input/AssetInputEntityFactoryTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/factory/input/AssetInputEntityFactoryTest.groovy @@ -289,7 +289,11 @@ class AssetInputEntityFactoryTest extends Specification implements FactoryTestHe "0: [id, uuid] or [id, uuid]\n" + "1: [id, operatesFrom, uuid] or [id, operates_from, uuid]\n" + "2: [id, operatesUntil, uuid] or [id, operates_until, uuid]\n" + - "3: [id, operatesFrom, operatesUntil, uuid] or [id, operates_from, operates_until, uuid]\n" + "3: [id, operatesFrom, operatesUntil, uuid] or [id, operates_from, operates_until, uuid]\n" + + "4: [id, operator, uuid] or [id, operator, uuid]\n" + + "5: [id, operatesFrom, operator, uuid] or [id, operates_from, operator, uuid]\n" + + "6: [id, operatesUntil, operator, uuid] or [id, operates_until, operator, uuid]\n" + + "7: [id, operatesFrom, operatesUntil, operator, uuid] or [id, operates_from, operates_until, operator, uuid]\n" } private static class TestAssetInput extends AssetInput { diff --git a/src/test/groovy/edu/ie3/datamodel/io/factory/input/participant/EmInputFactoryTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/factory/input/EmInputFactoryTest.groovy similarity index 73% rename from src/test/groovy/edu/ie3/datamodel/io/factory/input/participant/EmInputFactoryTest.groovy rename to src/test/groovy/edu/ie3/datamodel/io/factory/input/EmInputFactoryTest.groovy index 6a0734f07..5cc32ca9d 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/factory/input/participant/EmInputFactoryTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/factory/input/EmInputFactoryTest.groovy @@ -3,16 +3,16 @@ * Institute of Energy Systems, Energy Efficiency and Energy Economics, * Research group Distribution grid planning and operation */ -package edu.ie3.datamodel.io.factory.input.participant +package edu.ie3.datamodel.io.factory.input import edu.ie3.datamodel.exceptions.FactoryException -import edu.ie3.datamodel.io.factory.input.EmAssetInputEntityData import edu.ie3.datamodel.models.input.EmInput import edu.ie3.datamodel.models.input.OperatorInput import edu.ie3.datamodel.utils.Try import spock.lang.Specification import java.time.ZonedDateTime +import java.util.stream.Collectors class EmInputFactoryTest extends Specification { @@ -25,6 +25,79 @@ class EmInputFactoryTest extends Specification { inputFactory.supportedClasses == expectedClasses } + def "An EmInputFactory should return the valid fields correctly"() { + given: + def inputFactory = new EmInputFactory() + def validCombinations = [ + [ + "uuid", + "id", + "controlStrategy", + "controllingEm" + ], + [ + "uuid", + "id", + "controlStrategy", + "controllingEm", + "operatesFrom" + ], + [ + "uuid", + "id", + "controlStrategy", + "controllingEm", + "operatesUntil" + ], + [ + "uuid", + "id", + "controlStrategy", + "controllingEm", + "operatesFrom", + "operatesUntil" + ], + [ + "uuid", + "id", + "controlStrategy", + "controllingEm", + "operator" + ], + [ + "uuid", + "id", + "controlStrategy", + "controllingEm", + "operator", + "operatesFrom" + ], + [ + "uuid", + "id", + "controlStrategy", + "controllingEm", + "operator", + "operatesUntil" + ], + [ + "uuid", + "id", + "controlStrategy", + "controllingEm", + "operator", + "operatesFrom", + "operatesUntil" + ] + ].collect { it as Set } + + when: + def fieldCombinations = inputFactory.getFields(EmInput) + + then: + fieldCombinations == validCombinations + } + def "A EmInputFactory should parse a valid EmInput with parent EM correctly"() { given: def inputFactory = new EmInputFactory() diff --git a/src/test/groovy/edu/ie3/datamodel/io/factory/input/participant/FixedFeedInInputFactoryTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/factory/input/participant/FixedFeedInInputFactoryTest.groovy index d94ff5b9e..3f4eeb84a 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/factory/input/participant/FixedFeedInInputFactoryTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/factory/input/participant/FixedFeedInInputFactoryTest.groovy @@ -8,6 +8,7 @@ package edu.ie3.datamodel.io.factory.input.participant import static edu.ie3.util.quantities.PowerSystemUnits.PU import edu.ie3.datamodel.exceptions.FactoryException +import edu.ie3.datamodel.exceptions.ValidationException import edu.ie3.datamodel.models.StandardUnits import edu.ie3.datamodel.models.input.EmInput import edu.ie3.datamodel.models.input.NodeInput @@ -81,7 +82,7 @@ class FixedFeedInInputFactoryTest extends Specification implements FactoryTestHe def actualFields = FixedFeedInInputFactory.newSet("uuid", "id", "s_rated", "cosphi_rated") when: - Try input = inputFactory.validate(actualFields, FixedFeedInInput) + Try input = inputFactory.validate(actualFields, FixedFeedInInput) then: input.failure @@ -91,9 +92,17 @@ class FixedFeedInInputFactoryTest extends Specification implements FactoryTestHe "1: [cosPhiRated, id, operatesFrom, qCharacteristics, sRated, uuid] or [cos_phi_rated, id, operates_from, q_characteristics, s_rated, uuid]\n" + "2: [cosPhiRated, id, operatesUntil, qCharacteristics, sRated, uuid] or [cos_phi_rated, id, operates_until, q_characteristics, s_rated, uuid]\n" + "3: [cosPhiRated, id, operatesFrom, operatesUntil, qCharacteristics, sRated, uuid] or [cos_phi_rated, id, operates_from, operates_until, q_characteristics, s_rated, uuid]\n" + - "4: [cosPhiRated, em, id, qCharacteristics, sRated, uuid] or [cos_phi_rated, em, id, q_characteristics, s_rated, uuid]\n" + - "5: [cosPhiRated, em, id, operatesFrom, qCharacteristics, sRated, uuid] or [cos_phi_rated, em, id, operates_from, q_characteristics, s_rated, uuid]\n" + - "6: [cosPhiRated, em, id, operatesUntil, qCharacteristics, sRated, uuid] or [cos_phi_rated, em, id, operates_until, q_characteristics, s_rated, uuid]\n" + - "7: [cosPhiRated, em, id, operatesFrom, operatesUntil, qCharacteristics, sRated, uuid] or [cos_phi_rated, em, id, operates_from, operates_until, q_characteristics, s_rated, uuid]\n" + "4: [cosPhiRated, id, operator, qCharacteristics, sRated, uuid] or [cos_phi_rated, id, operator, q_characteristics, s_rated, uuid]\n" + + "5: [cosPhiRated, id, operatesFrom, operator, qCharacteristics, sRated, uuid] or [cos_phi_rated, id, operates_from, operator, q_characteristics, s_rated, uuid]\n" + + "6: [cosPhiRated, id, operatesUntil, operator, qCharacteristics, sRated, uuid] or [cos_phi_rated, id, operates_until, operator, q_characteristics, s_rated, uuid]\n" + + "7: [cosPhiRated, id, operatesFrom, operatesUntil, operator, qCharacteristics, sRated, uuid] or [cos_phi_rated, id, operates_from, operates_until, operator, q_characteristics, s_rated, uuid]\n" + + "8: [controllingEm, cosPhiRated, id, qCharacteristics, sRated, uuid] or [controlling_em, cos_phi_rated, id, q_characteristics, s_rated, uuid]\n" + + "9: [controllingEm, cosPhiRated, id, operatesFrom, qCharacteristics, sRated, uuid] or [controlling_em, cos_phi_rated, id, operates_from, q_characteristics, s_rated, uuid]\n" + + "10: [controllingEm, cosPhiRated, id, operatesUntil, qCharacteristics, sRated, uuid] or [controlling_em, cos_phi_rated, id, operates_until, q_characteristics, s_rated, uuid]\n" + + "11: [controllingEm, cosPhiRated, id, operatesFrom, operatesUntil, qCharacteristics, sRated, uuid] or [controlling_em, cos_phi_rated, id, operates_from, operates_until, q_characteristics, s_rated, uuid]\n" + + "12: [controllingEm, cosPhiRated, id, operator, qCharacteristics, sRated, uuid] or [controlling_em, cos_phi_rated, id, operator, q_characteristics, s_rated, uuid]\n" + + "13: [controllingEm, cosPhiRated, id, operatesFrom, operator, qCharacteristics, sRated, uuid] or [controlling_em, cos_phi_rated, id, operates_from, operator, q_characteristics, s_rated, uuid]\n" + + "14: [controllingEm, cosPhiRated, id, operatesUntil, operator, qCharacteristics, sRated, uuid] or [controlling_em, cos_phi_rated, id, operates_until, operator, q_characteristics, s_rated, uuid]\n" + + "15: [controllingEm, cosPhiRated, id, operatesFrom, operatesUntil, operator, qCharacteristics, sRated, uuid] or [controlling_em, cos_phi_rated, id, operates_from, operates_until, operator, q_characteristics, s_rated, uuid]\n" } } diff --git a/src/test/groovy/edu/ie3/datamodel/io/processor/result/ResultEntityProcessorTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/processor/result/ResultEntityProcessorTest.groovy index 320dc8db7..7a8dbf297 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/processor/result/ResultEntityProcessorTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/processor/result/ResultEntityProcessorTest.groovy @@ -7,6 +7,7 @@ package edu.ie3.datamodel.io.processor.result import edu.ie3.datamodel.exceptions.EntityProcessorException import edu.ie3.datamodel.models.StandardUnits +import edu.ie3.datamodel.models.result.CongestionResult import edu.ie3.datamodel.models.result.NodeResult import edu.ie3.datamodel.models.result.ResultEntity import edu.ie3.datamodel.models.result.connector.LineResult @@ -277,6 +278,37 @@ class ResultEntityProcessorTest extends Specification { validProcessedElement == expectedResults } + def "A ResultEntityProcessor should serialize a CongestionResult correctly"() { + given: + def resultProcessor = new ResultEntityProcessor(CongestionResult) + + def validResult = new CongestionResult( + ZonedDateTime.parse("2020-01-30T17:26:44Z"), + inputModel, + CongestionResult.InputModelType.LINE, + 3, + Quantities.getQuantity(110, Units.PERCENT), + Quantities.getQuantity(0, Units.PERCENT), + Quantities.getQuantity(100, Units.PERCENT), + ) + + def expectedResults = [ + inputModel: '22bea5fc-2cb2-4c61-beb9-b476e0107f52', + max : '100.0', + min : '0.0', + subgrid : '3', + time : '2020-01-30T17:26:44Z', + type : 'line', + value : '110.0' + ] + + when: + def validProcessedElement = resultProcessor.handleEntity(validResult) + + then: + validProcessedElement == expectedResults + } + def "A ResultEntityProcessor should throw an EntityProcessorException when it receives an entity result that is not eligible"() { given: diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/EnergyManagementSourceTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/EnergyManagementSourceTest.groovy index 288c6be0a..86d5edf77 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/EnergyManagementSourceTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/EnergyManagementSourceTest.groovy @@ -24,35 +24,35 @@ class EnergyManagementSourceTest extends Specification { new AssetInputEntityData( ["uuid": "0-0-0-0-0", "id": "root", - "parentem" : "", + "controllingem" : "", "controlstrategy" : ""], EmInput ), new AssetInputEntityData( ["uuid": "0-0-0-0-1", "id": "child 1", - "parentem" : "0-0-0-0-0", + "controllingem" : "0-0-0-0-0", "controlstrategy" : ""], EmInput ), new AssetInputEntityData( ["uuid": "0-0-0-0-11", "id": "child 1-1", - "parentem" : "0-0-0-0-1", + "controllingem" : "0-0-0-0-1", "controlstrategy" : ""], EmInput ), new AssetInputEntityData( ["uuid": "0-0-0-0-2", "id": "child 2", - "parentem" : "0-0-0-0-0", + "controllingem" : "0-0-0-0-0", "controlstrategy" : ""], EmInput ), new AssetInputEntityData( ["uuid": "0-0-0-0-21", "id": "child 2-1", - "parentem" : "0-0-0-0-2", + "controllingem" : "0-0-0-0-2", "controlstrategy" : ""], EmInput ), @@ -101,21 +101,21 @@ class EnergyManagementSourceTest extends Specification { new AssetInputEntityData( ["uuid": "0-0-0-0-1", "id": "em 1", - "parentem" : "", + "controllingem" : "", "controlstrategy" : ""], EmInput ), new AssetInputEntityData( ["uuid": "0-0-0-0-2", "id": "em 2", - "parentem" : "", + "controllingem" : "", "controlstrategy" : "strat_b"], EmInput ), new AssetInputEntityData( ["uuid": "0-0-0-0-3", "id": "em 3", - "parentem" : "", + "controllingem" : "", "controlstrategy" : "other"], EmInput ), @@ -152,14 +152,14 @@ class EnergyManagementSourceTest extends Specification { new Try.Success(new AssetInputEntityData( ["uuid": "0-0-0-0-1", "id": "em 1", - "parentem" : "", + "controllingem" : "", "controlstrategy" : ""], EmInput )), new Try.Success(new AssetInputEntityData( ["uuid": "0-0-0-0-2", "id": "em 2", - "parentem" : "", + "controllingem" : "", "controlstrategy" : ""], EmInput )), @@ -171,7 +171,7 @@ class EnergyManagementSourceTest extends Specification { then: def exc = thrown(SourceException) - exc.cause.message.contains("test failure abc") + exc.message.contains("test failure abc") } def "An EnergyManagementSource should fail if a parent EM UUID is malformed"() { @@ -180,14 +180,14 @@ class EnergyManagementSourceTest extends Specification { new AssetInputEntityData( ["uuid": "0-0-0-0-1", "id": "em 1", - "parentem" : "", + "controllingem" : "", "controlstrategy" : ""], EmInput ), new AssetInputEntityData( ["uuid": "0-0-0-0-2", "id": "em 2", - "parentem" : "not-a-uuid", + "controllingem" : "not-a-uuid", "controlstrategy" : ""], EmInput ), @@ -198,7 +198,7 @@ class EnergyManagementSourceTest extends Specification { then: def exc = thrown(SourceException) - exc.cause.message.contains("Exception while trying to parse UUID of field \"parentem\" with value \"not-a-uuid\"") + exc.message.contains("Exception while trying to parse UUID of field \"controllingEm\" with value \"not-a-uuid\"") } def "An EnergyManagementSource should fail if the factory fails for one EM"() { @@ -207,13 +207,13 @@ class EnergyManagementSourceTest extends Specification { new AssetInputEntityData( ["uuid": "0-0-0-0-1", "id": "em 1", - "parentem" : "", + "controllingem" : "", "controlstrategy" : ""], EmInput ), new AssetInputEntityData( ["uuid": "0-0-0-0-2", // id is missing - "parentem" : "", + "controllingem" : "", "controlstrategy" : ""], EmInput ), @@ -224,8 +224,8 @@ class EnergyManagementSourceTest extends Specification { then: def exc = thrown(SourceException) - exc.cause.message.contains("An error occurred when creating instance of EmInput") - exc.cause.cause.class == FactoryException + exc.message == "1 exception(s) occurred within \"EmInput\" data: \n" + + " An error occurred when creating instance of EmInput.class. Caused by: Field \"id\" not found in EntityData" } def "An EnergyManagementSource should fail if a parent em is not provided"() { @@ -234,14 +234,14 @@ class EnergyManagementSourceTest extends Specification { new AssetInputEntityData( ["uuid": "0-0-0-0-1", "id": "em 1", - "parentem" : "", + "controllingem" : "", "controlstrategy" : ""], EmInput ), new AssetInputEntityData( ["uuid": "0-0-0-0-2", "id": "em 2", - "parentem" : "1-2-3-4-5", // does not exist + "controllingem" : "1-2-3-4-5", // does not exist "controlstrategy" : ""], EmInput ), @@ -261,14 +261,14 @@ class EnergyManagementSourceTest extends Specification { new AssetInputEntityData( ["uuid": "0-0-0-0-1", "id": "em 1", - "parentem" : "1-2-3-4-5", // does not exist + "controllingem" : "1-2-3-4-5", // does not exist "controlstrategy" : ""], EmInput ), new AssetInputEntityData( ["uuid": "0-0-0-0-2", "id": "em 2", - "parentem" : "1-2-3-4-5", // does not exist + "controllingem" : "1-2-3-4-5", // does not exist "controlstrategy" : ""], EmInput ), diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/EntitySourceTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/EntitySourceTest.groovy index 0c46d0c9a..1061376f4 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/EntitySourceTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/EntitySourceTest.groovy @@ -48,7 +48,8 @@ class EntitySourceTest extends Specification { then: SourceException ex = thrown() - ex.message == "edu.ie3.datamodel.exceptions.FailureException: 1 exception(s) occurred within \"OperatorInput\" data, one is: edu.ie3.datamodel.exceptions.FactoryException: An error occurred when creating instance of OperatorInput.class." + ex.message == "1 exception(s) occurred within \"OperatorInput\" data: \n" + + " An error occurred when creating instance of OperatorInput.class. Caused by: Field \"id\" not found in EntityData" } def "An EntitySource can build EntityData correctly"() { @@ -168,12 +169,12 @@ class EntitySourceTest extends Specification { then: actual.failure actual.exception.get().class == SourceException - actual.exception.get().message.contains(expectedMessage) + actual.exception.get().message == expectedMessage where: fieldsToAttributes | entityMap | expectedMessage - ["operator": "no uuid"] | map([OperatorInput.NO_OPERATOR_ASSIGNED]) | "Extracting UUID field operator from entity data" - ["operator": GridTestData.profBroccoli.uuid.toString()] | map([OperatorInput.NO_OPERATOR_ASSIGNED]) | "Entity with uuid f15105c4-a2de-4ab8-a621-4bc98e372d92 was not provided." + ["operator": "no uuid"] | map([OperatorInput.NO_OPERATOR_ASSIGNED]) | "Extracting UUID for field 'operator' failed. Caused by: Exception while trying to parse UUID of field \"operator\" with value \"no uuid\"" + ["operator": GridTestData.profBroccoli.uuid.toString()] | map([OperatorInput.NO_OPERATOR_ASSIGNED]) | "Extracting UUID for field 'operator' failed. Caused by: Entity with uuid f15105c4-a2de-4ab8-a621-4bc98e372d92 was not provided." } def "An EntitySource returns a failure if a given map does not contain the given uuid"() { diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/SystemParticipantSourceTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/SystemParticipantSourceTest.groovy index aeb9f8829..845594901 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/SystemParticipantSourceTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/SystemParticipantSourceTest.groovy @@ -21,7 +21,7 @@ class SystemParticipantSourceTest extends Specification { def "An SystemParticipantSource participantEnricher should work as expected"() { given: - def entityData = new ConnectorInputEntityData(["operators": "", "node": sptd.participantNode.uuid.toString(), "em": sptd.emInput.uuid.toString()], LineInput, GridTestData.nodeA, GridTestData.nodeB) + def entityData = new ConnectorInputEntityData(["operators": "", "node": sptd.participantNode.uuid.toString(), "controllingEm": sptd.emInput.uuid.toString()], LineInput, GridTestData.nodeA, GridTestData.nodeB) def operators = map([OperatorInput.NO_OPERATOR_ASSIGNED]) def nodes = map([sptd.participantNode]) def emUnits = map([sptd.emInput]) @@ -33,7 +33,7 @@ class SystemParticipantSourceTest extends Specification { actual.success actual.data.get().operatorInput == OperatorInput.NO_OPERATOR_ASSIGNED actual.data.get().node == sptd.participantNode - actual.data.get().em == Optional.of(sptd.emInput) + actual.data.get().controllingEm == Optional.of(sptd.emInput) } def "An SystemParticipantSource can enrich SystemParticipantEntityData with SystemParticipantTypeInput correctly"() { diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/TimeSeriesMappingSourceTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/TimeSeriesMappingSourceTest.groovy index 9b5da47e2..d706fffc8 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/TimeSeriesMappingSourceTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/TimeSeriesMappingSourceTest.groovy @@ -98,8 +98,7 @@ class TimeSeriesMappingSourceTest extends Specification { then: def ex = thrown(SourceException) - ex.cause.class == FailureException - ex.cause.message.startsWith("1 exception(s) occurred within \"MappingEntry\" data") + ex.message.startsWith("1 exception(s) occurred within \"MappingEntry\" data") } def "should throw SourceException for invalid timeSeries"(){ @@ -110,8 +109,7 @@ class TimeSeriesMappingSourceTest extends Specification { then: def ex = thrown(SourceException) - ex.cause.class == FailureException - ex.cause.message.startsWith("1 exception(s) occurred within \"MappingEntry\" data") + ex.message.startsWith("1 exception(s) occurred within \"MappingEntry\" data") } def "should throw SourceException for invalid timeSeries and asset"(){ @@ -122,7 +120,8 @@ class TimeSeriesMappingSourceTest extends Specification { then: def ex = thrown(SourceException) - ex.cause.class == FailureException - ex.cause.message.startsWith("2 exception(s) occurred within \"MappingEntry\" data") + ex.message == "2 exception(s) occurred within \"MappingEntry\" data: \n" + + " An error occurred when creating instance of MappingEntry.class. Caused by: Exception while trying to parse UUID of field \"asset\" with value \"invalidAsset\"\n" + + " An error occurred when creating instance of MappingEntry.class. Caused by: Exception while trying to parse UUID of field \"asset\" with value \"invalidAsset2\"" } } diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvDataSourceTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvDataSourceTest.groovy index 9e4a8a614..754c62fa8 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvDataSourceTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvDataSourceTest.groovy @@ -123,10 +123,22 @@ class CsvDataSourceTest extends Specification implements CsvTestDataMeta { "q_characteristics", "e_cons_annual", "operator", - "em" + "controlling_em" ] as Set } + def "A CsvDataSource should throw an exception when retrieving column names from a valid CSV file using the wrong separator"() { + given: + DummyCsvSource source = new DummyCsvSource(";", participantsFolderPath, fileNamingStrategy) + + when: + source.getSourceFields(LoadInput) + + then: + SourceException ex = thrown(SourceException) + ex.message == "The given file has less than two columns! (Used separator ';' on headline 'uuid,cos_phi_rated,e_cons_annual,id,node,operates_from,operates_until,operator,q_characteristics,s_rated,load_profile,controlling_em')" + } + def "A CsvDataSource should return an empty result when retrieving column names for a non-existing CSV file"() { given: def path = Path.of("this/path/does-not-exist") @@ -322,16 +334,15 @@ class CsvDataSourceTest extends Specification implements CsvTestDataMeta { then: def exception = thrown(SourceException) - exception.getMessage().startsWith("The size of the headline (8) does not fit to the size of the attribute fields") + exception.getMessage() == expectedMessage where: - invalidCsvRow || explaination - "5ebd8f7e-dedb-4017-bb86-6373c4b68eb8;25.0;100.0;0.95;98.0;test_bmTypeInput;50.0;25.0" || "wrong separator" - "5ebd8f7e-dedb-4017-bb86-6373c4b68eb8,25.0,100.0,0.95,98.0,test_bmTypeInput" || "too little columns" - "5ebd8f7e-dedb-4017-bb86-6373c4b68eb8,25.0,100.0,0.95,98.0,test_bmTypeInput,,,," || "too many columns" + invalidCsvRow || explaination || expectedMessage + "5ebd8f7e-dedb-4017-bb86-6373c4b68eb8;25.0;100.0;0.95;98.0;test_bmTypeInput;50.0;25.0" || "wrong separator" || "The size of the headline (8) does not fit to the size of the attribute fields (1).\n Headline fields: ['uuid', 'active_power_gradient', 'capex', 'cosphi_rated', 'eta_conv', 'id', 'opex', 's_rated']\n Row values: ['5ebd8f7e-dedb-4017-bb86-6373c4b68eb8;25.0;100.0;0.95;98.0;test_bmTypeInput;50.0;25.0'].\n Please check:\n - is the csv separator in the row matching the provided separator ','\n - does the number of columns match the number of headline fields \n - are you using a valid RFC 4180 formatted csv row?" + "5ebd8f7e-dedb-4017-bb86-6373c4b68eb8,25.0,100.0,0.95,98.0,test_bmTypeInput" || "too little columns" || "The size of the headline (8) does not fit to the size of the attribute fields (6).\n Headline fields: ['uuid', 'active_power_gradient', 'capex', 'cosphi_rated', 'eta_conv', 'id', 'opex', 's_rated']\n Row values: ['5ebd8f7e-dedb-4017-bb86-6373c4b68eb8', '25.0', '100.0', '0.95', '98.0', 'test_bmTypeInput'].\n Please check:\n - is the csv separator in the row matching the provided separator ','\n - does the number of columns match the number of headline fields \n - are you using a valid RFC 4180 formatted csv row?" + "5ebd8f7e-dedb-4017-bb86-6373c4b68eb8,25.0,100.0,0.95,98.0,test_bmTypeInput,,,," || "too many columns" || "The size of the headline (8) does not fit to the size of the attribute fields (10).\n Headline fields: ['uuid', 'active_power_gradient', 'capex', 'cosphi_rated', 'eta_conv', 'id', 'opex', 's_rated']\n Row values: ['5ebd8f7e-dedb-4017-bb86-6373c4b68eb8', '25.0', '100.0', '0.95', '98.0', 'test_bmTypeInput', '', '', '', ''].\n Please check:\n - is the csv separator in the row matching the provided separator ','\n - does the number of columns match the number of headline fields \n - are you using a valid RFC 4180 formatted csv row?" } - def "A CsvDataSource should throw an exception if there are duplicate headlines"() { given: def invalidHeadline = [ diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvGraphicSourceTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvGraphicSourceTest.groovy index 9a7b15fc5..24c33f1e7 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvGraphicSourceTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvGraphicSourceTest.groovy @@ -70,7 +70,9 @@ class CsvGraphicSourceTest extends Specification implements CsvTestDataMeta { Exception ex = graphicElements.exception.get() ex.class == GraphicSourceException - ex.message.startsWith("1 error(s) occurred while initializing graphic elements. edu.ie3.datamodel.exceptions.FailureException: 1 exception(s) occurred within \"LineGraphicInput\" data, one is: edu.ie3.datamodel.exceptions.FactoryException: edu.ie3.datamodel.exceptions.SourceException: Entity with uuid 91ec3bcf-1777-4d38-af67-0bf7c9fa73c7 was not provided.") + ex.message == "Exception(s) occurred in 1 input file(s) while initializing graphic elements. \n" + + " 1 exception(s) occurred within \"LineGraphicInput\" data: \n" + + " Extracting UUID for field 'line' failed. Caused by: Entity with uuid 91ec3bcf-1777-4d38-af67-0bf7c9fa73c7 was not provided." } @@ -143,8 +145,7 @@ class CsvGraphicSourceTest extends Specification implements CsvTestDataMeta { then: def e = thrown(SourceException) - e.cause.class == FailureException - e.cause.message.startsWith(expectedFailures + " exception(s) occurred") + e.message.startsWith(expectedFailures + " exception(s) occurred") where: nodeCollection || expectedFailures @@ -167,8 +168,7 @@ class CsvGraphicSourceTest extends Specification implements CsvTestDataMeta { then: def e = thrown(SourceException) - e.cause.class == FailureException - e.cause.message.startsWith(expectedFailures + " exception(s) occurred") + e.message.startsWith(expectedFailures + " exception(s) occurred") where: lineCollection || expectedFailures diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvRawGridSourceTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvRawGridSourceTest.groovy index b3ad25998..6c62c4338 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvRawGridSourceTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvRawGridSourceTest.groovy @@ -268,7 +268,8 @@ class CsvRawGridSourceTest extends Specification implements CsvTestDataMeta { then: "the optional is empty" actual == null SourceException ex = thrown() - ex.message == "edu.ie3.datamodel.exceptions.FailureException: 1 exception(s) occurred within \"NodeInput\" data, one is: edu.ie3.datamodel.exceptions.FactoryException: An error occurred when creating instance of NodeInput.class." + ex.message == "1 exception(s) occurred within \"NodeInput\" data: \n" + + " An error occurred when creating instance of NodeInput.class. Caused by: Exception while trying to parse UUID of field \"uuid\" with value \"bd837a25-58f3-44ac-aa90-c6b6e3 cd91b2\"" } def "The CsvRawGridSource returns an empty grid, if the RawGridElements contain no single element"() { @@ -308,6 +309,8 @@ class CsvRawGridSourceTest extends Specification implements CsvTestDataMeta { Exception ex = rawGridElements.exception.get() ex.class == SourceException - ex.message.startsWith("edu.ie3.datamodel.exceptions.FailureException: 2 exception(s) occurred within \"LineInput\" data, one is: edu.ie3.datamodel.exceptions.FactoryException: edu.ie3.datamodel.exceptions.SourceException: Entity with uuid ") + ex.message == "2 exception(s) occurred within \"LineInput\" data: \n" + + " Extracting UUID for field 'nodeA' failed. Caused by: Entity with uuid 4ca90220-74c2-4369-9afa-a18bf068840d was not provided.\n" + + " Extracting UUID for field 'nodeA' failed. Caused by: Entity with uuid bd837a25-58f3-44ac-aa90-c6b6e3cd91b2 was not provided." } } \ No newline at end of file diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvSystemParticipantSourceTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvSystemParticipantSourceTest.groovy index 67316ab30..293ae514b 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvSystemParticipantSourceTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/csv/CsvSystemParticipantSourceTest.groovy @@ -76,10 +76,27 @@ class CsvSystemParticipantSourceTest extends Specification implements CsvTestDat Exception ex = systemParticipants.exception.get() ex.class == SystemParticipantsException - ex.message.startsWith("10 error(s) occurred while initializing system participants. " + - "edu.ie3.datamodel.exceptions.FailureException: 1 exception(s) occurred within " + - "\"FixedFeedInInput\" data, one is: edu.ie3.datamodel.exceptions.FactoryException: " + - "edu.ie3.datamodel.exceptions.SourceException: Entity with uuid 4ca90220-74c2-4369-9afa-a18bf068840d was not provided.") + ex.message == "Exception(s) occurred in 10 input file(s) while initializing system participants.\n" + + " 1 exception(s) occurred within \"FixedFeedInInput\" data: \n" + + " Extracting UUID for field 'node' failed. Caused by: Entity with uuid 4ca90220-74c2-4369-9afa-a18bf068840d was not provided.\n" + + " 1 exception(s) occurred within \"PvInput\" data: \n" + + " Extracting UUID for field 'node' failed. Caused by: Entity with uuid 4ca90220-74c2-4369-9afa-a18bf068840d was not provided.\n" + + " 1 exception(s) occurred within \"LoadInput\" data: \n" + + " Extracting UUID for field 'node' failed. Caused by: Entity with uuid 4ca90220-74c2-4369-9afa-a18bf068840d was not provided.\n" + + " 1 exception(s) occurred within \"BmInput\" data: \n" + + " Extracting UUID for field 'node' failed. Caused by: Entity with uuid 4ca90220-74c2-4369-9afa-a18bf068840d was not provided.\n" + + " 1 exception(s) occurred within \"StorageInput\" data: \n" + + " Extracting UUID for field 'node' failed. Caused by: Entity with uuid 4ca90220-74c2-4369-9afa-a18bf068840d was not provided.\n" + + " 1 exception(s) occurred within \"WecInput\" data: \n" + + " Extracting UUID for field 'node' failed. Caused by: Entity with uuid 4ca90220-74c2-4369-9afa-a18bf068840d was not provided.\n" + + " 1 exception(s) occurred within \"EvInput\" data: \n" + + " Extracting UUID for field 'node' failed. Caused by: Entity with uuid 4ca90220-74c2-4369-9afa-a18bf068840d was not provided.\n" + + " 1 exception(s) occurred within \"EvcsInput\" data: \n" + + " Extracting UUID for field 'node' failed. Caused by: Entity with uuid 4ca90220-74c2-4369-9afa-a18bf068840d was not provided.\n" + + " 1 exception(s) occurred within \"ChpInput\" data: \n" + + " Extracting UUID for field 'node' failed. Caused by: Entity with uuid 4ca90220-74c2-4369-9afa-a18bf068840d was not provided.\n" + + " 1 exception(s) occurred within \"HpInput\" data: \n" + + " Extracting UUID for field 'node' failed. Caused by: Entity with uuid 4ca90220-74c2-4369-9afa-a18bf068840d was not provided." } def "A SystemParticipantSource with csv input should return data from valid input file as expected"() { diff --git a/src/test/groovy/edu/ie3/datamodel/utils/ContainerUtilsTest.groovy b/src/test/groovy/edu/ie3/datamodel/utils/ContainerUtilsTest.groovy index c07ff0d54..660603fe9 100644 --- a/src/test/groovy/edu/ie3/datamodel/utils/ContainerUtilsTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/utils/ContainerUtilsTest.groovy @@ -553,176 +553,7 @@ class ContainerUtilsTest extends Specification { * - filtering of system participants can be tested * - filtering of graphic elements can be tested */ - def "Traversing along a simple switch chain returns the correct list of traveled nodes"() { - given: - def nodeA = Mock(NodeInput) - def nodeB = Mock(NodeInput) - def nodeC = Mock(NodeInput) - def nodeD = Mock(NodeInput) - - def switchAB = Mock(SwitchInput) - switchAB.getNodeA() >> nodeA - switchAB.getNodeB() >> nodeB - switchAB.allNodes() >> List.of(nodeA, nodeB) - def switchBC = Mock(SwitchInput) - switchBC.getNodeA() >> nodeB - switchBC.getNodeB() >> nodeC - switchBC.allNodes() >> List.of(nodeB, nodeC) - def switchCD = Mock(SwitchInput) - switchCD.getNodeA() >> nodeC - switchCD.getNodeB() >> nodeD - switchCD.allNodes() >> List.of(nodeC, nodeD) - - def switches = new HashSet() - switches.add(switchAB) - switches.add(switchBC) - switches.add(switchCD) - - def possibleJunctions = new HashSet() - - def expected = new LinkedList() - expected.addFirst(nodeA) - expected.addLast(nodeB) - expected.addLast(nodeC) - expected.addLast(nodeD) - - when: - def actual = ContainerUtils.traverseAlongSwitchChain(nodeA, switches, possibleJunctions) - - then: - actual == expected - } - - def "Traversing along a switch chain with intermediate junction returns the correct list of traveled nodes"() { - given: - def nodeA = Mock(NodeInput) - def nodeB = Mock(NodeInput) - def nodeC = Mock(NodeInput) - def nodeD = Mock(NodeInput) - - def switchAB = Mock(SwitchInput) - switchAB.getNodeA() >> nodeA - switchAB.getNodeB() >> nodeB - switchAB.allNodes() >> List.of(nodeA, nodeB) - def switchBC = Mock(SwitchInput) - switchBC.getNodeA() >> nodeB - switchBC.getNodeB() >> nodeC - switchBC.allNodes() >> List.of(nodeB, nodeC) - def switchCD = Mock(SwitchInput) - switchCD.getNodeA() >> nodeC - switchCD.getNodeB() >> nodeD - switchCD.allNodes() >> List.of(nodeC, nodeD) - - def switches = new HashSet() - switches.add(switchAB) - switches.add(switchBC) - switches.add(switchCD) - - def possibleJunctions = new HashSet() - possibleJunctions.add(nodeC) - - def expected = new LinkedList() - expected.addFirst(nodeA) - expected.addLast(nodeB) - expected.addLast(nodeC) - - when: - def actual = ContainerUtils.traverseAlongSwitchChain(nodeA, switches, possibleJunctions) - - then: - actual == expected - } - - def "Traversing along a non existing switch chain returns the correct list of traveled nodes"() { - given: - def nodeA = Mock(NodeInput) - - def switches = new HashSet() - - def possibleJunctions = new HashSet() - - def expected = new LinkedList() - expected.addFirst(nodeA) - - when: - def actual = ContainerUtils.traverseAlongSwitchChain(nodeA, switches, possibleJunctions) - - then: - actual == expected - } - - def "Traversing along a cyclic switch chain throws an exception"() { - given: - def nodeA = Mock(NodeInput) - def nodeB = Mock(NodeInput) - def nodeC = Mock(NodeInput) - - def switchAB = Mock(SwitchInput) - switchAB.getNodeA() >> nodeA - switchAB.getNodeB() >> nodeB - switchAB.allNodes() >> List.of(nodeA, nodeB) - def switchBC = Mock(SwitchInput) - switchBC.getNodeA() >> nodeB - switchBC.getNodeB() >> nodeC - switchBC.allNodes() >> List.of(nodeB, nodeC) - def switchCA = Mock(SwitchInput) - switchCA.getNodeA() >> nodeC - switchCA.getNodeB() >> nodeA - switchCA.allNodes() >> List.of(nodeC, nodeA) - - def switches = new HashSet() - switches.add(switchAB) - switches.add(switchBC) - switches.add(switchCA) - - def possibleJunctions = new HashSet() - - when: - ContainerUtils.traverseAlongSwitchChain(nodeA, switches, possibleJunctions) - - then: - IllegalArgumentException ex = thrown() - ex.message == "Cannot traverse along switch chain, as there is a junction included at node Mock for type " + - "'NodeInput' named 'nodeA'" - } - - def "Traversing along a switch chain with switch junction throws an exception"() { - given: - def nodeA = Mock(NodeInput) - def nodeB = Mock(NodeInput) - def nodeC = Mock(NodeInput) - def nodeD = Mock(NodeInput) - - def switchAB = Mock(SwitchInput) - switchAB.getNodeA() >> nodeA - switchAB.getNodeB() >> nodeB - switchAB.allNodes() >> List.of(nodeA, nodeB) - def switchBC = Mock(SwitchInput) - switchBC.getNodeA() >> nodeB - switchBC.getNodeB() >> nodeC - switchBC.allNodes() >> List.of(nodeB, nodeC) - def switchBD = Mock(SwitchInput) - switchBD.getNodeA() >> nodeB - switchBD.getNodeB() >> nodeD - switchBD.allNodes() >> List.of(nodeB, nodeD) - - def switches = new HashSet() - switches.add(switchAB) - switches.add(switchBC) - switches.add(switchBD) - - def possibleJunctions = new HashSet() - - when: - ContainerUtils.traverseAlongSwitchChain(nodeA, switches, possibleJunctions) - - then: - IllegalArgumentException ex = thrown() - ex.message == "Cannot traverse along switch chain, as there is a junction included at node Mock for type " + - "'NodeInput' named 'nodeB'" - } - - def "Determining the surrounding sub grid containers of a two winding transformer w/o switchgear works fine"() { + def "Determining the surrounding sub grid containers of a two winding transformer works fine"() { given: def nodeD = Mock(NodeInput) nodeD.getUuid() >> UUID.fromString("ae4869d5-3551-4cce-a101-d61629716c4f") @@ -754,66 +585,4 @@ class ContainerUtilsTest extends Specification { then: actual == expected } - - def "Determining the surrounding sub grid containers of a two winding transformer w/ switchgear works fine"() { - given: - def nodeA = Mock(NodeInput) - nodeA.getUuid() >> UUID.fromString("a37b2501-70c5-479f-92f9-d5b0e4628b2b") - nodeA.getSubnet() >> 1 - def nodeB = Mock(NodeInput) - nodeB.getUuid() >> UUID.fromString("8361b082-9d4c-4c54-97d0-2df9ac35333c") - nodeB.getSubnet() >> 2 - def nodeC = Mock(NodeInput) - nodeC.getUuid() >> UUID.fromString("b9e4f16b-0317-4794-9f53-339db45a2092") - nodeC.getSubnet() >> 2 - def nodeD = Mock(NodeInput) - nodeD.getUuid() >> UUID.fromString("ae4869d5-3551-4cce-a101-d61629716c4f") - nodeD.getSubnet() >> 2 - def nodeE = Mock(NodeInput) - nodeE.getUuid() >> UUID.fromString("5d4107b2-385b-40fe-a668-19414bf45d9d") - nodeE.getSubnet() >> 2 - - def transformer = Mock(Transformer2WInput) - transformer.getUuid() >> UUID.fromString("ddcdd72a-5f97-4bef-913b-d32d31216e27") - transformer.getNodeA() >> nodeD - transformer.getNodeB() >> nodeE - transformer.allNodes() >> List.of(nodeD, nodeE) - - def switchAB = Mock(SwitchInput) - switchAB.getUuid() >> UUID.fromString("5fcb8705-1436-4fbe-97b3-d2dcaf6a783b") - switchAB.allNodes() >> List.of(nodeA, nodeB) - def switchBC = Mock(SwitchInput) - switchBC.getUuid() >> UUID.fromString("4ca81b0b-e06d-408e-a991-de140f4e229b") - switchBC.allNodes() >> List.of(nodeB, nodeC) - def switchCD = Mock(SwitchInput) - switchCD.getUuid() >> UUID.fromString("92ce075e-9e3b-4ee6-89b6-19e6372fba01") - switchCD.allNodes() >> List.of(nodeC, nodeD) - - def rawGridElements = new RawGridElements([ - nodeA, - nodeB, - nodeC, - nodeD, - nodeE, - transformer, - switchAB, - switchBC, - switchCD - ]) - - def subGrid1 = Mock(SubGridContainer) - def subGrid2 = Mock(SubGridContainer) - def subGridMapping = [ - 1: subGrid1, - 2: subGrid2 - ] - - def expected = new ContainerUtils.TransformerSubGridContainers(subGrid1, subGrid2) - - when: - def actual = ContainerUtils.getSubGridContainers(transformer, rawGridElements, subGridMapping) - - then: - actual == expected - } } diff --git a/src/test/groovy/edu/ie3/datamodel/utils/TryTest.groovy b/src/test/groovy/edu/ie3/datamodel/utils/TryTest.groovy index b7d636a15..59909cb14 100644 --- a/src/test/groovy/edu/ie3/datamodel/utils/TryTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/utils/TryTest.groovy @@ -233,17 +233,18 @@ class TryTest extends Specification { given: Set> set = Set.of( new Try.Success<>("one"), - new Try.Failure<>(new Exception("exception")), + new Try.Failure<>(new Exception("exception", new SourceException("source exception"))), new Try.Success<>("two"), new Try.Success<>("three") ) when: - Try, Exception> scan = Try.scanCollection(set, String) + Try, Exception> scan = Try.scanCollection(set, String, Exception::new) then: scan.failure - scan.exception.get().message == "1 exception(s) occurred within \"String\" data, one is: java.lang.Exception: exception" + scan.exception.get().message == "1 exception(s) occurred within \"String\" data: \n" + + " exception Caused by: source exception" } def "A scan for exceptions should work as expected when no failures are included"() { @@ -255,7 +256,7 @@ class TryTest extends Specification { ) when: - Try, Exception> scan = Try.scanCollection(set, String) + Try, Exception> scan = Try.scanCollection(set, String, Exception::new) then: scan.success diff --git a/src/test/groovy/edu/ie3/datamodel/utils/validation/EmValidationUtilsTest.groovy b/src/test/groovy/edu/ie3/datamodel/utils/validation/EmValidationUtilsTest.groovy new file mode 100644 index 000000000..ed5139031 --- /dev/null +++ b/src/test/groovy/edu/ie3/datamodel/utils/validation/EmValidationUtilsTest.groovy @@ -0,0 +1,41 @@ +/* + * © 2025. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation + */ +package edu.ie3.datamodel.utils.validation + +import edu.ie3.datamodel.exceptions.InvalidEntityException +import edu.ie3.datamodel.exceptions.ValidationException +import edu.ie3.datamodel.utils.Try +import edu.ie3.test.common.GridTestData +import spock.lang.Specification + +class EmValidationUtilsTest extends Specification { + + def "Smoke Test: Correct energy management system throws no exception"() { + given: + def em = GridTestData.energyManagementInput + + when: + List> tries = EnergyManagementValidationUtils.check(em) + + then: + tries.every { it.success } + } + + def "The check method recognizes all potential errors for an energy management input"() { + when: + List> exceptions = EnergyManagementValidationUtils.check(invalidEm).stream().filter { it -> it.failure }.toList() + + then: + exceptions.size() == expectedSize + Exception ex = exceptions.get(0).exception.get() + ex.class == expectedException.class + ex.message == expectedException.message + + where: + invalidEm || expectedSize || expectedException + GridTestData.energyManagementInput.copy().controlStrategy(null).build() || 1 || new InvalidEntityException("No control strategy of energy management defined for", invalidEm) + } +} diff --git a/src/test/groovy/edu/ie3/datamodel/utils/validation/SystemParticipantValidationUtilsTest.groovy b/src/test/groovy/edu/ie3/datamodel/utils/validation/SystemParticipantValidationUtilsTest.groovy index c89d7d005..a8c90b766 100644 --- a/src/test/groovy/edu/ie3/datamodel/utils/validation/SystemParticipantValidationUtilsTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/utils/validation/SystemParticipantValidationUtilsTest.groovy @@ -99,10 +99,8 @@ class SystemParticipantValidationUtilsTest extends Specification { SystemParticipantValidationUtils.check(invalidType) then: - Throwable topEx = thrown() - Throwable ex = topEx.cause - ex.class == expectedException.class - ex.message == expectedException.message + Throwable ex = thrown() + ex.message.contains(expectedException.message) where: invalidType || expectedException @@ -142,10 +140,8 @@ class SystemParticipantValidationUtilsTest extends Specification { ValidationUtils.check(invalidBmType) then: - Throwable topEx = thrown() - Throwable ex = topEx.cause - ex.class == expectedException.class - ex.message == expectedException.message + Throwable ex = thrown() + ex.message.contains(expectedException.message) where: invalidBmType || expectedException @@ -184,10 +180,8 @@ class SystemParticipantValidationUtilsTest extends Specification { SystemParticipantValidationUtils.check(invalidChpType) then: - Throwable topEx = thrown() - Throwable ex = topEx.cause - ex.class == expectedException.class - ex.message == expectedException.message + Throwable ex = thrown() + ex.message.contains(expectedException.message) where: invalidChpType || expectedException @@ -228,10 +222,8 @@ class SystemParticipantValidationUtilsTest extends Specification { SystemParticipantValidationUtils.check(invalidEvType) then: - Throwable topEx = thrown() - Throwable ex = topEx.cause - ex.class == expectedException.class - ex.message == expectedException.message + Throwable ex = thrown() + ex.message.contains(expectedException.message) where: invalidEvType || expectedException @@ -298,10 +290,8 @@ class SystemParticipantValidationUtilsTest extends Specification { SystemParticipantValidationUtils.check(invalidHpType) then: - Throwable topEx = thrown() - Throwable ex = topEx.cause - ex.class == expectedException.class - ex.message == expectedException.message + Throwable ex = thrown() + ex.message.contains(expectedException.message) where: invalidHpType || expectedException @@ -365,7 +355,7 @@ class SystemParticipantValidationUtilsTest extends Specification { invalidPV || expectedSize || expectedException SystemParticipantTestData.pvInput.copy().sRated(Quantities.getQuantity(-25d, ACTIVE_POWER_IN)).build() || 1 || new InvalidEntityException("The following quantities have to be zero or positive: -25 kVA", invalidPV) SystemParticipantTestData.pvInput.copy().albedo(2).build() || 1 || new InvalidEntityException("Albedo of the plant's surrounding of PvInput must be between 0 and 1", invalidPV) - SystemParticipantTestData.pvInput.copy().azimuth(Quantities.getQuantity(-100d, AZIMUTH)).build() || 1 || new InvalidEntityException("Azimuth angle of PvInput must be between -90° (east) and 90° (west)", invalidPV) + SystemParticipantTestData.pvInput.copy().azimuth(Quantities.getQuantity(-181d, AZIMUTH)).build() || 1 || new InvalidEntityException("Azimuth angle of PvInput must be between -180° and 180°", invalidPV) SystemParticipantTestData.pvInput.copy().etaConv(Quantities.getQuantity(110d, EFFICIENCY)).build() || 1 || new InvalidEntityException("Efficiency of the converter of PvInput must be between 0% and 100%", invalidPV) SystemParticipantTestData.pvInput.copy().elevationAngle(Quantities.getQuantity(100d, SOLAR_ELEVATION_ANGLE)).build() || 1 || new InvalidEntityException("Tilted inclination from horizontal of PvInput must be between 0° and 90°", invalidPV) SystemParticipantTestData.pvInput.copy().cosPhiRated(2).build() || 1 || new InvalidEntityException("Rated power factor of PvInput must be between 0 and 1", invalidPV) @@ -402,10 +392,8 @@ class SystemParticipantValidationUtilsTest extends Specification { SystemParticipantValidationUtils.check(invalidStorageType) then: - Throwable topEx = thrown() - Throwable ex = topEx.cause - ex.class == expectedException.class - ex.message == expectedException.message + Throwable ex = thrown() + ex.message.contains(expectedException.message) where: invalidStorageType || expectedException @@ -445,10 +433,8 @@ class SystemParticipantValidationUtilsTest extends Specification { SystemParticipantValidationUtils.check(invalidWecType) then: - Throwable topEx = thrown() - Throwable ex = topEx.cause - ex.class == expectedException.class - ex.message == expectedException.message + Throwable ex = thrown() + ex.message.contains(expectedException.message) where: invalidWecType || expectedException diff --git a/src/test/groovy/edu/ie3/datamodel/utils/validation/UniquenessValidationUtilsTest.groovy b/src/test/groovy/edu/ie3/datamodel/utils/validation/UniquenessValidationUtilsTest.groovy index 82066c52c..92169b0bf 100644 --- a/src/test/groovy/edu/ie3/datamodel/utils/validation/UniquenessValidationUtilsTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/utils/validation/UniquenessValidationUtilsTest.groovy @@ -97,9 +97,8 @@ class UniquenessValidationUtilsTest extends Specification { then: DuplicateEntitiesException de = thrown() - de.message == "The following exception(s) occurred while checking the uniqueness of 'AssetInput' entities: " + - "'DummyAssetInput' entities with duplicated String key, but different field values found! " + - "Affected primary keys: [first]" + de.message == "The following exception(s) occurred while checking the uniqueness of 'AssetInput' entities: \n" + + " 'DummyAssetInput' entities with duplicated String key, but different field values found! Affected primary keys: [first]" } def "Checking if result entities are unique"() { diff --git a/src/test/groovy/edu/ie3/datamodel/utils/validation/ValidationUtilsTest.groovy b/src/test/groovy/edu/ie3/datamodel/utils/validation/ValidationUtilsTest.groovy index 43d3b518f..74bf0a1b4 100644 --- a/src/test/groovy/edu/ie3/datamodel/utils/validation/ValidationUtilsTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/utils/validation/ValidationUtilsTest.groovy @@ -86,7 +86,7 @@ class ValidationUtilsTest extends Specification { then: InvalidEntityException ex = thrown() - ex.message == "Entity is invalid because of: \nThe following quantities have to be zero or positive: -1 µS/km [LineTypeInput{uuid=3bed3eb3-9790-4874-89b5-a5434d408088, id=lineType_AtoB, b=-1 µS/km, g=0.0 µS/km, r=0.437 Ω/km, x=0.356 Ω/km, iMax=300 A, vRated=20 kV}]" + ex.message == "Entity is invalid because of: The following quantities have to be zero or positive: -1 µS/km [LineTypeInput{uuid=3bed3eb3-9790-4874-89b5-a5434d408088, id=lineType_AtoB, b=-1 µS/km, g=0.0 µS/km, r=0.437 Ω/km, x=0.356 Ω/km, iMax=300 A, vRated=20 kV}]" } def "The check for zero or negative entities should work as expected"() { @@ -123,7 +123,7 @@ class ValidationUtilsTest extends Specification { then: InvalidEntityException ex = thrown() - ex.message == "Entity is invalid because of: \nThe following quantities have to be positive: 0.0 µS/km [LineTypeInput{uuid=3bed3eb3-9790-4874-89b5-a5434d408088, id=lineType_AtoB, b=0.0 µS/km, g=0.0 µS/km, r=0.437 Ω/km, x=0.356 Ω/km, iMax=300 A, vRated=20 kV}]" + ex.message == "Entity is invalid because of: The following quantities have to be positive: 0.0 µS/km [LineTypeInput{uuid=3bed3eb3-9790-4874-89b5-a5434d408088, id=lineType_AtoB, b=0.0 µS/km, g=0.0 µS/km, r=0.437 Ω/km, x=0.356 Ω/km, iMax=300 A, vRated=20 kV}]" } def "Checking an asset type input without an id leads to an exception"() { @@ -136,6 +136,6 @@ class ValidationUtilsTest extends Specification { then: exceptions.size() == 1 def e = exceptions.get(0).exception.get() - e.message.startsWith("Entity is invalid because of: \nNo ID assigned [AssetTypeInput") + e.message.startsWith("Entity is invalid because of: No ID assigned [AssetTypeInput") } } diff --git a/src/test/groovy/edu/ie3/test/common/GridTestData.groovy b/src/test/groovy/edu/ie3/test/common/GridTestData.groovy index 2ca15217c..87c13de89 100644 --- a/src/test/groovy/edu/ie3/test/common/GridTestData.groovy +++ b/src/test/groovy/edu/ie3/test/common/GridTestData.groovy @@ -9,6 +9,7 @@ import static edu.ie3.datamodel.models.StandardUnits.* import static edu.ie3.util.quantities.PowerSystemUnits.* import edu.ie3.datamodel.models.OperationTime +import edu.ie3.datamodel.models.input.EmInput import edu.ie3.datamodel.models.input.MeasurementUnitInput import edu.ie3.datamodel.models.input.NodeInput import edu.ie3.datamodel.models.input.OperatorInput @@ -387,4 +388,13 @@ class GridTestData { true, true ) + + public static final EmInput energyManagementInput = new EmInput( + UUID.fromString("4bef6955-5e31-4283-8920-5e4cae267a23"), + "test_energyManagement", + profBroccoli, + defaultOperationTime, + "PRIORITIZED", + null, + ) } diff --git a/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/bm_input.csv b/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/bm_input.csv index 9e690815a..86d29a1f5 100644 --- a/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/bm_input.csv +++ b/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/bm_input.csv @@ -1,2 +1,2 @@ -uuid,cost_controlled,feed_in_tariff,id,market_reaction,node,operates_from,operates_until,operator,q_characteristics,type,em +uuid,cost_controlled,feed_in_tariff,id,market_reaction,node,operates_from,operates_until,operator,q_characteristics,type,controlling_em d06e5bb7-a3c7-4749-bdd1-4581ff2f6f4d,false,10.0,test_bmInput,false,4ca90220-74c2-4369-9afa-a18bf068840d,2020-03-24T15:11:31Z,2020-03-25T15:11:31Z,8f9682df-0744-4b58-a122-f0dc730f6510,"qV:{(0.90,-0.30),(0.95,0.00),(1.05,0.00),(1.10,0.30)}",5ebd8f7e-dedb-4017-bb86-6373c4b68eb8,977157f4-25e5-4c72-bf34-440edc778792 diff --git a/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/chp_input.csv b/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/chp_input.csv index 9f8be0765..e41e2d5c1 100644 --- a/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/chp_input.csv +++ b/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/chp_input.csv @@ -1,2 +1,2 @@ -uuid,id,market_reaction,node,operates_from,operates_until,operator,q_characteristics,thermal_bus,thermal_storage,type,em +uuid,id,market_reaction,node,operates_from,operates_until,operator,q_characteristics,thermal_bus,thermal_storage,type,controlling_em 9981b4d7-5a8e-4909-9602-e2e7ef4fca5c,test_chpInput,false,4ca90220-74c2-4369-9afa-a18bf068840d,2020-03-24T15:11:31Z,2020-03-25T15:11:31Z,8f9682df-0744-4b58-a122-f0dc730f6510,"cosPhiFixed:{(0.00,0.95)}",0d95d7f2-49fb-4d49-8636-383a5220384e,8851813b-3a7d-4fee-874b-4df9d724e4b3,5ebd8f7e-dedb-4017-bb86-6373c4b68eb8,977157f4-25e5-4c72-bf34-440edc778792 diff --git a/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/cylindrical_storage_input.csv b/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/cylindrical_storage_input.csv index 141286dbb..c3531deb5 100644 --- a/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/cylindrical_storage_input.csv +++ b/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/cylindrical_storage_input.csv @@ -1,2 +1,2 @@ -uuid,c,id,inlet_temp,operates_from,operates_until,operator,return_temp,storage_volume_lvl,p_thermal_max,thermal_bus,em +uuid,c,id,inlet_temp,operates_from,operates_until,operator,return_temp,storage_volume_lvl,p_thermal_max,thermal_bus,controlling_em 8851813b-3a7d-4fee-874b-4df9d724e4b3,1.0,test_cylindricalThermalStorage,110.0,,,f15105c4-a2de-4ab8-a621-4bc98e372d92,80.0,1.039154027,20.0,0d95d7f2-49fb-4d49-8636-383a5220384e,977157f4-25e5-4c72-bf34-440edc778792 diff --git a/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/em_input.csv b/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/em_input.csv index 14d20cb3e..f8e8263a2 100644 --- a/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/em_input.csv +++ b/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/em_input.csv @@ -1,3 +1,3 @@ -uuid,control_strategy,id,operates_from,operates_until,operator,parent_em +uuid,control_strategy,id,operates_from,operates_until,operator,controlling_em 977157f4-25e5-4c72-bf34-440edc778792,self_optimization,test_emInput,2020-03-24T15:11:31Z,2020-03-25T15:11:31Z,8f9682df-0744-4b58-a122-f0dc730f6510,897bfc17-8e54-43d0-8d98-740786fd94dd 897bfc17-8e54-43d0-8d98-740786fd94dd,self_optimization,test_parentEmInput,2020-03-24T15:11:31Z,2020-03-25T15:11:31Z,8f9682df-0744-4b58-a122-f0dc730f6510, \ No newline at end of file diff --git a/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/ev_input.csv b/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/ev_input.csv index dfb07f22d..634773452 100644 --- a/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/ev_input.csv +++ b/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/ev_input.csv @@ -1,2 +1,2 @@ -uuid,id,node,operates_from,operates_until,operator,q_characteristics,type,em +uuid,id,node,operates_from,operates_until,operator,q_characteristics,type,controlling_em a17be20f-c7a7-471d-8ffe-015487c9d022,test_evInput,4ca90220-74c2-4369-9afa-a18bf068840d,2020-03-24T15:11:31Z,2020-03-25T15:11:31Z,8f9682df-0744-4b58-a122-f0dc730f6510,"cosPhiFixed:{(0.00,0.95)}",5ebd8f7e-dedb-4017-bb86-6373c4b68eb8,977157f4-25e5-4c72-bf34-440edc778792 diff --git a/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/evcs_input.csv b/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/evcs_input.csv index d5579f7cd..0fd01d91f 100644 --- a/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/evcs_input.csv +++ b/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/evcs_input.csv @@ -1,2 +1,2 @@ -uuid,id,operator,operates_from,operates_until,node,q_characteristics,cos_phi_rated,type,charging_points,location_type,v2g_support,em +uuid,id,operator,operates_from,operates_until,node,q_characteristics,cos_phi_rated,type,charging_points,location_type,v2g_support,controlling_em 798028b5-caff-4da7-bcd9-1750fdd8742c,test_csInput,8f9682df-0744-4b58-a122-f0dc730f6510,2020-03-24T15:11:31Z,2020-03-25T15:11:31Z,4ca90220-74c2-4369-9afa-a18bf068840d,"cosPhiFixed:{(0.00,0.95)}",0.95,hhs,4,HOME,false,977157f4-25e5-4c72-bf34-440edc778792 \ No newline at end of file diff --git a/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/fixed_feed_in_input.csv b/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/fixed_feed_in_input.csv index 5d25bd18f..a9be543de 100644 --- a/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/fixed_feed_in_input.csv +++ b/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/fixed_feed_in_input.csv @@ -1,2 +1,2 @@ -uuid,cos_phi_rated,id,node,operates_from,operates_until,operator,q_characteristics,s_rated,em +uuid,cos_phi_rated,id,node,operates_from,operates_until,operator,q_characteristics,s_rated,controlling_em 717af017-cc69-406f-b452-e022d7fb516a,0.95,test_fixedFeedInInput,4ca90220-74c2-4369-9afa-a18bf068840d,2020-03-24T15:11:31Z,2020-03-25T15:11:31Z,8f9682df-0744-4b58-a122-f0dc730f6510,"cosPhiFixed:{(0.00,0.95)}",25.0,977157f4-25e5-4c72-bf34-440edc778792 diff --git a/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/hp_input.csv b/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/hp_input.csv index 9ed79f8ea..5ea7947c1 100644 --- a/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/hp_input.csv +++ b/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/hp_input.csv @@ -1,2 +1,2 @@ -uuid,id,node,operates_from,operates_until,operator,q_characteristics,thermal_bus,type,em +uuid,id,node,operates_from,operates_until,operator,q_characteristics,thermal_bus,type,controlling_em 798028b5-caff-4da7-bcd9-1750fdd8742b,test_hpInput,4ca90220-74c2-4369-9afa-a18bf068840d,2020-03-24T15:11:31Z,2020-03-25T15:11:31Z,8f9682df-0744-4b58-a122-f0dc730f6510,"cosPhiFixed:{(0.00,0.95)}",0d95d7f2-49fb-4d49-8636-383a5220384e,5ebd8f7e-dedb-4017-bb86-6373c4b68eb8,977157f4-25e5-4c72-bf34-440edc778792 diff --git a/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/load_input.csv b/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/load_input.csv index 4a2d97e37..1825a5ed6 100644 --- a/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/load_input.csv +++ b/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/load_input.csv @@ -1,2 +1,2 @@ -uuid,cos_phi_rated,e_cons_annual,id,node,operates_from,operates_until,operator,q_characteristics,s_rated,load_profile,em +uuid,cos_phi_rated,e_cons_annual,id,node,operates_from,operates_until,operator,q_characteristics,s_rated,load_profile,controlling_em eaf77f7e-9001-479f-94ca-7fb657766f5f,0.95,4000.0,test_loadInput,4ca90220-74c2-4369-9afa-a18bf068840d,2020-03-24T15:11:31Z,2020-03-25T15:11:31Z,8f9682df-0744-4b58-a122-f0dc730f6510,"cosPhiFixed:{(0.00,0.95)}",25.0,h0,977157f4-25e5-4c72-bf34-440edc778792 diff --git a/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/pv_input.csv b/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/pv_input.csv index 37e6b8666..3bdf961e3 100644 --- a/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/pv_input.csv +++ b/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/pv_input.csv @@ -1,2 +1,2 @@ -uuid,albedo,azimuth,cos_phi_rated,eta_conv,elevation_angle,id,k_g,k_t,market_reaction,node,operates_from,operates_until,operator,q_characteristics,s_rated,em +uuid,albedo,azimuth,cos_phi_rated,eta_conv,elevation_angle,id,k_g,k_t,market_reaction,node,operates_from,operates_until,operator,q_characteristics,s_rated,controlling_em d56f15b7-8293-4b98-b5bd-58f6273ce229,0.20000000298023224,-8.926613807678223,0.95,98.0,41.01871871948242,test_pvInput,0.8999999761581421,1.0,false,4ca90220-74c2-4369-9afa-a18bf068840d,2020-03-24T15:11:31Z,2020-03-25T15:11:31Z,8f9682df-0744-4b58-a122-f0dc730f6510,"cosPhiFixed:{(0.00,0.95)}",25.0,977157f4-25e5-4c72-bf34-440edc778792 diff --git a/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/storage_input.csv b/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/storage_input.csv index 158e8bbae..d21595f60 100644 --- a/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/storage_input.csv +++ b/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/storage_input.csv @@ -1,2 +1,2 @@ -uuid,id,node,operates_from,operates_until,operator,q_characteristics,type,em +uuid,id,node,operates_from,operates_until,operator,q_characteristics,type,controlling_em 06b58276-8350-40fb-86c0-2414aa4a0452,test_storageInput,4ca90220-74c2-4369-9afa-a18bf068840d,2020-03-24T15:11:31Z,2020-03-25T15:11:31Z,8f9682df-0744-4b58-a122-f0dc730f6510,"cosPhiFixed:{(0.00,0.95)}",5ebd8f7e-dedb-4017-bb86-6373c4b68eb8,977157f4-25e5-4c72-bf34-440edc778792 diff --git a/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/wec_input.csv b/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/wec_input.csv index 3305e2e25..0e717f7a2 100644 --- a/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/wec_input.csv +++ b/src/test/resources/edu/ie3/datamodel/io/source/csv/_participants/wec_input.csv @@ -1,2 +1,2 @@ -uuid,id,market_reaction,node,operates_from,operates_until,operator,q_characteristics,type,em +uuid,id,market_reaction,node,operates_from,operates_until,operator,q_characteristics,type,controlling_em ee7e2e37-a5ad-4def-a832-26a317567ca1,test_wecInput,false,4ca90220-74c2-4369-9afa-a18bf068840d,2020-03-24T15:11:31Z,2020-03-25T15:11:31Z,8f9682df-0744-4b58-a122-f0dc730f6510,"cosPhiP:{(0.00,1.00),(0.90,1.00),(1.20,-0.30)}",5ebd8f7e-dedb-4017-bb86-6373c4b68eb8,977157f4-25e5-4c72-bf34-440edc778792 diff --git a/version.properties b/version.properties index 232aa364b..414a5f2fc 100644 --- a/version.properties +++ b/version.properties @@ -1,8 +1,8 @@ #Generated by the Semver Plugin for Gradle -#Thu May 08 14:54:26 CEST 2025 +#Thu Jul 17 14:58:32 CEST 2025 version.buildmeta= -version.major=7 +version.major=8 version.minor=0 version.patch=0 version.prerelease= -version.semver=7.0.0 +version.semver=8.0.0