diff --git a/CHANGELOG.md b/CHANGELOG.md index 609e6327c..083590698 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased/Snapshot] +### Added + +### Fixed + +### Changed + +## [5.1.0] - 2024-06-24 + ### Added - Enhancing `VoltageLevel` with `equals` method [#1063](https://github.com/ie3-institute/PowerSystemDataModel/issues/1063) - `ConnectorValidationUtils` checks if parallel devices is > 0 [#1077](https://github.com/ie3-institute/PowerSystemDataModel/issues/1077) @@ -14,17 +22,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Fixed `MappingEntryies` not getting processed by adding `Getter` methods for record fields [#1084](https://github.com/ie3-institute/PowerSystemDataModel/issues/1084) +- Fixed "depth of discharge" in documentation [#872](https://github.com/ie3-institute/PowerSystemDataModel/issues/872) +- Fixed project being build twice in CI [#994](https://github.com/ie3-institute/PowerSystemDataModel/issues/994) ### Changed - Improvements to the search for corner points in `IdCoordinateSource` [#1016](https://github.com/ie3-institute/PowerSystemDataModel/issues/1016) - Refactor `CsvFileConnector` and `CsvDataSource` [#1007](https://github.com/ie3-institute/PowerSystemDataModel/issues/1007) - +- Make `EntitySource` completely static [#975](https://github.com/ie3-institute/PowerSystemDataModel/issues/975) +- Abstract commonly used functionality from `EntitySource` [#981](https://github.com/ie3-institute/PowerSystemDataModel/issues/981) ## [5.0.1] - 2024-03-07 ### Fixed - Fixed `equals` of `ResultEntity` and `TimeSeriesEntry` [#1037](https://github.com/ie3-institute/PowerSystemDataModel/issues/1037) -- Fixed "depth of discharge" in documentation [#872](https://github.com/ie3-institute/PowerSystemDataModel/issues/872) ## [5.0.0] - 2024-03-06 @@ -292,9 +302,10 @@ 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/5.0.1...HEAD -[5.0.0]: https://github.com/ie3-institute/powersystemdatamodel/compare/5.0.0...5.0.1 -[4.1.0]: https://github.com/ie3-institute/powersystemdatamodel/compare/4.1.0...5.0.0 +[Unreleased/Snapshot]: https://github.com/ie3-institute/powersystemdatamodel/compare/5.1.0...HEAD +[5.1.0]: https://github.com/ie3-institute/powersystemdatamodel/compare/5.0.1...5.1.0 +[5.0.1]: https://github.com/ie3-institute/powersystemdatamodel/compare/5.0.0...5.0.1 +[5.0.0]: https://github.com/ie3-institute/powersystemdatamodel/compare/4.1.0...5.0.0 [4.1.0]: https://github.com/ie3-institute/powersystemdatamodel/compare/4.0.0...4.1.0 [4.0.0]: https://github.com/ie3-institute/powersystemdatamodel/compare/3.0.0...4.0.0 [3.0.0]: https://github.com/ie3-institute/powersystemdatamodel/compare/2.1.0...3.0.0 diff --git a/Jenkinsfile b/Jenkinsfile index 1a6029879..ea043dbd5 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -113,7 +113,7 @@ node { gradle('--refresh-dependencies clean spotlessCheck pmdMain pmdTest spotbugsMain ' + 'spotbugsTest test jacocoTestReport jacocoTestCoverageVerification', projectName) - sh(script: """set +x && cd $projectName""" + ''' set +x; ./gradlew clean javadoc''', returnStdout: true) + sh(script: """set +x && cd $projectName""" + ''' set +x; ./gradlew javadoc''', returnStdout: true) } // sonarqube analysis @@ -156,7 +156,7 @@ node { */ sh( script: """set +x && cd $projectName""" + - ''' set +x; ./gradlew clean javadoc''', + ''' set +x; ./gradlew javadoc''', returnStdout: true ) diff --git a/build.gradle b/build.gradle index 019499ddd..e39a59206 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ plugins { id 'signing' id 'pmd' // code check, working on source code id 'com.diffplug.spotless' version '6.25.0' //code format - id 'com.github.spotbugs' version '6.0.16' // code check, working on byte code + id 'com.github.spotbugs' version '6.0.18' // 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 @@ -17,7 +17,7 @@ ext { //version (changing these should be considered thoroughly!) javaVersion = JavaVersion.VERSION_17 groovyVersion = "4.0" - groovyBinaryVersion = "4.0.21" + groovyBinaryVersion = "4.0.22" testcontainersVersion = '1.19.8' scriptsLocation = 'gradle' + File.separator + 'scripts' + File.separator //location of script plugins @@ -70,7 +70,7 @@ dependencies { // testing testImplementation "org.apache.groovy:groovy:$groovyBinaryVersion" - testImplementation 'org.junit.jupiter:junit-jupiter:5.10.2' + testImplementation 'org.junit.jupiter:junit-jupiter:5.10.3' 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.14.17' // Mocks of classes @@ -90,7 +90,7 @@ dependencies { // Databases implementation 'org.influxdb:influxdb-java:2.24' - implementation 'com.couchbase.client:java-client:3.6.2' + implementation 'com.couchbase.client:java-client:3.7.0' runtimeOnly 'org.postgresql:postgresql:42.7.3' // postgresql jdbc driver required during runtime implementation 'commons-io:commons-io:2.16.1' // I/O functionalities diff --git a/docs/uml/main/EntitySourceClassDiagram.puml b/docs/uml/main/EntitySourceClassDiagram.puml index 56ac69c40..a9ae77130 100644 --- a/docs/uml/main/EntitySourceClassDiagram.puml +++ b/docs/uml/main/EntitySourceClassDiagram.puml @@ -3,27 +3,38 @@ note "Assuming all classes to implement \nthe abstract methods of their interfaces\n\n" as generalNotes abstract class EntitySource { - # DataSource dataSource - # {static} Try enrichEntityData(E, String, Map, BiFunction) - # {static} Try enrichEntityData(E, String, Map, String, Map, TriFunction) - # {static} Try getLinkedEntity(EntityData, String, Map) - # {static} Try optionallyEnrichEntityData(E, String, Map, T, BiFunction) - # Stream> buildNodeAssetEntities(Class, Map, Map) - # {static} Stream> nodeAssetInputEntityDataStream(Stream>, Map) - # Stream> buildAssetInputEntities(Class, Map) - # {static} Stream> assetInputEntityDataStream(Stream>, Map) - # Stream> buildEntityData(Class) - # {static} Map unpackMap(Stream>, Class) throws SourceException - # {static} Set unpackSet(Stream>, Class) throws SourceException - # {static} Stream unpackSet(Stream>, Class) throws SourceException + + void validate() throws ValidationException } +EntitySource <|-- EnergyManagementSource EntitySource <|-- GraphicSource +EntitySource <|-- IdCoordinateSource +IdCoordinateSource <|-- CsvIdCoordinateSource +IdCoordinateSource <|-- SqlIdCoordinateSource EntitySource <|-- RawGridSource EntitySource <|-- ResultEntitySource EntitySource <|-- SystemParticipantSource EntitySource <|-- ThermalSource +EntitySource <|-- TimeSeriesMappingSource +TimeSeriesMappingSource <|-- CsvTimeSeriesMappingSource +TimeSeriesMappingSource <|-- SqlTimeSeriesMappingSource +EntitySource <|-- TimeSeriesSource +TimeSeriesSource <|-- CsvTimeSeriesSource +TimeSeriesSource <|-- SqlTimeSeriesSource EntitySource <|-- TypeSource +EntitySource <|-- WeatherSource +WeatherSource <|-- CouchbaseWeatherSource +WeatherSource <|-- CsvWeatherSource +WeatherSource <|-- InfluxDbWeatherSource +WeatherSource <|-- SqlWeatherSource + +class EnergyManagementSource { + - TypeSource typeSource + - EmInputFactory emInputFactory + + EnergyManagementSource(TypeSource, DataSource) + + Map getEmUnits() throws SourceException + + Map getEmUnits(Map) throws SourceException +} class GraphicSource { - TypeSource typeSource @@ -39,6 +50,34 @@ class GraphicSource { + Set getLineGraphicInput(Map) throws SourceException } +abstract class IdCoordinateSource { + + Optional> getSourceFields() throws SourceException + + Optional getCoordinate(int) + + Collection getCoordinates(int[]) + + Optional getId(Point) + + Collection getAllCoordinates() + + List getNearestCoordinates(Point, int) + + List getClosestCoordinates(Point, int, ComparableQuantity) + + List calculateCoordinateDistances(Point, int, Collection) + + List findCornerPoints(Point, ComparableQuantity) + + List findCornerPoints(Point, Collection) +} + +class CsvIdCoordinateSource { + - Map idToCoordinate; + - Map coordinateToId; + - CsvDataSource dataSource; + - IdCoordinateFactory factory; + + CsvIdCoordinateSource(IdCoordinateFactory, CsvDataSource) throws SourceException + + int getCoordinateCount() +} + +class SqlIdCoordinateSource { + - SqlDataSource dataSource + - SqlIdCoordinateFactory factory + + SqlIdCoordinateSource(SqlIdCoordinateFactory, String, SqlDataSource) +} + class RawGridSource { - TypeSource typeSource - NodeInputFactory nodeInputFactory @@ -70,9 +109,10 @@ class ResultEntitySource { - SwitchResultFactory switchResultFactory - NodeResultFactory nodeResultFactory - ConnectorResultFactory connectorResultFactory + - CongestionResultFactory congestionResultFactory - FlexOptionsResultFactory flexOptionsResultFactory + ResultEntitySource(DataSource) - + ResultEntitySource(DataSource, String) + + ResultEntitySource(DataSource, DateTimeFormatter) + Set getNodeResults() throws SourceException + Set getSwitchResults() throws SourceException + Set getLineResults() throws SourceException @@ -92,12 +132,14 @@ class ResultEntitySource { + Set getCylindricalStorageResult() throws SourceException + Set getThermalHouseResults() throws SourceException + Set getEmResults() throws SourceException + + Set getCongestionResults() throws SourceException } class SystemParticipantSource{ - TypeSource typeSource - RawGridSource rawGridSource - ThermalSource thermalSource + - EnergyManagementSource energyManagementSource - BmInputFactory bmInputFactory - ChpInputFactory chpInputFactory - EvInputFactory evInputFactory @@ -108,7 +150,7 @@ class SystemParticipantSource{ - StorageInputFactory storageInputFactory - WecInputFactory wecInputFactory - EvcsInputFactory evcsInputFactory - + SystemParticipantSource(TypeSource, ThermalSource, RawGridSource, DataSource) + + SystemParticipantSource(TypeSource, ThermalSource, RawGridSource, EnergyManagementSource, DataSource) + SystemParticipants getSystemParticipants() throws SourceException + SystemParticipants getSystemParticipants(Map, Map) throws SourceException + Set getBmPlants() throws SourceException @@ -141,20 +183,65 @@ class ThermalSource { + ThermalSource(TypeSource, DataSource) + Map getThermalBuses() throws SourceException + Map getThermalBuses(Map) throws SourceException - + Set getThermalStorages() throws SourceException - + Set getThermalStorages(Map, Map) throws SourceException - + Set getThermalHouses() throws SourceException - + Set getThermalHouses(Map, Map) throws SourceException + + Map getThermalStorages() throws SourceException + + Map getThermalStorages(Map, Map) throws SourceException + + Map getThermalHouses() throws SourceException + + Map getThermalHouses(Map, Map) throws SourceException + Set getCylindricStorages() throws SourceException + Set getCylindricStorages(Map, Map) throws SourceException } +abstract class TimeSeriesMappingSource { + - TimeSeriesMappingFactory mappingFactory + + Map getMapping() throws SourceException + + Optional getTimeSeriesUuid(UUID) throws SourceException + + Stream> getMappingSourceData() throws SourceException + + Optional> getSourceFields() throws SourceException +} + +class CsvTimeSeriesMappingSource { + - CsvDataSource dataSource + + CsvTimeSeriesMappingSource(String, Path, FileNamingStrategy) +} + +class SqlTimeSeriesMappingSource { + - EntityPersistenceNamingStrategy entityPersistenceNamingStrategy + - SqlDataSource dataSource + + SqlTimeSeriesMappingSource(SqlConnector, String, EntityPersistenceNamingStrategy) +} + +abstract class TimeSeriesSource { + - Class valueClass + - TimeBasedSimpleValueFactory valueFactory + + TimeSeriesSource(Class, TimeBasedSimpleValueFactory) + + IndividualTimeSeries getTimeSeries() + + IndividualTimeSeries getTimeSeries(ClosedInterval) throws SourceException + + Optional getValue(ZonedDateTime) throws SourceException +} + +class CsvTimeSeriesSource { + - IndividualTimeSeries timeSeries + - CsvDataSource dataSource + - Path filePath + + {static} CsvTimeSeriesSource getSource(String, Path, FileNamingStrategy, CsvIndividualTimeSeriesMetaInformation) + + CsvTimeSeriesSource(String, Path, FileNamingStrategy, UUID, Path, Class, TimeBasedSimpleValueFactory) +} + +class SqlTimeSeriesSource { + - SqlDataSource dataSource + - UUID timeSeriesUuid + + SqlTimeSeriesSource(SqlDataSource, UUID, Class, TimeBasedSimpleValueFactory) + + SqlTimeSeriesSource(SqlConnector, String, DatabaseNamingStrategy, UUID, Class, TimeBasedSimpleValueFactory) + + SqlTimeSeriesSource createSource(SqlConnector, String, DatabaseNamingStrategy, IndividualTimeSeriesMetaInformation, DateTimeFormatter) throws SourceException +} + class TypeSource { - OperatorInputFactory operatorInputFactory - Transformer2WTypeInputFactory transformer2WTypeInputFactory - LineTypeInputFactory lineTypeInputFactory - Transformer3WTypeInputFactory transformer3WTypeInputFactory - SystemParticipantTypeInputFactory systemParticipantTypeInputFactory + - DataSource dataSource + TypeSource(DataSource) + Map getTransformer2WTypes() throws SourceException + Map getTransformer3WTypes() throws SourceException @@ -167,4 +254,38 @@ class TypeSource { + Map getWecTypes() throws SourceException + Map getEvTypes() throws SourceException } + +abstract class WeatherSource { + - TimeBasedWeatherValueFactory weatherFactory + - IdCoordinateSource idCoordinateSource + + WeatherSource(IdCoordinateSource, TimeBasedWeatherValueFactory) + + Optional> getSourceFields() throws SourceException + + Map> getWeather(ClosedInterval) throws SourceException + + Map> getWeather(ClosedInterval, Collection) throws SourceException + + Optional> getWeather(ZonedDateTime, Point) throws SourceException +} + +class CouchbaseWeatherSource { + - CouchbaseConnector connector + + CouchbaseWeatherSource(CouchbaseConnector, IdCoordinateSource, String, TimeBasedWeatherValueFactory, String) + + CouchbaseWeatherSource(CouchbaseConnector, IdCoordinateSource, String, String, TimeBasedWeatherValueFactory, String) +} + +class CsvWeatherSource { + - CsvDataSource dataSource + - Map> coordinateToTimeSeries + + CsvWeatherSource(String, Path, FileNamingStrategy, IdCoordinateSource, TimeBasedWeatherValueFactory) throws SourceException +} + +class InfluxDbWeatherSource { + - InfluxDbConnector connector + + InfluxDbWeatherSource(InfluxDbConnector, IdCoordinateSource, TimeBasedWeatherValueFactory) + + IndividualTimeSeries getWeather(ClosedInterval, Point) +} + +class SqlWeatherSource { + - SqlDataSource dataSource + + SqlWeatherSource(SqlConnector, IdCoordinateSource, String, String, TimeBasedWeatherValueFactory) +} + @enduml \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7f93135c4..d64cd4917 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a80b22ce5..a4413138c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew.bat b/gradlew.bat index 93e3f59f1..25da30dbd 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail 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 a5797cf9b..b9a104137 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 @@ -27,6 +27,7 @@ public abstract class AssetInputEntityFactory... allowedClasses) { super(allowedClasses); } diff --git a/src/main/java/edu/ie3/datamodel/io/factory/input/ConnectorInputEntityFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/input/ConnectorInputEntityFactory.java index cc29c7e5e..8fc59cbec 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/input/ConnectorInputEntityFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/input/ConnectorInputEntityFactory.java @@ -20,7 +20,7 @@ * @param Type of data class that is required for entity creation * @since 19.02.20 */ -abstract class ConnectorInputEntityFactory< +public abstract class ConnectorInputEntityFactory< T extends ConnectorInput, D extends ConnectorInputEntityData> extends AssetInputEntityFactory { @@ -31,6 +31,7 @@ abstract class ConnectorInputEntityFactory< */ protected static final String PARALLEL_DEVICES = "parallelDevices"; + @SafeVarargs protected ConnectorInputEntityFactory(Class... allowedClasses) { super(allowedClasses); } diff --git a/src/main/java/edu/ie3/datamodel/io/factory/input/Transformer3WInputEntityData.java b/src/main/java/edu/ie3/datamodel/io/factory/input/Transformer3WInputEntityData.java index e53678f1a..deed94e8e 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/input/Transformer3WInputEntityData.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/input/Transformer3WInputEntityData.java @@ -39,6 +39,21 @@ public Transformer3WInputEntityData( this.nodeC = nodeC; } + /** + * Creates a new Transformer3WInputEntityData object based on a given {@link + * ConnectorInputEntityData} object, a given third node as well as a given {@link + * Transformer3WTypeInput}. + * + * @param entityData The TypedConnectorInputEntityData object to enhance + * @param nodeC The third node + * @param type of the transformer + */ + public Transformer3WInputEntityData( + ConnectorInputEntityData entityData, NodeInput nodeC, Transformer3WTypeInput type) { + super(entityData, type); + this.nodeC = nodeC; + } + /** * Creates a new Transformer3WInputEntityData object based on a given {@link * TypedConnectorInputEntityData} object and given third node diff --git a/src/main/java/edu/ie3/datamodel/io/factory/result/ResultEntityFactory.java b/src/main/java/edu/ie3/datamodel/io/factory/result/ResultEntityFactory.java index 3f3346aae..f4c239795 100644 --- a/src/main/java/edu/ie3/datamodel/io/factory/result/ResultEntityFactory.java +++ b/src/main/java/edu/ie3/datamodel/io/factory/result/ResultEntityFactory.java @@ -18,17 +18,20 @@ * @version 0.1 * @since 11.02.20 */ -abstract class ResultEntityFactory extends EntityFactory { +public abstract class ResultEntityFactory + extends EntityFactory { protected static final String TIME = "time"; protected final TimeUtil timeUtil; + @SafeVarargs protected ResultEntityFactory(Class... allowedClasses) { super(allowedClasses); timeUtil = TimeUtil.withDefaults; } + @SafeVarargs protected ResultEntityFactory( DateTimeFormatter dateTimeFormatter, Class... allowedClasses) { super(allowedClasses); diff --git a/src/main/java/edu/ie3/datamodel/io/source/AssetEntitySource.java b/src/main/java/edu/ie3/datamodel/io/source/AssetEntitySource.java new file mode 100644 index 000000000..1757fdacd --- /dev/null +++ b/src/main/java/edu/ie3/datamodel/io/source/AssetEntitySource.java @@ -0,0 +1,111 @@ +/* + * © 2023. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation +*/ +package edu.ie3.datamodel.io.source; + +import static edu.ie3.datamodel.models.input.OperatorInput.NO_OPERATOR_ASSIGNED; + +import edu.ie3.datamodel.exceptions.SourceException; +import edu.ie3.datamodel.io.factory.EntityData; +import edu.ie3.datamodel.io.factory.input.*; +import edu.ie3.datamodel.models.input.AssetTypeInput; +import edu.ie3.datamodel.models.input.NodeInput; +import edu.ie3.datamodel.models.input.OperatorInput; +import edu.ie3.datamodel.models.input.connector.ConnectorInput; +import java.util.Map; +import java.util.UUID; +import java.util.function.BiFunction; +import java.util.stream.Stream; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** Class that provides all functionalities to build asset entities */ +public abstract class AssetEntitySource extends EntitySource { + + protected static final Logger log = LoggerFactory.getLogger(AssetEntitySource.class); + + protected final DataSource dataSource; + + // field names + protected static final String OPERATOR = "operator"; + protected static final String NODE = "node"; + protected static final String NODE_A = "nodeA"; + protected static final String NODE_B = "nodeB"; + protected static final String TYPE = "type"; + + // enriching functions + protected static final EnrichFunction + assetEnricher = + (data, operators) -> + enrichWithDefault( + OPERATOR, operators, NO_OPERATOR_ASSIGNED, AssetInputEntityData::new) + .apply(data); + + protected static final BiEnrichFunction< + EntityData, OperatorInput, NodeInput, NodeAssetInputEntityData> + nodeAssetEnricher = + (data, operators, nodes) -> + assetEnricher + .andThen(enrich(NODE, nodes, NodeAssetInputEntityData::new)) + .apply(data, operators); + + protected static final BiEnrichFunction< + EntityData, OperatorInput, NodeInput, ConnectorInputEntityData> + connectorEnricher = + (data, operators, nodes) -> + assetEnricher + .andThen(biEnrich(NODE_A, nodes, NODE_B, nodes, ConnectorInputEntityData::new)) + .apply(data, operators); + + protected AssetEntitySource(DataSource dataSource) { + this.dataSource = dataSource; + } + + // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + + /** + * Method to build typed connector entities. + * + * @param entityClass class of the entity + * @param dataSource source for the data + * @param factory to build the entity + * @param operators map: uuid to {@link OperatorInput} + * @param nodes map: uuid to {@link NodeInput} + * @param types map: uuid to {@link AssetTypeInput} + * @return a stream of {@link ConnectorInput}s + * @param type of connector input + * @param type of asset types + * @throws SourceException if an error happens during reading + */ + protected static + Stream getTypedConnectorEntities( + Class entityClass, + DataSource dataSource, + ConnectorInputEntityFactory> factory, + Map operators, + Map nodes, + Map types) + throws SourceException { + return getEntities( + entityClass, + dataSource, + factory, + data -> connectorEnricher.andThen(enrichConnector(types)).apply(data, operators, nodes)); + } + + /** + * Builds a function for enriching {@link ConnectorInputEntityData} with types. + * + * @param types all known types + * @return a typed entity data + * @param type of types + */ + private static + WrappedFunction> enrichConnector(Map types) { + BiFunction> typeEnricher = + TypedConnectorInputEntityData::new; + return entityData -> enrich(TYPE, types, typeEnricher).apply(entityData); + } +} 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 acca23634..8a5cce317 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/EnergyManagementSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/EnergyManagementSource.java @@ -21,7 +21,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -public class EnergyManagementSource extends EntitySource { +public class EnergyManagementSource extends AssetEntitySource { private final TypeSource typeSource; @@ -34,7 +34,7 @@ public EnergyManagementSource(TypeSource typeSource, DataSource dataSource) { @Override public void validate() throws ValidationException { - validate(EmInput.class, emInputFactory).getOrThrow(); + validate(EmInput.class, dataSource, emInputFactory).getOrThrow(); } /** @@ -68,14 +68,15 @@ public Map getEmUnits() throws SourceException { * @return a map of UUID to {@link EmInput} entities */ public Map getEmUnits(Map operators) throws SourceException { - return createEmInputs(buildAssetInputEntityData(EmInput.class, operators)); + return createEmInputs( + buildEntityData(EmInput.class, dataSource, data -> assetEnricher.apply(data, operators))); } /** * Since each EM can itself be controlled by another EM, it does not suffice to link {@link - * EmInput}s via {@link EntitySource#optionallyEnrichEntityData} as we do for system participants - * in {@link SystemParticipantSource}. Instead, we use a recursive approach, starting with EMs at - * root level (which are not EM-controlled themselves). + * EmInput}s via {@link EntitySource#enrichFunction} as we do for system participants in {@link + * SystemParticipantSource}. Instead, we use a recursive approach, starting with EMs at root level + * (which are not EM-controlled themselves). * * @param assetEntityDataStream the data stream of {@link AssetInputEntityData} {@link Try} * objects @@ -103,15 +104,16 @@ private static Map createEmInputs( // at the start, this is only root ems Map allEms = - unpackMap( - rootEmsEntityData.stream() - .parallel() - .map( - entityDataTry -> - entityDataTry.map( - entityData -> new EmAssetInputEntityData(entityData, null))) - .map(emInputFactory::get), - EmInput.class); + unpack( + rootEmsEntityData.stream() + .parallel() + .map( + entityDataTry -> + entityDataTry.map( + entityData -> new EmAssetInputEntityData(entityData, null))) + .map(emInputFactory::get), + EmInput.class) + .collect(toMap()); if (!others.isEmpty()) { // there's more EM levels beyond root level. Build them recursively @@ -175,16 +177,17 @@ private static Map createHierarchicalEmInputs( } else { // New EMs can be built at this level Map newEms = - unpackMap( - toBeBuiltAtThisLevel.stream() - .map( - data -> { - // exists because we checked above - EmInput parentEm = lastLevelEms.get(data.parentEm); - return emInputFactory.get( - new EmAssetInputEntityData(data.entityData, parentEm)); - }), - EmInput.class); + unpack( + toBeBuiltAtThisLevel.stream() + .map( + data -> { + // exists because we checked above + EmInput parentEm = lastLevelEms.get(data.parentEm); + return emInputFactory.get( + new EmAssetInputEntityData(data.entityData, parentEm)); + }), + EmInput.class) + .collect(toMap()); if (!toBeBuiltAtNextLevel.isEmpty()) { // If there's more EMs left to build, the new EMs have to function as parents there 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 ff5e5a6b3..95dd1e0dc 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/EntitySource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/EntitySource.java @@ -1,5 +1,5 @@ /* - * © 2023. TU Dortmund University, + * © 2024. TU Dortmund University, * Institute of Energy Systems, Energy Efficiency and Energy Economics, * Research group Distribution grid planning and operation */ @@ -11,58 +11,74 @@ import edu.ie3.datamodel.exceptions.ValidationException; import edu.ie3.datamodel.io.factory.EntityData; import edu.ie3.datamodel.io.factory.EntityFactory; -import edu.ie3.datamodel.io.factory.input.AssetInputEntityData; -import edu.ie3.datamodel.io.factory.input.NodeAssetInputEntityData; import edu.ie3.datamodel.models.Entity; import edu.ie3.datamodel.models.UniqueEntity; -import edu.ie3.datamodel.models.input.AssetInput; -import edu.ie3.datamodel.models.input.NodeInput; -import edu.ie3.datamodel.models.input.OperatorInput; +import edu.ie3.datamodel.utils.QuadFunction; import edu.ie3.datamodel.utils.TriFunction; import edu.ie3.datamodel.utils.Try; import edu.ie3.datamodel.utils.Try.Failure; -import edu.ie3.datamodel.utils.Try.Success; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; +import java.util.*; import java.util.function.BiFunction; import java.util.function.Function; +import java.util.stream.Collector; import java.util.stream.Collectors; import java.util.stream.Stream; +import org.apache.commons.lang3.tuple.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -/** Class that provides all functionalities to build entities */ +/** + * Base class for all entity sources. This class provides some functionalities that are common among + * sources. + */ public abstract class EntitySource { - protected static final Logger log = LoggerFactory.getLogger(EntitySource.class); - // field names - protected static final String OPERATOR = "operator"; - protected static final String NODE = "node"; - protected static final String TYPE = "type"; + // convenience collectors - protected final DataSource dataSource; + protected static Collector> toMap() { + return Collectors.toMap(UniqueEntity::getUuid, Function.identity()); + } - protected EntitySource(DataSource dataSource) { - this.dataSource = dataSource; + protected static Collector> toSet() { + return Collectors.toSet(); } - // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + protected EntitySource() {} + /** + * Method for validating a given {@link EntitySource}. + * + * @throws ValidationException - if an error occurred while validating the source + */ public abstract void validate() throws ValidationException; /** * Method for validating a single source. * * @param entityClass class to be validated + * @param dataSource source for the fields * @param validator used to validate * @param type of the class */ - protected final Try validate( - Class entityClass, SourceValidator validator) { - return Try.of(() -> dataSource.getSourceFields(entityClass), SourceException.class) + protected static Try validate( + Class entityClass, DataSource dataSource, SourceValidator validator) { + return validate(entityClass, () -> dataSource.getSourceFields(entityClass), validator); + } + + /** + * Method for validating a single source. + * + * @param entityClass class to be validated + * @param sourceFields supplier for source fields + * @param validator used to validate + * @param type of the class + */ + protected static Try validate( + Class entityClass, + Try.TrySupplier>, SourceException> sourceFields, + SourceValidator validator) { + return Try.of(sourceFields, SourceException.class) .transformF( se -> (ValidationException) @@ -79,342 +95,321 @@ protected final Try validate( } /** - * Enhances given entity data with an entity from the given entity map. The linked entity is - * chosen by taking into account the UUID found by retrieving the field with given fieldName from - * entityData. + * Universal method to get a map: uuid to {@link UniqueEntity}. * - * @param entityData The entity data to be enhanced, which also provides a link to another entity - * via UUID - * @param fieldName The field name of the field that provides the UUID of the linked entity - * @param linkedEntities A map of UUID to entities, of which one should be linked to given entity - * data - * @param createEntityData The function that creates the resulting entity data given entityData - * and the linked entity - * @param Type of input entity data - * @param Type of the linked entity - * @param Type of resulting entity data that combines the given entityData and linked entity - * @return {@link Try} to enhanced data + * @param entityClass subclass of {@link UniqueEntity} + * @param dataSource source for the data + * @param factory to build the entity + * @return a map: uuid to {@link UniqueEntity} + * @param type of entity + * @throws SourceException - if an error happen during reading */ - protected static - Try enrichEntityData( - E entityData, - String fieldName, - Map linkedEntities, - BiFunction createEntityData) { - return getLinkedEntity(entityData, fieldName, linkedEntities) - .map( - linkedEntity -> { - Map fieldsToAttributes = entityData.getFieldsToValues(); - - // remove fields that are passed as objects to constructor - fieldsToAttributes.keySet().remove(fieldName); - - // build resulting entity data - return createEntityData.apply(entityData, linkedEntity); - }); + @SuppressWarnings("unchecked") + protected static Map getEntities( + Class entityClass, + DataSource dataSource, + EntityFactory factory) + throws SourceException { + return unpack( + buildEntityData(entityClass, dataSource) + .map(data -> (Try) factory.get(data)), + entityClass) + .collect(toMap()); } /** - * Enhances given entity data with two entities from the given entity maps. The linked entities - * are chosen by taking into account the UUIDs found by retrieving the fields with given - * fieldName1 and fieldName2 from entityData. + * Universal method to get a {@link Entity} stream. * - * @param entityData The entity data to be enhanced, which also provides links to two other - * entities via UUID - * @param fieldName1 The field name of the field that provides the UUID of the first linked entity - * @param linkedEntities1 The first map of UUID to entities, of which one should be linked to - * given entity data - * @param fieldName2 The field name of the field that provides the UUID of the second linked - * entity - * @param linkedEntities2 The second map of UUID to entities, of which one should be linked to - * given entity data - * @param createEntityData The function that creates the resulting entity data given entityData - * and the linked entities - * @param Type of input entity data - * @param Type of the first linked entity - * @param Type of the second linked entity - * @param Type of resulting entity data that combines the given entityData and two linked - * entities - * @return {@link Try} to enhanced data + * @param entityClass class of the entity + * @param dataSource source for the entity + * @param factory to build the entity + * @param enrichFunction function to enrich the given entity data + * @return a set of {@link Entity}s + * @param type of entity + * @param type of entity data + * @throws SourceException - if an error happen during reading */ - protected static < - E extends EntityData, T1 extends UniqueEntity, T2 extends UniqueEntity, R extends E> - Try enrichEntityData( - E entityData, - String fieldName1, - Map linkedEntities1, - String fieldName2, - Map linkedEntities2, - TriFunction createEntityData) { - return getLinkedEntity(entityData, fieldName1, linkedEntities1) - .flatMap( - linkedEntity1 -> - getLinkedEntity(entityData, fieldName2, linkedEntities2) - .map( - linkedEntity2 -> { - Map fieldsToAttributes = entityData.getFieldsToValues(); - - // remove fields that are passed as objects to constructor - fieldsToAttributes.keySet().remove(fieldName1); - fieldsToAttributes.keySet().remove(fieldName2); - - // build resulting entity data - return createEntityData.apply(entityData, linkedEntity1, linkedEntity2); - })); + protected static Stream getEntities( + Class entityClass, + DataSource dataSource, + EntityFactory factory, + WrappedFunction enrichFunction) + throws SourceException { + return unpack( + buildEntityData(entityClass, dataSource, enrichFunction).map(factory::get), entityClass); } + // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + /** - * Checks if the linked entity can be found in the provided map of entities. The linked entities - * are chosen by taking into account the UUIDs found by retrieving the fields with given - * fieldName1 and fieldName2 from entityData. + * Returns a stream of {@link EntityData} that can be used to build instances of several subtypes + * of {@link Entity} by a corresponding {@link EntityFactory} that consumes this data. * - * @param entityData The entity data of the entity that provides a link to another entity via UUID - * @param fieldName The field name of the field that provides the UUID of the linked entity - * @param linkedEntities A map of UUID to entities, of which one should be linked to given entity - * data - * @param the type of the resulting linked entity instance - * @return a {@link Success} containing the entity or a {@link Failure} if the entity cannot be - * found + * @param entityClass the entity class that should be build + * @param dataSource source for the data + * @return a stream of the entity data wrapped in a {@link Try} */ - protected static Try getLinkedEntity( - EntityData entityData, String fieldName, Map linkedEntities) { + 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))); + } - return Try.of(() -> entityData.getUUID(fieldName), FactoryException.class) - .transformF( - exception -> - new SourceException( - "Extracting UUID field " - + fieldName - + " from entity data " - + entityData.toString() - + " failed.", - exception)) - .flatMap( - entityUuid -> - getEntity(entityUuid, linkedEntities) - .transformF( - exception -> - new SourceException( - "Linked " - + fieldName - + " with UUID " - + entityUuid - + " was not found for entity " - + entityData, - exception))); + /** + * Returns a stream of {@link EntityData} that can be used to build instances of several subtypes + * of {@link Entity} by a corresponding {@link EntityFactory} that consumes this data. + * + * @param entityClass class of the entity + * @param dataSource source for the data + * @param converter to convert {@link EntityData} to {@link E} + * @return an entity data + * @param type of entity data + */ + protected static Stream> buildEntityData( + Class entityClass, + DataSource dataSource, + WrappedFunction converter) { + return buildEntityData(entityClass, dataSource).map(converter); } + // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + /** - * Enhances given entity data with an entity from the given entity map or the default value. The - * linked entity is possibly chosen by taking into account the UUID found by retrieving the field - * with given fieldName from entityData. If no entity is linked, the default value is used. + * Method to build an enrich function. * - * @param entityData The entity data to be enhanced, which also might provide a link to another - * entity via UUID - * @param fieldName The field name of the field that might provide the UUID of the linked entity - * @param linkedEntities A map of UUID to entities, of which one should be linked to given entity - * data - * @param defaultEntity The default linked entity to use, if no actual linked entity could be - * found - * @param createEntityData The function that creates the resulting entity data given entityData - * and the linked entity (either retrieved from the map or the standard entity) - * @param Type of input entity data - * @param Type of the linked entity - * @param Type of resulting entity data that combines the given entityData and linked entity - * @return {@link Try} to enhanced data + * @param fieldName name of the field + * @param entities map: uuid to {@link Entity} + * @param defaultEntity entity that should be used if no other entity was extracted + * @param buildingFcn to build the returned {@link EntityData} + * @return an enrich function + * @param type of entity data + * @param type of entity + * @param type of returned entity data */ - protected static - Try optionallyEnrichEntityData( - E entityData, + protected static + WrappedFunction enrichWithDefault( String fieldName, - Map linkedEntities, + Map entities, T defaultEntity, - BiFunction createEntityData) { - return entityData - .getFieldOptional(fieldName) - .filter(s -> !s.isBlank()) - .map( - // Entity data includes a non-empty UUID String for the desired entity - uuidString -> - Try.of(() -> UUID.fromString(uuidString), IllegalArgumentException.class) - .transformF( - iae -> - // Parsing error still results in a failure, ... - new SourceException( - String.format( - "Exception while trying to parse UUID of field \"%s\" with value \"%s\"", - fieldName, uuidString), - iae)) - .flatMap( - entityUuid -> - getEntity(entityUuid, linkedEntities) - // ... as well as a provided entity UUID that does not match any - // given data - .transformF( - exception -> - new SourceException( - "Linked " - + fieldName - + " with UUID " - + entityUuid - + " was not found for entity " - + entityData, - exception)))) - .orElseGet( - () -> { - // No UUID was given (column does not exist, or field is empty). - // This is totally fine - we successfully return the default value - log.debug( - "Input source for class {} is missing the '{}' field. " - + "Default value '{}' is used.", - entityData.getTargetClass().getSimpleName(), - fieldName, - defaultEntity); - return new Try.Success<>(defaultEntity); - }) - .map( - linkedEntity -> { - Map fieldsToAttributes = entityData.getFieldsToValues(); - - // remove fields that are passed as objects to constructor - fieldsToAttributes.keySet().remove(fieldName); - - // build resulting entity data - return createEntityData.apply(entityData, linkedEntity); - }); + BiFunction buildingFcn) { + return entityData -> + entityData + .zip( + extractFunction(entityData, fieldName, entities) + .orElse(() -> Try.Success.of(defaultEntity))) + .map(enrichFunction(List.of(fieldName), buildingFcn)); } - private static Try getEntity(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)) - // ... or find no matching entity, returning a failure. - .orElse( - new Try.Failure<>( - new SourceException("Entity with uuid " + uuid + " was not provided."))); + /** + * Method to build an enrich function. + * + * @param fieldName name of the field + * @param entities map: uuid to {@link Entity} + * @param buildingFcn to build the returned {@link EntityData} + * @return an enrich function + * @param type of entity data + * @param type of entity + * @param type of returned entity data + */ + protected static WrappedFunction enrich( + String fieldName, Map entities, BiFunction buildingFcn) { + return entityData -> + entityData + .zip(extractFunction(entityData, fieldName, entities)) + .map(enrichFunction(List.of(fieldName), buildingFcn)); } - // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - /** - * Returns a stream of {@link Try} entities that can be built by using {@link - * NodeAssetInputEntityData} and their corresponding factory. + * Method to build an enrich function. * - * @param entityClass the entity class that should be build - * @param nodes a map of UUID to {@link NodeInput} entities that should be used to build the - * entities - * @param operators a map of UUID to {@link OperatorInput} entities should be used to build the - * entities - * @return stream of tries of the entities that has been built by the factory + * @param fieldName1 name of the first field + * @param entities1 map: uuid to {@link Entity} + * @param fieldName2 name of the second field + * @param entities2 map: uuid to {@link Entity} + * @param buildingFcn to build the returned {@link EntityData} + * @return an enrich function + * @param type of entity data + * @param type of the first entity + * @param type of the second entity + * @param type of returned entity data */ - protected Stream> buildNodeAssetEntityData( - Class entityClass, - Map operators, - Map nodes) { - return nodeAssetInputEntityDataStream(buildAssetInputEntityData(entityClass, operators), nodes); + protected static < + E extends EntityData, T1 extends Entity, T2 extends Entity, R extends EntityData> + WrappedFunction biEnrich( + String fieldName1, + Map entities1, + String fieldName2, + Map entities2, + TriFunction buildingFcn) { + // adapting the provided function + BiFunction, R> adaptedBuildingFcn = + (data, pair) -> buildingFcn.apply(data, pair.getKey(), pair.getValue()); + + // extractor to get the needed entities + WrappedFunction> pairExtractor = + data -> + extractFunction(data, fieldName1, entities1) + .zip(extractFunction(data, fieldName2, entities2)); + + return entityData -> + entityData + .zip(pairExtractor) + .map(enrichFunction(List.of(fieldName1, fieldName2), adaptedBuildingFcn)); } /** - * Returns a stream of tries of {@link NodeAssetInputEntityData} that can be used to build - * instances of several subtypes of {@link UniqueEntity} by a corresponding {@link EntityFactory} - * that consumes this data. + * Method to build a function to create an {@link EntityData}. * - * @param assetInputEntityDataStream a stream consisting of {@link AssetInputEntityData} that is - * enriched with {@link NodeInput} data - * @param nodes a map of UUID to {@link NodeInput} entities that should be used to build the data - * @return stream of the entity data wrapped in a {@link Try} + * @param fieldNames list with field names + * @param buildingFcn to build the returned {@link EntityData} + * @return an entity data + * @param type of given entity data + * @param type of entities + * @param type of returned entity data */ - protected static Stream> - nodeAssetInputEntityDataStream( - Stream> assetInputEntityDataStream, - Map nodes) { - return assetInputEntityDataStream - .parallel() - .map( - assetInputEntityDataTry -> - assetInputEntityDataTry.flatMap( - assetInputEntityData -> - enrichEntityData( - assetInputEntityData, NODE, nodes, NodeAssetInputEntityData::new))); + protected static + Function, R> enrichFunction( + List fieldNames, BiFunction buildingFcn) { + return pair -> { + E data = pair.getKey(); + T entities = pair.getValue(); + + Map fieldsToAttributes = data.getFieldsToValues(); + + // remove fields that are passed as objects to constructor + fieldNames.forEach(fieldsToAttributes.keySet()::remove); + + return buildingFcn.apply(data, entities); + }; } + // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + /** - * Returns a stream of optional {@link AssetInputEntityData} that can be used to build instances - * of several subtypes of {@link UniqueEntity} by a corresponding {@link EntityFactory} that - * consumes this data. + * Method to unpack a stream of tries. * - * @param entityClass the entity class that should be build - * @param operators a map of UUID to {@link OperatorInput} entities that should be used to build - * the data - * @return stream of the entity data wrapped in a {@link Try} + * @param inputStream given stream + * @param clazz class of the entity + * @return a stream of entities + * @param type of entity + * @param type of exception + * @throws SourceException - if an error occurred during reading */ - protected Stream> buildAssetInputEntityData( - Class entityClass, Map operators) { - return assetInputEntityDataStream(buildEntityData(entityClass), operators); + protected static Stream unpack( + Stream> inputStream, Class clazz) throws SourceException { + return Try.scanStream(inputStream, clazz.getSimpleName()) + .transformF(SourceException::new) + .getOrThrow(); } /** - * Returns a stream of tries of {@link AssetInputEntityData} that can be used to build instances - * of several subtypes of {@link UniqueEntity} by a corresponding {@link EntityFactory} that - * consumes this data. + * Method to extract an entity. * - * @param entityDataStream a stream consisting of {@link EntityData} that is enriched with {@link - * OperatorInput} data - * @param operators map of UUID to {@link OperatorInput} entities that should be used to build the - * data - * @return stream of the entity data wrapped in a {@link Try} + * @param entityData data containing complex entities + * @param fieldName name of the field + * @param entities map: uuid to {@link Entity} + * @return an enrichment + * @param type of entity data + * @param type of entity */ - protected static Stream> assetInputEntityDataStream( - Stream> entityDataStream, - Map operators) { - return entityDataStream - .parallel() - .map( - entityDataTry -> - entityDataTry.flatMap( - entityData -> - optionallyEnrichEntityData( - entityData, - OPERATOR, - operators, - OperatorInput.NO_OPERATOR_ASSIGNED, - AssetInputEntityData::new))); + protected static Try extractFunction( + Try entityData, String fieldName, Map entities) { + return entityData.flatMap( + data -> + Try.of(() -> data.getUUID(fieldName), FactoryException.class) + .transformF( + exception -> + new SourceException( + "Extracting UUID field " + + fieldName + + " from entity data " + + entityData + + " failed.", + exception)) + .flatMap(entityUuid -> extractFunction(entityUuid, entities))); } /** - * Returns a stream of optional {@link EntityData} that can be used to build instances of several - * subtypes of {@link Entity} by a corresponding {@link EntityFactory} that consumes this data. + * Method to extract an {@link Entity} from a given map. * - * @param entityClass the entity class that should be build - * @return stream of the entity data wrapped in a {@link Try} + * @param uuid of the entity + * @param entityMap map: uuid to entity + * @return a try of the {@link Entity} + * @param type of entity */ - protected Stream> buildEntityData( - Class entityClass) { - - return Try.of(() -> dataSource.getSourceData(entityClass), SourceException.class) - .convert( - data -> - data.map( - fieldsToAttributes -> - new Success<>(new EntityData(fieldsToAttributes, entityClass))), - exception -> Stream.of(Failure.of(exception))); + 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)) + // ... or find no matching entity, returning a failure. + .orElse( + new Failure<>(new SourceException("Entity with uuid " + uuid + " was not provided."))); } - protected static Map unpackMap( - Stream> inputStream, Class entityClass) throws SourceException { - return unpack(inputStream, entityClass) - .collect(Collectors.toMap(UniqueEntity::getUuid, Function.identity())); - } + // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= - protected static Set unpackSet( - Stream> inputStream, Class entityClass) throws SourceException { - return unpack(inputStream, entityClass).collect(Collectors.toSet()); - } + // functional interfaces - protected static Stream unpack( - Stream> inputStream, Class clazz) throws SourceException { - return Try.scanStream(inputStream, clazz.getSimpleName()) - .transformF(SourceException::new) - .getOrThrow(); - } + /** + * Wraps the function arguments with a try. + * + * @param type of first argument + * @param type of second argument + */ + @FunctionalInterface + protected interface WrappedFunction + extends Function, Try> {} + + /** + * Function for enriching an {@link EntityData} with an {@link Entity}. + * + * @param type of entity data + * @param type of entity + * @param type of returned entity data + */ + @FunctionalInterface + protected interface EnrichFunction + extends BiFunction, Map, Try> {} + + /** + * Function for enriching an {@link EntityData} with two {@link Entity}. + * + * @param type of entity data + * @param type of first entity + * @param type of second entity + * @param type of returned entity data + */ + @FunctionalInterface + protected interface BiEnrichFunction< + E extends EntityData, T1 extends Entity, T2 extends Entity, R extends EntityData> + extends TriFunction< + Try, Map, Map, Try> {} + + /** + * Function for enriching an {@link EntityData} with three {@link Entity}. + * + * @param type of entity data + * @param type of first entity + * @param type of second entity + * @param type of third entity + * @param type of returned entity data + */ + @FunctionalInterface + protected interface TriEnrichFunction< + E extends EntityData, + T1 extends Entity, + T2 extends Entity, + T3 extends Entity, + R extends EntityData> + extends QuadFunction< + Try, + Map, + Map, + Map, + Try> {} } 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 e8a0cf7b0..339f3f638 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/GraphicSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/GraphicSource.java @@ -22,8 +22,10 @@ import edu.ie3.datamodel.models.input.graphics.LineGraphicInput; import edu.ie3.datamodel.models.input.graphics.NodeGraphicInput; import edu.ie3.datamodel.utils.Try; -import edu.ie3.datamodel.utils.Try.*; -import java.util.*; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; import java.util.stream.Stream; /** @@ -33,7 +35,7 @@ * @version 0.1 * @since 08.04.20 */ -public class GraphicSource extends EntitySource { +public class GraphicSource extends AssetEntitySource { // general fields private final TypeSource typeSource; private final RawGridSource rawGridSource; @@ -55,8 +57,8 @@ public GraphicSource(TypeSource typeSource, RawGridSource rawGridSource, DataSou public void validate() throws ValidationException { Try.scanStream( Stream.of( - validate(NodeGraphicInput.class, nodeGraphicInputFactory), - validate(LineGraphicInput.class, lineGraphicInputFactory)), + validate(NodeGraphicInput.class, dataSource, nodeGraphicInputFactory), + validate(LineGraphicInput.class, dataSource, lineGraphicInputFactory)), "Validation") .transformF(FailedValidationException::new) .getOrThrow(); @@ -97,7 +99,7 @@ public GraphicElements getGraphicElements(Map nodes, Map getNodeGraphicInput() throws SourceException { public Set getNodeGraphicInput(Map nodes) throws SourceException { - return unpackSet( - buildNodeGraphicEntityData(nodes).map(nodeGraphicInputFactory::get), - NodeGraphicInput.class); + return getEntities( + NodeGraphicInput.class, + dataSource, + nodeGraphicInputFactory, + enrich(NODE, nodes, NodeGraphicInputEntityData::new)) + .collect(toSet()); } /** @@ -137,63 +142,11 @@ public Set getLineGraphicInput() throws SourceException { public Set getLineGraphicInput(Map lines) throws SourceException { - return unpackSet( - buildLineGraphicEntityData(lines).map(lineGraphicInputFactory::get), - LineGraphicInput.class); - } - - // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - // build EntityData - - /** - * Builds a stream of {@link NodeGraphicInputEntityData} instances that can be consumed by a - * {@link NodeGraphicInputFactory} to build instances of {@link NodeGraphicInput} entities. This - * method depends on corresponding instances of {@link NodeInput} entities that are represented by - * a corresponding {@link NodeGraphicInput} entity. The determination of matching {@link - * NodeInput} and {@link NodeGraphicInput} entities is carried out by the UUID of the {@link - * NodeInput} entity. Hence it is crucial to only pass over collections that are pre-checked for - * the uniqueness of the UUIDs of the nodes they contain. No further sanity checks are included in - * this method. If no UUID of a {@link NodeInput} entity can be found for a {@link - * NodeGraphicInputEntityData} instance, a {@link Failure} is included in the stream and warning - * is logged. - * - * @param nodes a map of UUID to object- and uuid-unique {@link NodeInput} entities - * @return a stream of tries of {@link NodeGraphicInput} entities - */ - protected Stream> buildNodeGraphicEntityData( - Map nodes) { - return buildEntityData(NodeGraphicInput.class) - .map( - entityDataTry -> - entityDataTry.flatMap( - entityData -> - enrichEntityData( - entityData, NODE, nodes, NodeGraphicInputEntityData::new))); - } - - /** - * Builds a stream of {@link LineGraphicInputEntityData} instances that can be consumed by a - * {@link LineGraphicInputFactory} to build instances of {@link LineGraphicInput} entities. This - * method depends on corresponding instances of {@link LineInput} entities that are represented by - * a corresponding {@link LineGraphicInput} entity. The determination of matching {@link - * LineInput} and {@link LineGraphicInput} entities is carried out by the UUID of the {@link - * LineInput} entity. Hence it is crucial to only pass over collections that are pre-checked for - * the uniqueness of the UUIDs of the nodes they contain. No further sanity checks are included in - * this method. If no UUID of a {@link LineInput} entity can be found for a {@link - * LineGraphicInputEntityData} instance, a {@link Failure} is included in the stream and warning - * is logged. - * - * @param lines a map of UUID to object- and uuid-unique {@link LineInput} entities - * @return a stream of tries of {@link LineGraphicInput} entities - */ - protected Stream> buildLineGraphicEntityData( - Map lines) { - return buildEntityData(LineGraphicInput.class) - .map( - entityDataTry -> - entityDataTry.flatMap( - entityData -> - enrichEntityData( - entityData, "line", lines, LineGraphicInputEntityData::new))); + return getEntities( + LineGraphicInput.class, + dataSource, + lineGraphicInputFactory, + enrich("line", lines, LineGraphicInputEntityData::new)) + .collect(toSet()); } } diff --git a/src/main/java/edu/ie3/datamodel/io/source/IdCoordinateSource.java b/src/main/java/edu/ie3/datamodel/io/source/IdCoordinateSource.java index d7d72ffca..33fb8b9f5 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/IdCoordinateSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/IdCoordinateSource.java @@ -18,14 +18,14 @@ * latitude and longitude values, which is especially needed for data source that don't offer * combined primary or foreign keys. */ -public interface IdCoordinateSource { +public abstract class IdCoordinateSource extends EntitySource { /** * Method to retrieve the fields found in the source. * * @return an option for the found fields */ - Optional> getSourceFields() throws SourceException; + public abstract Optional> getSourceFields() throws SourceException; /** * Get the matching coordinate for the given ID @@ -33,7 +33,7 @@ public interface IdCoordinateSource { * @param id the ID to look up * @return matching coordinate */ - Optional getCoordinate(int id); + public abstract Optional getCoordinate(int id); /** * Get the matching coordinates for the given IDs @@ -41,7 +41,7 @@ public interface IdCoordinateSource { * @param ids the IDs to look up * @return the matching coordinates */ - Collection getCoordinates(int... ids); + public abstract Collection getCoordinates(int... ids); /** * Get the ID for the coordinate point @@ -49,14 +49,14 @@ public interface IdCoordinateSource { * @param coordinate the coordinate to look up * @return the matching ID */ - Optional getId(Point coordinate); + public abstract Optional getId(Point coordinate); /** * Returns all the coordinates of this source * * @return all available coordinates */ - Collection getAllCoordinates(); + public abstract Collection getAllCoordinates(); /** * Returns the nearest n coordinate points. If n is greater than four, this method will try to @@ -66,7 +66,7 @@ public interface IdCoordinateSource { * @param n number of searched points * @return the nearest n coordinates or all coordinates if n is less than all available points */ - List getNearestCoordinates(Point coordinate, int n); + public abstract List getNearestCoordinates(Point coordinate, int n); /** * Returns the closest n coordinate points to the given coordinate, that are inside a given @@ -79,7 +79,7 @@ public interface IdCoordinateSource { * @param distance to the borders of the envelope that contains the coordinates * @return the nearest n coordinates to the given point */ - List getClosestCoordinates( + public abstract List getClosestCoordinates( Point coordinate, int n, ComparableQuantity distance); /** @@ -91,7 +91,7 @@ List getClosestCoordinates( * @param coordinates the collection of points * @return a list of the nearest n coordinates to the given point or an empty list */ - default List calculateCoordinateDistances( + public List calculateCoordinateDistances( Point coordinate, int n, Collection coordinates) { if (coordinates != null && !coordinates.isEmpty()) { return GeoUtils.calcOrderedCoordinateDistances(coordinate, coordinates).stream() @@ -112,7 +112,8 @@ default List calculateCoordinateDistances( * @return either a list with one exact match or a list of corner points (default implementation: * max. 4 points) */ - List findCornerPoints(Point coordinate, ComparableQuantity distance); + public abstract List findCornerPoints( + Point coordinate, ComparableQuantity distance); /** * Method for finding the corner points of a given coordinate. If a point matches the given @@ -128,7 +129,7 @@ default List calculateCoordinateDistances( * @return either a list with one exact match or a list of corner points (default implementation: * max. 4 points) */ - default List findCornerPoints( + public List findCornerPoints( Point coordinate, Collection coordinateDistances) { boolean topLeft = false; boolean topRight = false; 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 741e821a8..46d9432b5 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/RawGridSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/RawGridSource.java @@ -6,6 +6,7 @@ package edu.ie3.datamodel.io.source; import edu.ie3.datamodel.exceptions.*; +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.*; @@ -14,7 +15,6 @@ import edu.ie3.datamodel.models.input.connector.type.Transformer3WTypeInput; import edu.ie3.datamodel.models.input.container.RawGridElements; import edu.ie3.datamodel.utils.Try; -import edu.ie3.datamodel.utils.Try.Failure; import java.util.*; import java.util.stream.Stream; @@ -26,12 +26,7 @@ * @version 0.1 * @since 08.04.20 */ -public class RawGridSource extends EntitySource { - - // field names - protected static final String NODE_A = "nodeA"; - protected static final String NODE_B = "nodeB"; - protected static final String TYPE = "type"; +public class RawGridSource extends AssetEntitySource { // general fields private final TypeSource typeSource; @@ -61,12 +56,12 @@ public RawGridSource(TypeSource typeSource, DataSource dataSource) { public void validate() throws ValidationException { Try.scanStream( Stream.of( - validate(NodeInput.class, nodeInputFactory), - validate(LineInput.class, lineInputFactory), - validate(Transformer2WInput.class, transformer2WInputFactory), - validate(Transformer3WInput.class, transformer3WInputFactory), - validate(SwitchInput.class, switchInputFactory), - validate(MeasurementUnitInput.class, measurementUnitInputFactory)), + validate(NodeInput.class, dataSource, nodeInputFactory), + validate(LineInput.class, dataSource, lineInputFactory), + validate(Transformer2WInput.class, dataSource, transformer2WInputFactory), + validate(Transformer3WInput.class, dataSource, transformer3WInputFactory), + validate(SwitchInput.class, dataSource, switchInputFactory), + validate(MeasurementUnitInput.class, dataSource, measurementUnitInputFactory)), "Validation") .transformF(FailedValidationException::new) .getOrThrow(); @@ -203,9 +198,12 @@ public Map getNodes() throws SourceException { * @return a map of UUID to object- and uuid-unique {@link NodeInput} entities */ public Map getNodes(Map operators) throws SourceException { - return unpackMap( - buildAssetInputEntityData(NodeInput.class, operators).map(nodeInputFactory::get), - NodeInput.class); + return getEntities( + NodeInput.class, + dataSource, + nodeInputFactory, + data -> assetEnricher.apply(data, operators)) + .collect(toMap()); } /** @@ -247,10 +245,9 @@ public Map getLines( Map nodes, Map lineTypeInputs) throws SourceException { - return unpackMap( - buildTypedEntityData(LineInput.class, operators, nodes, lineTypeInputs) - .map(lineInputFactory::get), - LineInput.class); + return getTypedConnectorEntities( + LineInput.class, dataSource, lineInputFactory, operators, nodes, lineTypeInputs) + .collect(toMap()); } /** @@ -294,10 +291,14 @@ public Set get2WTransformers( Map nodes, Map transformer2WTypes) throws SourceException { - return unpackSet( - buildTypedEntityData(Transformer2WInput.class, operators, nodes, transformer2WTypes) - .map(transformer2WInputFactory::get), - Transformer2WInput.class); + return getTypedConnectorEntities( + Transformer2WInput.class, + dataSource, + transformer2WInputFactory, + operators, + nodes, + transformer2WTypes) + .collect(toSet()); } /** @@ -341,13 +342,20 @@ public Set get3WTransformers( Map nodes, Map transformer3WTypes) throws SourceException { - return unpackSet( - transformer3WEntityDataStream( - buildTypedEntityData( - Transformer3WInput.class, operators, nodes, transformer3WTypes), - nodes) - .map(transformer3WInputFactory::get), - Transformer3WInput.class); + WrappedFunction builder = + data -> + connectorEnricher + .andThen( + biEnrich( + "nodeC", + nodes, + TYPE, + transformer3WTypes, + Transformer3WInputEntityData::new)) + .apply(data, operators, nodes); + + return getEntities(Transformer3WInput.class, dataSource, transformer3WInputFactory, builder) + .collect(toSet()); } /** @@ -385,9 +393,12 @@ public Set getSwitches() throws SourceException { */ public Set getSwitches( Map operators, Map nodes) throws SourceException { - return unpackSet( - buildUntypedEntityData(SwitchInput.class, operators, nodes).map(switchInputFactory::get), - SwitchInput.class); + return getEntities( + SwitchInput.class, + dataSource, + switchInputFactory, + data -> connectorEnricher.apply(data, operators, nodes)) + .collect(toSet()); } /** @@ -426,103 +437,11 @@ public Set getMeasurementUnits() throws SourceException { */ public Set getMeasurementUnits( Map operators, Map nodes) throws SourceException { - return unpackSet( - buildNodeAssetEntityData(MeasurementUnitInput.class, operators, nodes) - .map(measurementUnitInputFactory::get), - MeasurementUnitInput.class); - } - - // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - - /** - * Enriches the Stream of tries on {@link Transformer3WInputEntityData} with the information of - * the internal node. - * - * @param typedConnectorEntityDataStream Stream of already typed input entity data - * @param nodes Yet available nodes - * @return A stream of {@link Try} on enriched data - */ - protected Stream> - transformer3WEntityDataStream( - Stream, SourceException>> - typedConnectorEntityDataStream, - Map nodes) { - return typedConnectorEntityDataStream - .parallel() - .map( - typedEntityDataOpt -> - typedEntityDataOpt.flatMap( - typeEntityData -> - enrichEntityData( - typeEntityData, "nodeC", nodes, Transformer3WInputEntityData::new))); - } - - private - Stream, SourceException>> buildTypedEntityData( - Class entityClass, - Map operators, - Map nodes, - Map types) { - return typedConnectorEntityDataStream( - buildUntypedEntityData(entityClass, operators, nodes), types); - } - - /** - * Enriches the given untyped entity data with the equivalent asset type. If this is not possible, - * a {@link Failure} is returned. - * - * @param connectorEntityDataStream Stream of untyped entity data - * @param availableTypes Yet available asset types - * @param Type of the asset type - * @return Stream of {@link Try} to enhanced data - */ - protected - Stream, SourceException>> typedConnectorEntityDataStream( - Stream> connectorEntityDataStream, - Map availableTypes) { - return connectorEntityDataStream - .parallel() - .map( - noTypeEntityDataOpt -> - noTypeEntityDataOpt.flatMap( - noTypeEntityData -> - enrichEntityData( - noTypeEntityData, - TYPE, - availableTypes, - TypedConnectorInputEntityData::new))); - } - - public - Stream> buildUntypedEntityData( - Class entityClass, Map operators, Map nodes) { - return untypedConnectorEntityDataStream( - buildAssetInputEntityData(entityClass, operators), nodes); - } - - /** - * Converts a stream of {@link AssetInputEntityData} in connection with a collection of known - * {@link NodeInput}s to a stream of {@link ConnectorInputEntityData}. - * - * @param assetInputEntityDataStream Input stream of {@link AssetInputEntityData} - * @param nodes A collection of known nodes - * @return A stream on {@link Try} to matching {@link ConnectorInputEntityData} - */ - protected Stream> untypedConnectorEntityDataStream( - Stream> assetInputEntityDataStream, - Map nodes) { - return assetInputEntityDataStream - .parallel() - .map( - assetInputEntityDataTry -> - assetInputEntityDataTry.flatMap( - assetInputEntityData -> - enrichEntityData( - assetInputEntityData, - NODE_A, - nodes, - NODE_B, - nodes, - ConnectorInputEntityData::new))); + return getEntities( + MeasurementUnitInput.class, + dataSource, + measurementUnitInputFactory, + data -> nodeAssetEnricher.apply(data, operators, nodes)) + .collect(toSet()); } } 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 2a9eba45b..72ab4d8b7 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/ResultEntitySource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/ResultEntitySource.java @@ -8,8 +8,6 @@ import edu.ie3.datamodel.exceptions.FailedValidationException; 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.EntityFactory; import edu.ie3.datamodel.io.factory.result.*; import edu.ie3.datamodel.models.result.CongestionResult; import edu.ie3.datamodel.models.result.NodeResult; @@ -26,6 +24,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; +import java.util.stream.Collectors; import java.util.stream.Stream; /** @@ -45,8 +44,10 @@ public class ResultEntitySource extends EntitySource { private final CongestionResultFactory congestionResultFactory; private final FlexOptionsResultFactory flexOptionsResultFactory; + private final DataSource dataSource; + public ResultEntitySource(DataSource dataSource) { - super(dataSource); + this.dataSource = dataSource; // init factories this.systemParticipantResultFactory = new SystemParticipantResultFactory(); @@ -59,7 +60,7 @@ public ResultEntitySource(DataSource dataSource) { } public ResultEntitySource(DataSource dataSource, DateTimeFormatter dateTimeFormatter) { - super(dataSource); + this.dataSource = dataSource; // init factories this.systemParticipantResultFactory = new SystemParticipantResultFactory(dateTimeFormatter); @@ -87,20 +88,20 @@ public void validate() throws ValidationException { EvResult.class, HpResult.class, EmResult.class) - .map(c -> validate(c, systemParticipantResultFactory)) + .map(c -> validate(c, dataSource, systemParticipantResultFactory)) .toList()); participantResults.addAll( List.of( - validate(ThermalHouseResult.class, thermalResultFactory), - validate(CylindricalStorageResult.class, thermalResultFactory), - validate(SwitchResult.class, switchResultFactory), - validate(NodeResult.class, nodeResultFactory), - validate(LineResult.class, connectorResultFactory), - validate(Transformer2WResult.class, connectorResultFactory), - validate(Transformer3WResult.class, connectorResultFactory), - validate(FlexOptionsResult.class, flexOptionsResultFactory), - validate(CongestionResult.class, congestionResultFactory))); + validate(ThermalHouseResult.class, dataSource, thermalResultFactory), + validate(CylindricalStorageResult.class, dataSource, thermalResultFactory), + validate(SwitchResult.class, dataSource, switchResultFactory), + validate(NodeResult.class, dataSource, nodeResultFactory), + validate(LineResult.class, dataSource, connectorResultFactory), + validate(Transformer2WResult.class, dataSource, connectorResultFactory), + validate(Transformer3WResult.class, dataSource, connectorResultFactory), + validate(FlexOptionsResult.class, dataSource, flexOptionsResultFactory), + validate(CongestionResult.class, dataSource, congestionResultFactory))); Try.scanCollection(participantResults, Void.class) .transformF(FailedValidationException::new) @@ -377,18 +378,16 @@ public Set getCongestionResults() throws SourceException { * Build and cast entities to the correct type, since result factories outputs result entities of * some general type. * - * @param entityClass - * @param factory - * @return - * @param + * @param entityClass that should be build + * @param factory for building the entity + * @return a set of entities + * @param type of entity */ @SuppressWarnings("unchecked") private Set getResultEntities( - Class entityClass, EntityFactory factory) + Class entityClass, ResultEntityFactory factory) throws SourceException { - return unpackSet( - buildEntityData(entityClass) - .map(entityData -> factory.get(entityData).map(data -> (T) data)), - entityClass); + return getEntities(entityClass, dataSource, (ResultEntityFactory) factory, t -> t) + .collect(Collectors.toSet()); } } 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 380e79fdb..3df433dac 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/SystemParticipantSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/SystemParticipantSource.java @@ -9,6 +9,7 @@ import edu.ie3.datamodel.exceptions.SourceException; import edu.ie3.datamodel.exceptions.SystemParticipantsException; import edu.ie3.datamodel.exceptions.ValidationException; +import edu.ie3.datamodel.io.factory.EntityData; import edu.ie3.datamodel.io.factory.input.NodeAssetInputEntityData; import edu.ie3.datamodel.io.factory.input.participant.*; import edu.ie3.datamodel.models.input.EmInput; @@ -24,13 +25,14 @@ import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.function.BiFunction; import java.util.stream.Stream; /** * Implementation that provides the capability to build entities of type {@link * SystemParticipantInput} as well as {@link SystemParticipants} container. */ -public class SystemParticipantSource extends EntitySource { +public class SystemParticipantSource extends AssetEntitySource { private static final String THERMAL_STORAGE = "thermalstorage"; private static final String THERMAL_BUS = "thermalbus"; @@ -53,6 +55,21 @@ public class SystemParticipantSource extends EntitySource { private final WecInputFactory wecInputFactory; private final EvcsInputFactory evcsInputFactory; + // enriching function + protected static final TriEnrichFunction< + EntityData, OperatorInput, NodeInput, EmInput, SystemParticipantEntityData> + participantEnricher = + (data, operators, nodes, emUnits) -> + assetEnricher + .andThen(enrich(NODE, nodes, NodeAssetInputEntityData::new)) + .andThen( + enrichWithDefault( + SystemParticipantInputEntityFactory.EM, + emUnits, + null, + SystemParticipantEntityData::new)) + .apply(data, operators); + public SystemParticipantSource( TypeSource typeSource, ThermalSource thermalSource, @@ -83,16 +100,16 @@ public SystemParticipantSource( public void validate() throws ValidationException { Try.scanStream( Stream.of( - validate(BmInput.class, bmInputFactory), - validate(ChpInput.class, chpInputFactory), - validate(EvInput.class, evInputFactory), - validate(FixedFeedInInput.class, fixedFeedInInputFactory), - validate(HpInput.class, hpInputFactory), - validate(LoadInput.class, loadInputFactory), - validate(PvInput.class, pvInputFactory), - validate(StorageInput.class, storageInputFactory), - validate(WecInput.class, wecInputFactory), - validate(EvcsInput.class, evcsInputFactory)), + validate(BmInput.class, dataSource, bmInputFactory), + validate(ChpInput.class, dataSource, chpInputFactory), + validate(EvInput.class, dataSource, evInputFactory), + validate(FixedFeedInInput.class, dataSource, fixedFeedInInputFactory), + validate(HpInput.class, dataSource, hpInputFactory), + validate(LoadInput.class, dataSource, loadInputFactory), + validate(PvInput.class, dataSource, pvInputFactory), + validate(StorageInput.class, dataSource, storageInputFactory), + validate(WecInput.class, dataSource, wecInputFactory), + validate(EvcsInput.class, dataSource, evcsInputFactory)), "Validation") .transformF(FailedValidationException::new) .getOrThrow(); @@ -267,10 +284,12 @@ public Set getFixedFeedIns() throws SourceException { public Set getFixedFeedIns( Map operators, Map nodes, Map emUnits) throws SourceException { - return unpackSet( - buildSystemParticipantEntityData(FixedFeedInInput.class, operators, nodes, emUnits) - .map(fixedFeedInInputFactory::get), - FixedFeedInInput.class); + return getEntities( + FixedFeedInInput.class, + dataSource, + fixedFeedInInputFactory, + data -> participantEnricher.apply(data, operators, nodes, emUnits)) + .collect(toSet()); } /** @@ -310,10 +329,12 @@ public Set getPvPlants() throws SourceException { public Set getPvPlants( Map operators, Map nodes, Map emUnits) throws SourceException { - return unpackSet( - buildSystemParticipantEntityData(PvInput.class, operators, nodes, emUnits) - .map(pvInputFactory::get), - PvInput.class); + return getEntities( + PvInput.class, + dataSource, + pvInputFactory, + data -> participantEnricher.apply(data, operators, nodes, emUnits)) + .collect(toSet()); } /** @@ -353,10 +374,12 @@ public Set getLoads() throws SourceException { public Set getLoads( Map operators, Map nodes, Map emUnits) throws SourceException { - return unpackSet( - buildSystemParticipantEntityData(LoadInput.class, operators, nodes, emUnits) - .map(loadInputFactory::get), - LoadInput.class); + return getEntities( + LoadInput.class, + dataSource, + loadInputFactory, + data -> participantEnricher.apply(data, operators, nodes, emUnits)) + .collect(toSet()); } /** @@ -396,10 +419,12 @@ public Set getEvcs() throws SourceException { public Set getEvcs( Map operators, Map nodes, Map emUnits) throws SourceException { - return unpackSet( - buildSystemParticipantEntityData(EvcsInput.class, operators, nodes, emUnits) - .map(evcsInputFactory::get), - EvcsInput.class); + return getEntities( + EvcsInput.class, + dataSource, + evcsInputFactory, + data -> participantEnricher.apply(data, operators, nodes, emUnits)) + .collect(toSet()); } /** @@ -444,10 +469,15 @@ public Set getBmPlants( Map emUnits, Map types) throws SourceException { - return unpackSet( - buildTypedSystemParticipantEntityData(BmInput.class, operators, nodes, emUnits, types) - .map(bmInputFactory::get), - BmInput.class); + return getEntities( + BmInput.class, + dataSource, + bmInputFactory, + data -> + participantEnricher + .andThen(enrichTypes(types)) + .apply(data, operators, nodes, emUnits)) + .collect(toSet()); } /** @@ -494,10 +524,15 @@ public Set getStorages( Map emUnits, Map types) throws SourceException { - return unpackSet( - buildTypedSystemParticipantEntityData(StorageInput.class, operators, nodes, emUnits, types) - .map(storageInputFactory::get), - StorageInput.class); + return getEntities( + StorageInput.class, + dataSource, + storageInputFactory, + data -> + participantEnricher + .andThen(enrichTypes(types)) + .apply(data, operators, nodes, emUnits)) + .collect(toSet()); } /** @@ -542,10 +577,15 @@ public Set getWecPlants( Map emUnits, Map types) throws SourceException { - return unpackSet( - buildTypedSystemParticipantEntityData(WecInput.class, operators, nodes, emUnits, types) - .map(wecInputFactory::get), - WecInput.class); + return getEntities( + WecInput.class, + dataSource, + wecInputFactory, + data -> + participantEnricher + .andThen(enrichTypes(types)) + .apply(data, operators, nodes, emUnits)) + .collect(toSet()); } /** @@ -589,10 +629,15 @@ public Set getEvs( Map emUnits, Map types) throws SourceException { - return unpackSet( - buildTypedSystemParticipantEntityData(EvInput.class, operators, nodes, emUnits, types) - .map(evInputFactory::get), - EvInput.class); + return getEntities( + EvInput.class, + dataSource, + evInputFactory, + data -> + participantEnricher + .andThen(enrichTypes(types)) + .apply(data, operators, nodes, emUnits)) + .collect(toSet()); } public Set getChpPlants() throws SourceException { @@ -635,14 +680,21 @@ public Set getChpPlants( Map thermalBuses, Map thermalStorages) throws SourceException { - return unpackSet( - chpEntityStream( - buildTypedSystemParticipantEntityData( - ChpInput.class, operators, nodes, emUnits, types), - thermalStorages, - thermalBuses) - .map(chpInputFactory::get), - ChpInput.class); + + WrappedFunction builder = + data -> + participantEnricher + .andThen(enrichTypes(types)) + .andThen( + biEnrich( + THERMAL_BUS, + thermalBuses, + THERMAL_STORAGE, + thermalStorages, + ChpInputEntityData::new)) + .apply(data, operators, nodes, emUnits); + + return getEntities(ChpInput.class, dataSource, chpInputFactory, builder).collect(toSet()); } public Set getHeatPumps() throws SourceException { @@ -680,154 +732,29 @@ public Set getHeatPumps( Map types, Map thermalBuses) throws SourceException { - return unpackSet( - hpEntityStream( - buildTypedSystemParticipantEntityData( - HpInput.class, operators, nodes, emUnits, types), - thermalBuses) - .map(hpInputFactory::get), - HpInput.class); - } - - // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - - private static Stream> chpEntityStream( - Stream, SourceException>> - typedEntityDataStream, - Map thermalStorages, - Map thermalBuses) { - - return typedEntityDataStream - .parallel() - .map( - typedEntityDataOpt -> - typedEntityDataOpt.flatMap( - typedEntityData -> - enrichEntityData( - typedEntityData, - THERMAL_BUS, - thermalBuses, - THERMAL_STORAGE, - thermalStorages, - ChpInputEntityData::new))); - } - - /** - * Enriches a given stream of {@link SystemParticipantTypedEntityData} tries with a type of {@link - * ThermalBusInput} based on the provided collection of buses and the fields to values mapping - * inside the already provided {@link SystemParticipantTypedEntityData} instance. - * - * @param typedEntityDataStream the data stream of {@link SystemParticipantTypedEntityData} tries - * @param thermalBuses the thermal buses that should be used for enrichment and to build {@link - * HpInputEntityData} - * @return stream of tries of {@link HpInputEntityData} instances - */ - private static Stream> hpEntityStream( - Stream, SourceException>> - typedEntityDataStream, - Map thermalBuses) { - - return typedEntityDataStream - .parallel() - .map( - typedEntityDataOpt -> - typedEntityDataOpt.flatMap( - typedEntityData -> - enrichEntityData( - typedEntityData, THERMAL_BUS, thermalBuses, HpInputEntityData::new))); - } - - /** - * Constructs a stream of {@link SystemParticipantTypedEntityData} wrapped in {@link Try}'s. - * - * @param entityClass the class of the entities that should be built - * @param operators the operators that should be considered for these entities - * @param nodes the nodes that should be considered for these entities - * @param types the types that should be considered for these entities - * @param the type of the type model of the resulting entity - * @return a stream of tries holding an instance of a {@link SystemParticipantTypedEntityData} - */ - private - Stream, SourceException>> - buildTypedSystemParticipantEntityData( - Class entityClass, - Map operators, - Map nodes, - Map emUnits, - Map types) { - return typedSystemParticipantEntityStream( - buildSystemParticipantEntityData(entityClass, operators, nodes, emUnits), types); - } - /** - * Enriches a given stream of {@link SystemParticipantEntityData} {@link Try} objects with a type - * of {@link SystemParticipantTypeInput} based on the provided collection of types and the fields - * to values mapping that inside the already provided {@link SystemParticipantEntityData} - * instance. - * - * @param systemParticipantEntityDataStream the data stream of {@link SystemParticipantEntityData} - * {@link Try} objects - * @param types the types that should be used for enrichment and to build {@link - * SystemParticipantTypedEntityData} from - * @param the type of the provided entity types as well as the type parameter of the resulting - * {@link SystemParticipantTypedEntityData} - * @return a stream of tries of {@link SystemParticipantTypedEntityData} instances - */ - private static - Stream, SourceException>> - typedSystemParticipantEntityStream( - Stream> - systemParticipantEntityDataStream, - Map types) { - return systemParticipantEntityDataStream - .parallel() - .map( - participantEntityDataTry -> - participantEntityDataTry.flatMap( - participantEntityData -> - enrichEntityData( - participantEntityData, - TYPE, - types, - SystemParticipantTypedEntityData::new))); + WrappedFunction builder = + data -> + participantEnricher + .andThen(enrichTypes(types)) + .andThen(enrich(THERMAL_BUS, thermalBuses, HpInputEntityData::new)) + .apply(data, operators, nodes, emUnits); + return getEntities(HpInput.class, dataSource, hpInputFactory, builder).collect(toSet()); } - private Stream> - buildSystemParticipantEntityData( - Class entityClass, - Map operators, - Map nodes, - Map emUnits) { - return systemParticipantEntityStream( - buildNodeAssetEntityData(entityClass, operators, nodes), emUnits); - } + // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- /** - * Enriches a given stream of {@link NodeAssetInputEntityData} {@link Try} objects with a type of - * {@link EmInput} based on the provided collection of EMs and the fields to values mapping that - * inside the already provided {@link NodeAssetInputEntityData} instance. - * - * @param nodeAssetEntityDataStream the data stream of {@link NodeAssetInputEntityData} {@link - * Try} objects - * @param emUnits the energy management units that should be used for enrichment and to build - * {@link SystemParticipantEntityData} from - * @return a stream of tries of {@link SystemParticipantEntityData} instances + * Builds a function for enriching {@link SystemParticipantEntityData} with types. + * + * @param types all known types + * @return a typed entity data + * @param type of types */ - private static Stream> - systemParticipantEntityStream( - Stream> nodeAssetEntityDataStream, - Map emUnits) { - return nodeAssetEntityDataStream - .parallel() - .map( - nodeAssetInputEntityDataTry -> - nodeAssetInputEntityDataTry.flatMap( - nodeAssetInputEntityData -> - optionallyEnrichEntityData( - nodeAssetInputEntityData, - SystemParticipantInputEntityFactory.EM, - emUnits, - null, - SystemParticipantEntityData::new))); + private static + WrappedFunction> enrichTypes(Map types) { + BiFunction> typeEnricher = + SystemParticipantTypedEntityData::new; + return entityData -> enrich(TYPE, types, typeEnricher).apply(entityData); } } 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 c83aa4e36..f3334600d 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/ThermalSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/ThermalSource.java @@ -6,8 +6,8 @@ package edu.ie3.datamodel.io.source; import edu.ie3.datamodel.exceptions.*; +import edu.ie3.datamodel.io.factory.EntityData; import edu.ie3.datamodel.io.factory.input.*; -import edu.ie3.datamodel.models.UniqueEntity; import edu.ie3.datamodel.models.input.OperatorInput; import edu.ie3.datamodel.models.input.thermal.CylindricalStorageInput; import edu.ie3.datamodel.models.input.thermal.ThermalBusInput; @@ -17,8 +17,6 @@ import java.util.Map; import java.util.Set; import java.util.UUID; -import java.util.function.Function; -import java.util.stream.Collectors; import java.util.stream.Stream; /** @@ -29,7 +27,7 @@ * @version 0.1 * @since 08.04.20 */ -public class ThermalSource extends EntitySource { +public class ThermalSource extends AssetEntitySource { // general fields private final TypeSource typeSource; @@ -38,6 +36,15 @@ public class ThermalSource extends EntitySource { private final CylindricalStorageInputFactory cylindricalStorageInputFactory; private final ThermalHouseInputFactory thermalHouseInputFactory; + // enriching function + protected static BiEnrichFunction< + EntityData, OperatorInput, ThermalBusInput, ThermalUnitInputEntityData> + thermalUnitEnricher = + (data, operators, buses) -> + assetEnricher + .andThen(enrich("thermalbus", buses, ThermalUnitInputEntityData::new)) + .apply(data, operators); + public ThermalSource(TypeSource typeSource, DataSource dataSource) { super(dataSource); this.typeSource = typeSource; @@ -51,9 +58,9 @@ public ThermalSource(TypeSource typeSource, DataSource dataSource) { public void validate() throws ValidationException { Try.scanStream( Stream.of( - validate(ThermalBusInput.class, thermalBusInputFactory), - validate(CylindricalStorageInput.class, cylindricalStorageInputFactory), - validate(ThermalHouseInput.class, thermalHouseInputFactory)), + validate(ThermalBusInput.class, dataSource, thermalBusInputFactory), + validate(CylindricalStorageInput.class, dataSource, cylindricalStorageInputFactory), + validate(ThermalHouseInput.class, dataSource, thermalHouseInputFactory)), "Validation") .transformF(FailedValidationException::new) .getOrThrow(); @@ -94,10 +101,12 @@ public Map getThermalBuses() throws SourceException { */ public Map getThermalBuses(Map operators) throws SourceException { - return unpackMap( - buildAssetInputEntityData(ThermalBusInput.class, operators) - .map(thermalBusInputFactory::get), - ThermalBusInput.class); + return getEntities( + ThermalBusInput.class, + dataSource, + thermalBusInputFactory, + data -> assetEnricher.apply(data, operators)) + .collect(toMap()); } /** @@ -112,8 +121,7 @@ public Map getThermalBuses(Map opera * @return a map of UUID to object- and uuid-unique {@link ThermalStorageInput} entities */ public Map getThermalStorages() throws SourceException { - return getCylindricalStorages().stream() - .collect(Collectors.toMap(UniqueEntity::getUuid, Function.identity())); + return getCylindricalStorages().stream().collect(toMap()); } /** @@ -138,8 +146,7 @@ public Map getThermalStorages() throws SourceExceptio public Map getThermalStorages( Map operators, Map thermalBuses) throws SourceException { - return getCylindricalStorages(operators, thermalBuses).stream() - .collect(Collectors.toMap(UniqueEntity::getUuid, Function.identity())); + return getCylindricalStorages(operators, thermalBuses).stream().collect(toMap()); } /** @@ -182,11 +189,12 @@ public Map getThermalHouses() throws SourceException { public Map getThermalHouses( Map operators, Map thermalBuses) throws SourceException { - return unpackMap( - thermalUnitInputEntityDataStream( - buildAssetInputEntityData(ThermalHouseInput.class, operators), thermalBuses) - .map(thermalHouseInputFactory::get), - ThermalHouseInput.class); + return getEntities( + ThermalHouseInput.class, + dataSource, + thermalHouseInputFactory, + data -> thermalUnitEnricher.apply(data, operators, thermalBuses)) + .collect(toMap()); } /** @@ -229,38 +237,11 @@ public Set getCylindricalStorages() throws SourceExcept public Set getCylindricalStorages( Map operators, Map thermalBuses) throws SourceException { - return unpackSet( - thermalUnitInputEntityDataStream( - buildAssetInputEntityData(CylindricalStorageInput.class, operators), thermalBuses) - .map(cylindricalStorageInputFactory::get), - CylindricalStorageInput.class); - } - - /** - * Enriches a given stream of {@link AssetInputEntityData} {@link Try} objects with a type of - * {@link ThermalBusInput} based on the provided collection of types and the fields to values - * mapping that inside the already provided {@link AssetInputEntityData} instance. - * - * @param assetInputEntityDataStream the data stream of {@link AssetInputEntityData} {@link Try} - * objects - * @param thermalBuses the thermal buses that should be used for enrichment and to build {@link - * ThermalUnitInputEntityData} from - * @return a stream of tries of {@link ThermalUnitInputEntityData} instances - */ - private static Stream> - thermalUnitInputEntityDataStream( - Stream> assetInputEntityDataStream, - Map thermalBuses) { - return assetInputEntityDataStream - .parallel() - .map( - assetInputEntityDataTry -> - assetInputEntityDataTry.flatMap( - assetInputEntityData -> - enrichEntityData( - assetInputEntityData, - "thermalbus", - thermalBuses, - ThermalUnitInputEntityData::new))); + return getEntities( + CylindricalStorageInput.class, + dataSource, + cylindricalStorageInputFactory, + data -> thermalUnitEnricher.apply(data, operators, thermalBuses)) + .collect(toSet()); } } 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 f65e7eb58..75a1802c6 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/TimeSeriesMappingSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/TimeSeriesMappingSource.java @@ -7,6 +7,7 @@ import edu.ie3.datamodel.exceptions.FactoryException; 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.timeseries.TimeSeriesMappingFactory; import edu.ie3.datamodel.models.input.InputEntity; @@ -22,7 +23,7 @@ * This interface describes basic function to handle mapping between models and their respective * time series */ -public abstract class TimeSeriesMappingSource { +public abstract class TimeSeriesMappingSource extends EntitySource { protected final TimeSeriesMappingFactory mappingFactory; @@ -30,6 +31,11 @@ protected TimeSeriesMappingSource() { this.mappingFactory = new TimeSeriesMappingFactory(); } + @Override + public void validate() throws ValidationException { + validate(MappingEntry.class, this::getSourceFields, mappingFactory); + } + /** * Get a mapping from model {@link UUID} to the time series {@link UUID} * diff --git a/src/main/java/edu/ie3/datamodel/io/source/TimeSeriesSource.java b/src/main/java/edu/ie3/datamodel/io/source/TimeSeriesSource.java index fe45ee751..994f0f440 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/TimeSeriesSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/TimeSeriesSource.java @@ -21,10 +21,10 @@ * The interface definition of a source, that is able to provide one specific time series for one * model */ -public abstract class TimeSeriesSource { +public abstract class TimeSeriesSource extends EntitySource { protected Class valueClass; - protected TimeBasedSimpleValueFactory valueFactory; + protected final TimeBasedSimpleValueFactory valueFactory; protected TimeSeriesSource(Class valueClass, TimeBasedSimpleValueFactory factory) { this.valueFactory = factory; 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 d0263f87a..16b2a9f4f 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/TypeSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/TypeSource.java @@ -5,20 +5,15 @@ */ package edu.ie3.datamodel.io.source; -import edu.ie3.datamodel.exceptions.FactoryException; import edu.ie3.datamodel.exceptions.FailedValidationException; 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.EntityFactory; import edu.ie3.datamodel.io.factory.input.OperatorInputFactory; import edu.ie3.datamodel.io.factory.typeinput.LineTypeInputFactory; import edu.ie3.datamodel.io.factory.typeinput.SystemParticipantTypeInputFactory; import edu.ie3.datamodel.io.factory.typeinput.Transformer2WTypeInputFactory; import edu.ie3.datamodel.io.factory.typeinput.Transformer3WTypeInputFactory; -import edu.ie3.datamodel.models.input.AssetTypeInput; import edu.ie3.datamodel.models.input.OperatorInput; -import edu.ie3.datamodel.models.input.UniqueInputEntity; 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; @@ -46,8 +41,10 @@ public class TypeSource extends EntitySource { private final Transformer3WTypeInputFactory transformer3WTypeInputFactory; private final SystemParticipantTypeInputFactory systemParticipantTypeInputFactory; + private final DataSource dataSource; + public TypeSource(DataSource dataSource) { - super(dataSource); + this.dataSource = dataSource; this.operatorInputFactory = new OperatorInputFactory(); this.transformer2WTypeInputFactory = new Transformer2WTypeInputFactory(); @@ -67,15 +64,15 @@ public void validate() throws ValidationException { WecTypeInput.class, ChpTypeInput.class, StorageTypeInput.class) - .map(c -> validate(c, systemParticipantTypeInputFactory)) + .map(c -> validate(c, dataSource, systemParticipantTypeInputFactory)) .toList()); participantResults.addAll( List.of( - validate(OperatorInput.class, operatorInputFactory), - validate(LineTypeInput.class, lineTypeInputFactory), - validate(Transformer2WTypeInput.class, transformer2WTypeInputFactory), - validate(Transformer3WTypeInput.class, transformer3WTypeInputFactory))); + validate(OperatorInput.class, dataSource, operatorInputFactory), + validate(LineTypeInput.class, dataSource, lineTypeInputFactory), + validate(Transformer2WTypeInput.class, dataSource, transformer2WTypeInputFactory), + validate(Transformer3WTypeInput.class, dataSource, transformer3WTypeInputFactory))); Try.scanCollection(participantResults, Void.class) .transformF(FailedValidationException::new) @@ -93,9 +90,7 @@ public void validate() throws ValidationException { * @return a map of UUID to object- and uuid-unique {@link Transformer2WTypeInput} entities */ public Map getTransformer2WTypes() throws SourceException { - return unpackMap( - buildEntityData(Transformer2WTypeInput.class).map(transformer2WTypeInputFactory::get), - Transformer2WTypeInput.class); + return getEntities(Transformer2WTypeInput.class, dataSource, transformer2WTypeInputFactory); } /** @@ -108,8 +103,7 @@ public Map getTransformer2WTypes() throws SourceEx * @return a map of UUID to object- and uuid-unique {@link OperatorInput} entities */ public Map getOperators() throws SourceException { - return unpackMap( - buildEntityData(OperatorInput.class).map(operatorInputFactory::get), OperatorInput.class); + return getEntities(OperatorInput.class, dataSource, operatorInputFactory); } /** @@ -122,8 +116,7 @@ public Map getOperators() throws SourceException { * @return a map of UUID to object- and uuid-unique {@link LineTypeInput} entities */ public Map getLineTypes() throws SourceException { - return unpackMap( - buildEntityData(LineTypeInput.class).map(lineTypeInputFactory::get), LineTypeInput.class); + return getEntities(LineTypeInput.class, dataSource, lineTypeInputFactory); } /** @@ -137,9 +130,7 @@ public Map getLineTypes() throws SourceException { * @return a map of UUID to object- and uuid-unique {@link Transformer3WTypeInput} entities */ public Map getTransformer3WTypes() throws SourceException { - return unpackMap( - buildEntityData(Transformer3WTypeInput.class).map(transformer3WTypeInputFactory::get), - Transformer3WTypeInput.class); + return getEntities(Transformer3WTypeInput.class, dataSource, transformer3WTypeInputFactory); } /** @@ -152,8 +143,7 @@ public Map getTransformer3WTypes() throws SourceEx * @return a map of UUID to object- and uuid-unique {@link BmTypeInput} entities */ public Map getBmTypes() throws SourceException { - return unpackMap( - buildEntities(BmTypeInput.class, systemParticipantTypeInputFactory), BmTypeInput.class); + return getEntities(BmTypeInput.class, dataSource, systemParticipantTypeInputFactory); } /** @@ -166,8 +156,7 @@ public Map getBmTypes() throws SourceException { * @return a map of UUID to object- and uuid-unique {@link ChpTypeInput} entities */ public Map getChpTypes() throws SourceException { - return unpackMap( - buildEntities(ChpTypeInput.class, systemParticipantTypeInputFactory), ChpTypeInput.class); + return getEntities(ChpTypeInput.class, dataSource, systemParticipantTypeInputFactory); } /** @@ -180,8 +169,7 @@ public Map getChpTypes() throws SourceException { * @return a map of UUID to object- and uuid-unique {@link HpTypeInput} entities */ public Map getHpTypes() throws SourceException { - return unpackMap( - buildEntities(HpTypeInput.class, systemParticipantTypeInputFactory), HpTypeInput.class); + return getEntities(HpTypeInput.class, dataSource, systemParticipantTypeInputFactory); } /** @@ -195,9 +183,7 @@ public Map getHpTypes() throws SourceException { * @return a map of UUID to object- and uuid-unique {@link StorageTypeInput} entities */ public Map getStorageTypes() throws SourceException { - return unpackMap( - buildEntities(StorageTypeInput.class, systemParticipantTypeInputFactory), - StorageTypeInput.class); + return getEntities(StorageTypeInput.class, dataSource, systemParticipantTypeInputFactory); } /** @@ -210,8 +196,7 @@ public Map getStorageTypes() throws SourceException { * @return a map of UUID to object- and uuid-unique {@link WecTypeInput} entities */ public Map getWecTypes() throws SourceException { - return unpackMap( - buildEntities(WecTypeInput.class, systemParticipantTypeInputFactory), WecTypeInput.class); + return getEntities(WecTypeInput.class, dataSource, systemParticipantTypeInputFactory); } /** @@ -224,22 +209,6 @@ public Map getWecTypes() throws SourceException { * @return a map of UUID to object- and uuid-unique {@link EvTypeInput} entities */ public Map getEvTypes() throws SourceException { - return unpackMap( - buildEntities(EvTypeInput.class, systemParticipantTypeInputFactory), EvTypeInput.class); - } - - /** - * Build and cast entities to the correct type, since {@link SystemParticipantTypeInputFactory} - * outputs {@link SystemParticipantTypeInput} of general type. - * - * @param entityClass The class of type input entity to build - * @param factory The factory to use to build the entity - * @return a stream of {@link Try}s containing the desired entities - * @param The type of AssetType to return - */ - @SuppressWarnings("unchecked") - private Stream> buildEntities( - Class entityClass, EntityFactory factory) { - return buildEntityData(entityClass).map(data -> (Try) factory.get(data)); + return getEntities(EvTypeInput.class, dataSource, systemParticipantTypeInputFactory); } } 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 1cf672164..959613b7c 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/WeatherSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/WeatherSource.java @@ -6,6 +6,7 @@ package edu.ie3.datamodel.io.source; import edu.ie3.datamodel.exceptions.SourceException; +import edu.ie3.datamodel.exceptions.ValidationException; import edu.ie3.datamodel.io.factory.timeseries.TimeBasedWeatherValueData; import edu.ie3.datamodel.io.factory.timeseries.TimeBasedWeatherValueFactory; import edu.ie3.datamodel.models.timeseries.individual.IndividualTimeSeries; @@ -22,7 +23,7 @@ import org.slf4j.LoggerFactory; /** Abstract class for WeatherSource by Csv and Sql Data */ -public abstract class WeatherSource { +public abstract class WeatherSource extends EntitySource { protected static final Logger log = LoggerFactory.getLogger(WeatherSource.class); @@ -43,11 +44,14 @@ protected WeatherSource( /** * Method to retrieve the fields found in the source. * - * @param entityClass class of the source * @return an option for fields found in the source */ - public abstract Optional> getSourceFields( - Class entityClass) throws SourceException; + public abstract Optional> getSourceFields() throws SourceException; + + @Override + public void validate() throws ValidationException { + validate(WeatherValue.class, this::getSourceFields, weatherFactory); + } // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- @@ -116,7 +120,7 @@ protected Map> mapWeatherValuesToPoint * @param inputStream stream of fields to convert into TimeBasedValues * @return a list of that TimeBasedValues */ - public List> buildTimeBasedValues( + protected List> buildTimeBasedValues( TimeBasedWeatherValueFactory factory, Stream> inputStream) throws SourceException { return Try.scanStream( diff --git a/src/main/java/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSource.java b/src/main/java/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSource.java index ac9ae8294..74732dbb0 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/couchbase/CouchbaseWeatherSource.java @@ -10,7 +10,6 @@ import com.couchbase.client.java.json.JsonObject; import com.couchbase.client.java.kv.GetResult; import com.couchbase.client.java.query.QueryResult; -import edu.ie3.datamodel.exceptions.SourceException; import edu.ie3.datamodel.io.connectors.CouchbaseConnector; import edu.ie3.datamodel.io.factory.timeseries.TimeBasedWeatherValueData; import edu.ie3.datamodel.io.factory.timeseries.TimeBasedWeatherValueFactory; @@ -19,7 +18,6 @@ import edu.ie3.datamodel.models.timeseries.individual.IndividualTimeSeries; import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue; import edu.ie3.datamodel.models.value.WeatherValue; -import edu.ie3.datamodel.utils.Try; import edu.ie3.util.interval.ClosedInterval; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; @@ -61,8 +59,7 @@ public CouchbaseWeatherSource( IdCoordinateSource coordinateSource, String coordinateIdColumnName, TimeBasedWeatherValueFactory weatherFactory, - String timeStampPattern) - throws SourceException { + String timeStampPattern) { this( connector, coordinateSource, @@ -91,30 +88,16 @@ public CouchbaseWeatherSource( String coordinateIdColumnName, String keyPrefix, TimeBasedWeatherValueFactory weatherFactory, - String timeStampPattern) - throws SourceException { + String timeStampPattern) { super(idCoordinateSource, weatherFactory); this.connector = connector; this.coordinateIdColumnName = coordinateIdColumnName; this.keyPrefix = keyPrefix; this.timeStampPattern = timeStampPattern; - - // validating - Try.of(() -> getSourceFields(WeatherValue.class), SourceException.class) - .flatMap( - fieldsOpt -> - fieldsOpt - .map( - fields -> - weatherFactory - .validate(fields, WeatherValue.class) - .transformF(SourceException::new)) - .orElse(Try.Success.empty())) - .getOrThrow(); } @Override - public Optional> getSourceFields(Class entityClass) { + public Optional> getSourceFields() { return connector.getSourceFields(); } @@ -190,7 +173,7 @@ public Optional> getWeather(ZonedDateTime date, Poi * @param coordinateId the coordinate Id of the weather data * @return a weather document key */ - public String generateWeatherKey(ZonedDateTime time, Integer coordinateId) { + private String generateWeatherKey(ZonedDateTime time, Integer coordinateId) { String key = keyPrefix + "::"; key += coordinateId + "::"; key += time.format(DateTimeFormatter.ofPattern(timeStampPattern)); @@ -205,7 +188,7 @@ public String generateWeatherKey(ZonedDateTime time, Integer coordinateId) { * @param coordinateId the coordinate ID for which the documents are queried * @return the query string */ - public String createQueryStringForIntervalAndCoordinate( + private String createQueryStringForIntervalAndCoordinate( ClosedInterval timeInterval, int coordinateId) { String basicQuery = "SELECT " + connector.getBucketName() + ".* FROM " + connector.getBucketName(); @@ -247,7 +230,7 @@ private Optional toTimeBasedWeatherValueData(JsonObje * @param jsonObj the JsonObject to convert * @return an optional weather value */ - public Optional> toTimeBasedWeatherValue(JsonObject jsonObj) { + private Optional> toTimeBasedWeatherValue(JsonObject jsonObj) { Optional data = toTimeBasedWeatherValueData(jsonObj); if (data.isEmpty()) { logger.warn("Unable to parse json object"); 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 04a1b08d9..7f7e0be78 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 @@ -36,7 +36,7 @@ * Implementation of {@link IdCoordinateSource} to read the mapping between coordinate id and actual * coordinate from csv file and build a mapping from it. */ -public class CsvIdCoordinateSource implements IdCoordinateSource { +public class CsvIdCoordinateSource extends IdCoordinateSource { protected static final Logger log = LoggerFactory.getLogger(CsvIdCoordinateSource.class); @@ -58,6 +58,11 @@ public CsvIdCoordinateSource(IdCoordinateFactory factory, CsvDataSource dataSour coordinateToId = invert(idToCoordinate); } + @Override + public void validate() throws ValidationException { + validate(IdCoordinateInput.class, this::getSourceFields, factory); + } + /** * Read in and process the mapping * diff --git a/src/main/java/edu/ie3/datamodel/io/source/csv/CsvTimeSeriesMappingSource.java b/src/main/java/edu/ie3/datamodel/io/source/csv/CsvTimeSeriesMappingSource.java index 4f1065dd7..c6de18c1e 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/csv/CsvTimeSeriesMappingSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/csv/CsvTimeSeriesMappingSource.java @@ -8,7 +8,6 @@ import edu.ie3.datamodel.exceptions.SourceException; import edu.ie3.datamodel.io.naming.FileNamingStrategy; import edu.ie3.datamodel.io.source.TimeSeriesMappingSource; -import edu.ie3.datamodel.utils.Try; import java.nio.file.Path; import java.util.Map; import java.util.Optional; @@ -20,22 +19,8 @@ public class CsvTimeSeriesMappingSource extends TimeSeriesMappingSource { private final CsvDataSource dataSource; public CsvTimeSeriesMappingSource( - String csvSep, Path gridFolderPath, FileNamingStrategy fileNamingStrategy) - throws SourceException { + String csvSep, Path gridFolderPath, FileNamingStrategy fileNamingStrategy) { this.dataSource = new CsvDataSource(csvSep, gridFolderPath, fileNamingStrategy); - - // validating - Try.of(this::getSourceFields, SourceException.class) - .flatMap( - fieldsOpt -> - fieldsOpt - .map( - fields -> - mappingFactory - .validate(fields, MappingEntry.class) - .transformF(SourceException::new)) - .orElse(Try.Success.empty())) - .getOrThrow(); } @Override 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 49d6f83e5..7fb5d5b02 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 @@ -7,6 +7,7 @@ import edu.ie3.datamodel.exceptions.FactoryException; import edu.ie3.datamodel.exceptions.SourceException; +import edu.ie3.datamodel.exceptions.ValidationException; import edu.ie3.datamodel.io.csv.CsvIndividualTimeSeriesMetaInformation; import edu.ie3.datamodel.io.factory.timeseries.*; import edu.ie3.datamodel.io.naming.FileNamingStrategy; @@ -27,6 +28,7 @@ public class CsvTimeSeriesSource extends TimeSeriesSource { private final IndividualTimeSeries timeSeries; private final CsvDataSource dataSource; + private final Path filePath; /** * Factory method to build a source from given meta information @@ -91,6 +93,7 @@ public CsvTimeSeriesSource( TimeBasedSimpleValueFactory factory) { super(valueClass, factory); this.dataSource = new CsvDataSource(csvSep, folderPath, fileNamingStrategy); + this.filePath = filePath; /* Read in the full time series */ try { @@ -105,6 +108,11 @@ public CsvTimeSeriesSource( } } + @Override + public void validate() throws ValidationException { + validate(valueClass, () -> dataSource.getSourceFields(filePath), valueFactory); + } + @Override public IndividualTimeSeries getTimeSeries() { return timeSeries; 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 9a2eb69aa..0b000bf94 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 @@ -64,6 +64,7 @@ public CsvWeatherSource( throws SourceException { super(idCoordinateSource, weatherFactory); this.dataSource = new CsvDataSource(csvSep, folderPath, fileNamingStrategy); + coordinateToTimeSeries = getWeatherTimeSeries(); } @@ -71,8 +72,20 @@ public CsvWeatherSource( /** Returns an empty optional for now. */ @Override - public Optional> getSourceFields(Class entityClass) { - return Optional.empty(); + public Optional> getSourceFields() { + return dataSource + .getCsvIndividualTimeSeriesMetaInformation(ColumnScheme.WEATHER) + .values() + .stream() + .findFirst() + .flatMap( + meta -> { + try { + return dataSource.getSourceFields(meta.getFullFilePath()); + } catch (SourceException e) { + return Optional.empty(); + } + }); } @Override diff --git a/src/main/java/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSource.java b/src/main/java/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSource.java index 2d9994d8a..54531826b 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/influxdb/InfluxDbWeatherSource.java @@ -5,7 +5,6 @@ */ package edu.ie3.datamodel.io.source.influxdb; -import edu.ie3.datamodel.exceptions.SourceException; import edu.ie3.datamodel.io.connectors.InfluxDbConnector; import edu.ie3.datamodel.io.factory.timeseries.TimeBasedWeatherValueData; import edu.ie3.datamodel.io.factory.timeseries.TimeBasedWeatherValueFactory; @@ -48,26 +47,13 @@ public class InfluxDbWeatherSource extends WeatherSource { public InfluxDbWeatherSource( InfluxDbConnector connector, IdCoordinateSource idCoordinateSource, - TimeBasedWeatherValueFactory weatherValueFactory) - throws SourceException { + TimeBasedWeatherValueFactory weatherValueFactory) { super(idCoordinateSource, weatherValueFactory); this.connector = connector; - - Try.of(() -> getSourceFields(WeatherValue.class), SourceException.class) - .flatMap( - fieldsOpt -> - fieldsOpt - .map( - fields -> - weatherFactory - .validate(fields, WeatherValue.class) - .transformF(SourceException::new)) - .orElse(Try.Success.empty())) - .getOrThrow(); } @Override - public Optional> getSourceFields(Class entityClass) { + public Optional> getSourceFields() { return connector.getSourceFields(); } diff --git a/src/main/java/edu/ie3/datamodel/io/source/sql/SqlIdCoordinateSource.java b/src/main/java/edu/ie3/datamodel/io/source/sql/SqlIdCoordinateSource.java index 4424d3adf..a891dd2ee 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/sql/SqlIdCoordinateSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/sql/SqlIdCoordinateSource.java @@ -7,7 +7,7 @@ import static edu.ie3.datamodel.io.source.sql.SqlDataSource.createBaseQueryString; -import edu.ie3.datamodel.exceptions.SourceException; +import edu.ie3.datamodel.exceptions.ValidationException; import edu.ie3.datamodel.io.connectors.SqlConnector; import edu.ie3.datamodel.io.factory.SimpleFactoryData; import edu.ie3.datamodel.io.factory.timeseries.SqlIdCoordinateFactory; @@ -15,7 +15,6 @@ import edu.ie3.datamodel.io.source.IdCoordinateSource; import edu.ie3.datamodel.models.input.IdCoordinateInput; import edu.ie3.datamodel.models.value.CoordinateValue; -import edu.ie3.datamodel.utils.Try; import edu.ie3.util.geo.CoordinateDistance; import edu.ie3.util.geo.GeoUtils; import java.sql.Array; @@ -27,7 +26,7 @@ import tech.units.indriya.ComparableQuantity; /** SQL source for coordinate data */ -public class SqlIdCoordinateSource implements IdCoordinateSource { +public class SqlIdCoordinateSource extends IdCoordinateSource { private static final String WHERE = " WHERE "; /** @@ -48,8 +47,7 @@ public class SqlIdCoordinateSource implements IdCoordinateSource { private final SqlIdCoordinateFactory factory; public SqlIdCoordinateSource( - SqlIdCoordinateFactory factory, String coordinateTableName, SqlDataSource dataSource) - throws SourceException { + SqlIdCoordinateFactory factory, String coordinateTableName, SqlDataSource dataSource) { this.factory = factory; this.dataSource = dataSource; this.coordinateTableName = coordinateTableName; @@ -58,19 +56,6 @@ public SqlIdCoordinateSource( String dbPointColumnName = dataSource.getDbColumnName(factory.getCoordinateField(), coordinateTableName); - // validating table - Try.of(this::getSourceFields, SourceException.class) - .flatMap( - fieldsOpt -> - fieldsOpt - .map( - fields -> - factory - .validate(fields, IdCoordinateInput.class) - .transformF(SourceException::new)) - .orElse(Try.Success.empty())) - .getOrThrow(); - // setup queries this.basicQuery = createBaseQueryString(dataSource.schemaName, coordinateTableName); this.queryForPoint = createQueryForPoint(dbIdColumnName); @@ -94,14 +79,18 @@ public SqlIdCoordinateSource( SqlConnector connector, String schemaName, String coordinateTableName, - SqlIdCoordinateFactory factory) - throws SourceException { + SqlIdCoordinateFactory factory) { this( factory, coordinateTableName, new SqlDataSource(connector, schemaName, new DatabaseNamingStrategy())); } + @Override + public void validate() throws ValidationException { + validate(IdCoordinateInput.class, this::getSourceFields, factory); + } + @Override public Optional> getSourceFields() { return dataSource.getSourceFields(coordinateTableName); diff --git a/src/main/java/edu/ie3/datamodel/io/source/sql/SqlTimeSeriesMappingSource.java b/src/main/java/edu/ie3/datamodel/io/source/sql/SqlTimeSeriesMappingSource.java index 6b37bd173..410290967 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/sql/SqlTimeSeriesMappingSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/sql/SqlTimeSeriesMappingSource.java @@ -12,7 +12,6 @@ import edu.ie3.datamodel.io.naming.DatabaseNamingStrategy; import edu.ie3.datamodel.io.naming.EntityPersistenceNamingStrategy; import edu.ie3.datamodel.io.source.TimeSeriesMappingSource; -import edu.ie3.datamodel.utils.Try; import java.util.Map; import java.util.Optional; import java.util.Set; @@ -27,8 +26,7 @@ public class SqlTimeSeriesMappingSource extends TimeSeriesMappingSource { public SqlTimeSeriesMappingSource( SqlConnector connector, String schemaName, - EntityPersistenceNamingStrategy entityPersistenceNamingStrategy) - throws SourceException { + EntityPersistenceNamingStrategy entityPersistenceNamingStrategy) { this.dataSource = new SqlDataSource( connector, schemaName, new DatabaseNamingStrategy(entityPersistenceNamingStrategy)); @@ -37,18 +35,6 @@ public SqlTimeSeriesMappingSource( this.tableName = entityPersistenceNamingStrategy.getEntityName(MappingEntry.class).orElseThrow(); this.queryFull = createBaseQueryString(schemaName, tableName); - - Try.of(this::getSourceFields, SourceException.class) - .flatMap( - fieldsOpt -> - fieldsOpt - .map( - fields -> - mappingFactory - .validate(fields, MappingEntry.class) - .transformF(SourceException::new)) - .orElse(Try.Success.empty())) - .getOrThrow(); } @Override diff --git a/src/main/java/edu/ie3/datamodel/io/source/sql/SqlTimeSeriesSource.java b/src/main/java/edu/ie3/datamodel/io/source/sql/SqlTimeSeriesSource.java index c2950911d..da725ea04 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/sql/SqlTimeSeriesSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/sql/SqlTimeSeriesSource.java @@ -8,6 +8,7 @@ import static edu.ie3.datamodel.io.source.sql.SqlDataSource.createBaseQueryString; import edu.ie3.datamodel.exceptions.SourceException; +import edu.ie3.datamodel.exceptions.ValidationException; import edu.ie3.datamodel.io.connectors.SqlConnector; import edu.ie3.datamodel.io.factory.timeseries.TimeBasedSimpleValueFactory; import edu.ie3.datamodel.io.naming.DatabaseNamingStrategy; @@ -18,12 +19,14 @@ import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue; import edu.ie3.datamodel.models.value.Value; import edu.ie3.datamodel.utils.TimeSeriesUtils; -import edu.ie3.datamodel.utils.Try; import edu.ie3.util.interval.ClosedInterval; import java.sql.Timestamp; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; -import java.util.*; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; import java.util.stream.Collectors; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,6 +35,7 @@ public class SqlTimeSeriesSource extends TimeSeriesSource { protected static final Logger log = LoggerFactory.getLogger(SqlTimeSeriesSource.class); private final SqlDataSource dataSource; + private final String tableName; private final UUID timeSeriesUuid; @@ -52,29 +56,14 @@ public SqlTimeSeriesSource( SqlDataSource sqlDataSource, UUID timeSeriesUuid, Class valueClass, - TimeBasedSimpleValueFactory factory) - throws SourceException { + TimeBasedSimpleValueFactory factory) { super(valueClass, factory); this.dataSource = sqlDataSource; this.timeSeriesUuid = timeSeriesUuid; - this.valueClass = valueClass; - this.valueFactory = factory; - final ColumnScheme columnScheme = ColumnScheme.parse(valueClass).orElseThrow(); - final String tableName = - sqlDataSource.databaseNamingStrategy.getTimeSeriesEntityName(columnScheme); - - Try.of(() -> dataSource.getSourceFields(tableName), SourceException.class) - .flatMap( - fieldsOpt -> - fieldsOpt - .map( - fields -> - factory.validate(fields, valueClass).transformF(SourceException::new)) - .orElse(Try.Success.empty())) - .getOrThrow(); + this.tableName = sqlDataSource.databaseNamingStrategy.getTimeSeriesEntityName(columnScheme); String dbTimeColumnName = sqlDataSource.getDbColumnName(factory.getTimeFieldString(), tableName); @@ -101,8 +90,7 @@ public SqlTimeSeriesSource( DatabaseNamingStrategy namingStrategy, UUID timeSeriesUuid, Class valueClass, - TimeBasedSimpleValueFactory factory) - throws SourceException { + TimeBasedSimpleValueFactory factory) { this( new SqlDataSource(connector, schemaName, namingStrategy), timeSeriesUuid, @@ -110,6 +98,11 @@ public SqlTimeSeriesSource( factory); } + @Override + public void validate() throws ValidationException { + validate(valueClass, () -> dataSource.getSourceFields(tableName), valueFactory); + } + /** * Factory method to build a source from given meta information * @@ -149,8 +142,7 @@ private static SqlTimeSeriesSource create( DatabaseNamingStrategy namingStrategy, UUID timeSeriesUuid, Class valClass, - DateTimeFormatter dateTimeFormatter) - throws SourceException { + DateTimeFormatter dateTimeFormatter) { TimeBasedSimpleValueFactory valueFactory = new TimeBasedSimpleValueFactory<>(valClass, dateTimeFormatter); return new SqlTimeSeriesSource<>( diff --git a/src/main/java/edu/ie3/datamodel/io/source/sql/SqlWeatherSource.java b/src/main/java/edu/ie3/datamodel/io/source/sql/SqlWeatherSource.java index 37ac91c2e..1973a57ec 100644 --- a/src/main/java/edu/ie3/datamodel/io/source/sql/SqlWeatherSource.java +++ b/src/main/java/edu/ie3/datamodel/io/source/sql/SqlWeatherSource.java @@ -16,9 +16,9 @@ import edu.ie3.datamodel.models.timeseries.individual.IndividualTimeSeries; import edu.ie3.datamodel.models.timeseries.individual.TimeBasedValue; import edu.ie3.datamodel.models.value.WeatherValue; -import edu.ie3.datamodel.utils.Try; import edu.ie3.util.interval.ClosedInterval; -import java.sql.*; +import java.sql.Array; +import java.sql.Timestamp; import java.time.ZonedDateTime; import java.util.*; import java.util.stream.Collectors; @@ -30,7 +30,6 @@ public class SqlWeatherSource extends WeatherSource { private final SqlDataSource dataSource; private static final String WHERE = " WHERE "; - private final String factoryCoordinateFieldName; private final String tableName; /** @@ -56,25 +55,12 @@ public SqlWeatherSource( IdCoordinateSource idCoordinateSource, String schemaName, String weatherTableName, - TimeBasedWeatherValueFactory weatherFactory) - throws SourceException { + TimeBasedWeatherValueFactory weatherFactory) { super(idCoordinateSource, weatherFactory); - this.factoryCoordinateFieldName = weatherFactory.getCoordinateIdFieldString(); + String factoryCoordinateFieldName = weatherFactory.getCoordinateIdFieldString(); this.dataSource = new SqlDataSource(connector, schemaName, new DatabaseNamingStrategy()); this.tableName = weatherTableName; - Try.of(() -> getSourceFields(WeatherValue.class), SourceException.class) - .flatMap( - fieldsOpt -> - fieldsOpt - .map( - fields -> - weatherFactory - .validate(fields, WeatherValue.class) - .transformF(SourceException::new)) - .orElse(Try.Success.empty())) - .getOrThrow(); - String dbTimeColumnName = dataSource.getDbColumnName(weatherFactory.getTimeFieldString(), weatherTableName); String dbCoordinateIdColumnName = @@ -92,7 +78,7 @@ public SqlWeatherSource( } @Override - public Optional> getSourceFields(Class entityClass) { + public Optional> getSourceFields() { return dataSource.getSourceFields(tableName); } diff --git a/src/main/java/edu/ie3/datamodel/utils/QuadFunction.java b/src/main/java/edu/ie3/datamodel/utils/QuadFunction.java new file mode 100644 index 000000000..5ef1ae710 --- /dev/null +++ b/src/main/java/edu/ie3/datamodel/utils/QuadFunction.java @@ -0,0 +1,50 @@ +/* + * © 2024. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation +*/ +package edu.ie3.datamodel.utils; + +import java.util.Objects; +import java.util.function.Function; + +/** + * Enhancement of {@link Function} and {@link java.util.function.BiFunction} that accepts four + * arguments and produces a result. + * + * @param the type of the first argument to the function + * @param the type of the second argument to the function + * @param the type of the third argument to the function + * @param the type of the fourth argument to the function + * @param the type of the result of the function + */ +@FunctionalInterface +public interface QuadFunction { + + /** + * Applies this function to the given arguments. + * + * @param a the first function argument + * @param b the second function argument + * @param c the third function argument + * @param d the fourth function argument + * @return the function result + */ + R apply(A a, B b, C c, D d); + + /** + * Returns a composed function that first applies this function to its input, and then applies the + * {@code after} function to the result. If evaluation of either function throws an exception, it + * is relayed to the caller of the composed function. + * + * @param the type of output of the {@code after} function, and of the composed function + * @param after the function to apply after this function is applied + * @return a composed function that first applies this function and then applies the {@code after} + * function + * @throws NullPointerException if after is null + */ + default QuadFunction andThen(Function after) { + Objects.requireNonNull(after); + return (final A a, final B b, final C c, final D d) -> after.apply(apply(a, b, c, d)); + } +} diff --git a/src/main/java/edu/ie3/datamodel/utils/Try.java b/src/main/java/edu/ie3/datamodel/utils/Try.java index 1b8da0f6b..ffe006407 100644 --- a/src/main/java/edu/ie3/datamodel/utils/Try.java +++ b/src/main/java/edu/ie3/datamodel/utils/Try.java @@ -10,10 +10,12 @@ import edu.ie3.datamodel.exceptions.FailureException; import edu.ie3.datamodel.exceptions.TryException; import java.util.*; +import java.util.function.BiFunction; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; +import org.apache.commons.lang3.tuple.Pair; public abstract class Try { // static utility methods @@ -271,6 +273,39 @@ public abstract Try transformF( public abstract Try transform( Function successFunc, Function failureFunc); + /** + * Method for zipping two tries. + * + * @param that other try + * @return a try of a pair. + * @param type of others data + */ + public Try, E> zip(Try that) { + return zip(that, Pair::of); + } + + /** + * Method for zipping two tries, where one is created using the data of this try. + * + * @param extractor function to create the second try + * @return a try of a pair. + * @param type of others data + */ + public Try, E> zip(Function, Try> extractor) { + return zip(extractor.apply(this)); + } + + /** + * Method for zipping two tries. + * + * @param that other try + * @param zipper function for zipping the two data types + * @return a try of type {@link P}. + * @param type of others data + * @param

type of zipped data + */ + public abstract Try zip(Try that, BiFunction zipper); + /** * Method to convert a {@link Try} object to a common type. * @@ -370,6 +405,11 @@ public Try transform( return new Success<>(successFunc.apply(data)); } + @Override + public Try zip(Try that, BiFunction zipper) { + return that.map(thatData -> zipper.apply(data, thatData)); + } + @Override public U convert(Function successFunc, Function failureFunc) { return successFunc.apply(data); @@ -505,6 +545,11 @@ public Try transform( return Failure.of(failureFunc.apply(exception)); } + @Override + public Try zip(Try that, BiFunction zipper) { + return Failure.of(exception); + } + @Override public U convert(Function successFunc, Function failureFunc) { return failureFunc.apply(exception); diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/AssetEntitySourceTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/AssetEntitySourceTest.groovy new file mode 100644 index 000000000..b92fd09a2 --- /dev/null +++ b/src/test/groovy/edu/ie3/datamodel/io/source/AssetEntitySourceTest.groovy @@ -0,0 +1,112 @@ +/* + * © 2023. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation + */ +package edu.ie3.datamodel.io.source + +import static edu.ie3.test.helper.EntityMap.map + +import edu.ie3.datamodel.io.factory.EntityData +import edu.ie3.datamodel.io.factory.input.ConnectorInputEntityData +import edu.ie3.datamodel.io.factory.input.LineInputFactory +import edu.ie3.datamodel.models.input.OperatorInput +import edu.ie3.datamodel.models.input.connector.LineInput +import edu.ie3.datamodel.utils.Try +import edu.ie3.test.common.GridTestData +import spock.lang.Specification + +class AssetEntitySourceTest extends Specification { + + + def "An AssetEntitySource assetEnricher should work as expected"() { + given: + def entityData = new EntityData(["operator": ""], LineInput) + def operators = map([GridTestData.profBroccoli]) + + when: + def actual = AssetEntitySource.assetEnricher.apply(new Try.Success<>(entityData), operators) + + then: + actual.success + actual.data.get().operatorInput == OperatorInput.NO_OPERATOR_ASSIGNED + } + + def "An AssetEntitySource nodeAssetEnricher should work as expected"() { + given: + def entityData = new EntityData(["operator": "", "node": GridTestData.nodeA.uuid.toString()], LineInput) + def operators = map([GridTestData.profBroccoli]) + def nodes = map([GridTestData.nodeA, GridTestData.nodeB]) + + when: + def actual = AssetEntitySource.nodeAssetEnricher.apply(new Try.Success<>(entityData), operators, nodes) + + then: + actual.success + actual.data.get().node == GridTestData.nodeA + } + + def "An AssetEntitySource connectorEnricher should work as expected"() { + given: + def entityData = new EntityData(["operator": "", "nodeA": GridTestData.nodeA.uuid.toString(), "nodeB": GridTestData.nodeB.uuid.toString()], LineInput) + def operators = map([GridTestData.profBroccoli]) + def nodes = map([GridTestData.nodeA, GridTestData.nodeB]) + + when: + def actual = AssetEntitySource.connectorEnricher.apply(new Try.Success<>(entityData), operators, nodes) + + then: + actual.success + actual.data.get().nodeA == GridTestData.nodeA + actual.data.get().nodeB == GridTestData.nodeB + } + + def "An AssetEntitySource can return a stream of typed connector entities"() { + given: + def parameters = [ + "uuid": "92ec3bcf-1777-4d38-af67-0bf7c9fa73c7", + "id": "test_line_AtoB", + "operator": GridTestData.profBroccoli.uuid.toString(), + "parallelDevices": "2", + "length": "0.003", + "geoPosition": "{ \"type\": \"LineString\", \"coordinates\": [[7.411111, 51.492528], [7.414116, 51.484136]]}", + "nodeA": GridTestData.nodeA.uuid.toString(), + "nodeB": GridTestData.nodeB.uuid.toString(), + "type": GridTestData.lineTypeInputCtoD.uuid.toString() + ] + def source = DummyDataSource.of(parameters) + def operators = map([GridTestData.profBroccoli]) + def nodes = map([ + GridTestData.nodeA, + GridTestData.nodeB + ]) + def types = map([ + GridTestData.lineTypeInputCtoD + ]) + + when: + def actual = AssetEntitySource.getTypedConnectorEntities(LineInput, source, new LineInputFactory(), operators, nodes, types).toList() + + then: + actual.size() == 1 + actual.get(0).with { + // we only want to test of enriching with nodes and type worked as expected + assert it.nodeA == GridTestData.nodeA + assert it.nodeB == GridTestData.nodeB + assert it.type == GridTestData.lineTypeInputCtoD + } + } + + def "An AssetEntitySource can enrich ConnectorInputEntityData with AssetTypeInput correctly"() { + given: + def entityData = new ConnectorInputEntityData(["type": GridTestData.lineTypeInputCtoD.uuid.toString()], LineInput, GridTestData.nodeA, GridTestData.nodeB) + def types = map([GridTestData.lineTypeInputCtoD]) + + when: + def actual = AssetEntitySource.enrichConnector(types).apply(new Try.Success<>(entityData)) + + then: + actual.success + actual.data.get().type == GridTestData.lineTypeInputCtoD + } +} diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/DummyDataSource.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/DummyDataSource.groovy new file mode 100644 index 000000000..af07453c5 --- /dev/null +++ b/src/test/groovy/edu/ie3/datamodel/io/source/DummyDataSource.groovy @@ -0,0 +1,34 @@ +/* + * © 2024. TU Dortmund University, + * Institute of Energy Systems, Energy Efficiency and Energy Economics, + * Research group Distribution grid planning and operation + */ +package edu.ie3.datamodel.io.source + +import edu.ie3.datamodel.exceptions.SourceException +import edu.ie3.datamodel.models.Entity + +import java.util.stream.Stream + +class DummyDataSource implements DataSource { + + private final Map data + + private DummyDataSource(Map data) { + this.data = data + } + + static DummyDataSource of(Map data) { + return new DummyDataSource(data) + } + + @Override + Optional> getSourceFields(Class entityClass) throws SourceException { + return Optional.empty() + } + + @Override + Stream> getSourceData(Class entityClass) throws SourceException { + return Stream.of(data) + } +} 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 f5cbc5bc0..0c46d0c9a 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/EntitySourceTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/EntitySourceTest.groovy @@ -1,232 +1,193 @@ /* - * © 2023. TU Dortmund University, + * © 2024. TU Dortmund University, * Institute of Energy Systems, Energy Efficiency and Energy Economics, * Research group Distribution grid planning and operation */ package edu.ie3.datamodel.io.source +import static edu.ie3.datamodel.io.source.EntitySource.* import static edu.ie3.test.helper.EntityMap.map 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.AssetInputEntityData -import edu.ie3.datamodel.io.factory.input.NodeAssetInputEntityData -import edu.ie3.datamodel.io.factory.input.participant.ChpInputEntityData -import edu.ie3.datamodel.io.factory.input.participant.SystemParticipantTypedEntityData -import edu.ie3.datamodel.io.source.csv.CsvDataSource -import edu.ie3.datamodel.models.input.AssetInput -import edu.ie3.datamodel.models.input.EmInput +import edu.ie3.datamodel.io.factory.input.ConnectorInputEntityData +import edu.ie3.datamodel.io.factory.input.OperatorInputFactory import edu.ie3.datamodel.models.input.NodeInput -import edu.ie3.datamodel.models.input.system.ChpInput -import edu.ie3.datamodel.models.input.system.type.ChpTypeInput -import edu.ie3.datamodel.models.input.thermal.ThermalBusInput -import edu.ie3.datamodel.models.input.thermal.ThermalStorageInput +import edu.ie3.datamodel.models.input.OperatorInput +import edu.ie3.datamodel.models.input.connector.LineInput import edu.ie3.datamodel.utils.Try +import edu.ie3.datamodel.utils.validation.DummyAssetInput import edu.ie3.test.common.GridTestData -import edu.ie3.test.common.SystemParticipantTestData as sptd -import spock.lang.Shared +import org.apache.commons.lang3.tuple.Pair import spock.lang.Specification class EntitySourceTest extends Specification { - private final class DummyEntitySource extends EntitySource { - DummyEntitySource(CsvDataSource dataSource) { - super(dataSource) - } - - @Override - void validate() throws ValidationException { - } - } - - @Shared - DummyEntitySource dummyEntitySource = new DummyEntitySource(Mock(CsvDataSource)) - - def "An EntitySource should enrich entity data with a linked entity, if it was provided"() { + def "An EntitySource can build a map of entities correctly"() { given: - Map parameter = [ - "linked_entity" : GridTestData.nodeA.uuid.toString(), - ] - def entityData = new AssetInputEntityData(parameter, AssetInput) - - Map entityMap = map([GridTestData.nodeA]) + Map parameter = ["uuid": GridTestData.profBroccoli.uuid.toString(), "id": GridTestData.profBroccoli.id] + def source = DummyDataSource.of(parameter) when: - def result = dummyEntitySource.enrichEntityData(entityData, "linked_entity", entityMap, NodeAssetInputEntityData::new) + def actual = getEntities(OperatorInput, source, new OperatorInputFactory()) then: - result == new Try.Success(new NodeAssetInputEntityData(entityData, GridTestData.nodeA)) + actual.size() == 1 + OperatorInput input = actual.get(GridTestData.profBroccoli.uuid) + input.id == GridTestData.profBroccoli.id } - def "An EntitySource trying to enrich entity data should fail, if no matching linked entity was provided"() { + def "An EntitySource throws a SourceException if an entity can not be build"() { given: - Map parameter = [ - "linked_entity" : GridTestData.nodeB.uuid.toString(), - ] - def entityData = new AssetInputEntityData(parameter, AssetInput) - - Map entityMap = map([GridTestData.nodeA]) + Map parameter = ["uuid": GridTestData.profBroccoli.uuid.toString()] + def source = DummyDataSource.of(parameter) when: - def result = dummyEntitySource.enrichEntityData(entityData, "linked_entity", entityMap, NodeAssetInputEntityData::new) + getEntities(OperatorInput, source, new OperatorInputFactory()) then: - result.isFailure() - result.getException().get().message.startsWith("Linked linked_entity with UUID 47d29df0-ba2d-4d23-8e75-c82229c5c758 was not found for entity AssetInputEntityData") + 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." } - def "An EntitySource should enrich entity data with two linked entities, if they are provided"() { + def "An EntitySource can build EntityData correctly"() { given: - Map parameter = [ - "t_bus" : sptd.thermalBus.uuid.toString(), - "t_storage" : sptd.thermalStorage.uuid.toString() - ] - def entityData = new SystemParticipantTypedEntityData(parameter, ChpInput, sptd.participantNode, null, sptd.chpTypeInput) - - Map busMap = map([sptd.thermalBus]) - Map storageMap = map([sptd.thermalStorage]) + Map parameter = ["operator": GridTestData.profBroccoli.uuid.toString()] + def source = DummyDataSource.of(parameter) when: - def result = dummyEntitySource.enrichEntityData(entityData, "t_bus", busMap, "t_storage", storageMap, ChpInputEntityData::new) + def actual = buildEntityData(DummyAssetInput, source).toList() then: - result == new Try.Success(new ChpInputEntityData(entityData, sptd.thermalBus, sptd.thermalStorage)) + actual.size() == 1 + actual.get(0).success } - def "An EntitySource trying to enrich entity data should fail, if one of two linked entities is not provided"() { + def "An EntitySource can enrich and build EntityData correctly"() { given: - Map parameter = [ - "t_bus" : sptd.thermalBus.uuid.toString(), - "t_storage" : "8851813b-3a7d-4fee-874b-4df9d724e4b4" - ] - def entityData = new SystemParticipantTypedEntityData(parameter, ChpInput, sptd.participantNode, null, sptd.chpTypeInput) - - Map busMap = map([sptd.thermalBus]) - Map storageMap = map([sptd.thermalStorage]) + Map parameter = ["operator": GridTestData.profBroccoli.uuid.toString()] + def entityMap = map([GridTestData.profBroccoli]) + def source = DummyDataSource.of(parameter) + def fcn = enrich("operator", entityMap, AssetInputEntityData::new) when: - def result = dummyEntitySource.enrichEntityData(entityData, "t_bus", busMap, "t_storage", storageMap, ChpInputEntityData::new) + def actual = buildEntityData(DummyAssetInput, source, fcn).toList() then: - result.isFailure() - result.getException().get().message.startsWith("Linked t_storage with UUID 8851813b-3a7d-4fee-874b-4df9d724e4b4 was not found for entity SystemParticipantTypedEntityData") + actual.size() == 1 + actual.get(0).success + def data = actual.get(0).data.get() + + data.targetClass == DummyAssetInput + data.fieldsToValues.size() == 0 } - def "An EntitySource should find a linked entity, if it was provided"() { + def "An EntitySource can enrich EntityData with default fallback"() { given: - Map parameter = [ - "linked_entity" : sptd.emInput.uuid.toString(), - ] - def entityData = new EntityData(parameter, AssetInput) - - Map entityMap = map([sptd.emInput]) + def entityMap = map([GridTestData.profBroccoli]) + def entityData1 = new EntityData(["operator": GridTestData.profBroccoli.uuid.toString()], NodeInput) + def entityData2 = new EntityData(["operator": ""], NodeInput) + def fcn = enrichWithDefault("operator", entityMap, OperatorInput.NO_OPERATOR_ASSIGNED, AssetInputEntityData::new) when: - def result = dummyEntitySource.getLinkedEntity(entityData, "linked_entity", entityMap) + def enrichedWithEntity = fcn.apply(new Try.Success<>(entityData1)) + def enrichedWithDefault = fcn.apply(new Try.Success<>(entityData2)) then: - result == new Try.Success(sptd.emInput) + enrichedWithEntity.success + enrichedWithEntity.data.get().operatorInput == GridTestData.profBroccoli + + enrichedWithDefault.success + enrichedWithDefault.data.get().operatorInput == OperatorInput.NO_OPERATOR_ASSIGNED } - def "An EntitySource trying to find a linked entity should fail, if no matching linked entity was provided"() { + def "An EntitySource can enrich EntityData"() { given: - Map parameter = [ - "linked_entity" : sptd.parentEm.uuid.toString(), - ] - def entityData = new EntityData(parameter, AssetInput) - - Map entityMap = map([sptd.emInput]) + def entityMap = map([GridTestData.profBroccoli]) + def entityData = new EntityData(["operator": GridTestData.profBroccoli.uuid.toString()], NodeInput) + def fcn = enrich("operator", entityMap, AssetInputEntityData::new) when: - def result = dummyEntitySource.getLinkedEntity(entityData, "linked_entity", entityMap) + def enrichedData = fcn.apply(new Try.Success<>(entityData)) then: - result.isFailure() - result.getException().get().message == "Linked linked_entity with UUID 897bfc17-8e54-43d0-8d98-740786fd94dd was not found for entity EntityData{fieldsToAttributes={linked_entity=897bfc17-8e54-43d0-8d98-740786fd94dd}, targetClass=class edu.ie3.datamodel.models.input.AssetInput}" + enrichedData.success + enrichedData.data.get().operatorInput == GridTestData.profBroccoli } - def "An EntitySource trying to find a linked entity should fail, if corresponding UUID is malformed"() { + def "An EntitySource can enrich EntityData with two entities"() { given: - Map parameter = [ - "linked_entity" : "not-a-uuid", - ] - def entityData = new EntityData(parameter, AssetInput) - - Map entityMap = map([sptd.emInput]) + def entityMap = map([GridTestData.nodeA, GridTestData.nodeB]) + def entityData = new AssetInputEntityData(["nodeA": GridTestData.nodeA.uuid.toString(), "nodeB": GridTestData.nodeB.uuid.toString()], LineInput) + def fcn = biEnrich("nodeA", entityMap, "nodeB", entityMap, ConnectorInputEntityData::new) when: - def result = dummyEntitySource.getLinkedEntity(entityData, "linked_entity", entityMap) + def enrichedData = fcn.apply(new Try.Success<>(entityData)) then: - result.isFailure() - result.getException().get().message == "Extracting UUID field linked_entity from entity data EntityData{fieldsToAttributes={linked_entity=not-a-uuid}, targetClass=class edu.ie3.datamodel.models.input.AssetInput} failed." + enrichedData.success + enrichedData.data.get().nodeA == GridTestData.nodeA + enrichedData.data.get().nodeB == GridTestData.nodeB } - def "An EntitySource should optionally enrich entity data with a linked entity, if it was provided"() { + def "An EntitySource's builder function should work as expected"() { given: - Map parameter = [ - "linked_entity" : GridTestData.nodeA.uuid.toString(), - ] - def entityData = new AssetInputEntityData(parameter, AssetInput) - - Map entityMap = map([GridTestData.nodeA]) + def entityData = new EntityData(["operator": ""], NodeInput) + def pair = Pair.of(entityData, GridTestData.profBroccoli) + def fcn = enrichFunction(["operator"], AssetInputEntityData::new) when: - def result = dummyEntitySource.optionallyEnrichEntityData(entityData, "linked_entity", entityMap, GridTestData.nodeB, NodeAssetInputEntityData::new) + def result = fcn.apply(pair) then: - result == new Try.Success(new NodeAssetInputEntityData(entityData, GridTestData.nodeA)) + result.fieldsToValues.isEmpty() + result.operatorInput == GridTestData.profBroccoli } - def "An EntitySource should (optionally) enrich entity data with the default entity, if no linked entity is specified"() { + def "An EntitySource can extract an Entity from a map correctly if a field name is given"() { given: - Map parameter = [ - "linked_entity" : "", - ] - def entityData = new AssetInputEntityData(parameter, AssetInput) - - Map entityMap = map([GridTestData.nodeA]) + def entityData = new EntityData(["operator": GridTestData.profBroccoli.uuid.toString()], NodeInput) + def entityMap = map([GridTestData.profBroccoli]) when: - def result = dummyEntitySource.optionallyEnrichEntityData(entityData, "linked_entity", entityMap, GridTestData.nodeB, NodeAssetInputEntityData::new) + def actual = extractFunction(new Try.Success<>(entityData), "operator", entityMap) then: - result == new Try.Success(new NodeAssetInputEntityData(entityData, GridTestData.nodeB)) + actual.success + actual.data.get() == GridTestData.profBroccoli } - def "An EntitySource trying to optionally find a linked entity should fail, if no matching linked entity was provided"() { + def "An EntitySource returns a failure if an entity can not be extracted from a given map"() { given: - Map parameter = [ - "linked_entity" : "4ca90220-74c2-4369-9afa-a18bf068840e", - ] - def entityData = new AssetInputEntityData(parameter, AssetInput) - - Map entityMap = map([GridTestData.nodeA]) + def entityData = new EntityData(fieldsToAttributes, NodeInput) when: - def result = dummyEntitySource.optionallyEnrichEntityData(entityData, "linked_entity", entityMap, GridTestData.nodeB, NodeAssetInputEntityData::new) + def actual = extractFunction(new Try.Success<>(entityData), "operator", entityMap) then: - result.isFailure() - result.getException().get().message.startsWith("Linked linked_entity with UUID 4ca90220-74c2-4369-9afa-a18bf068840e was not found for entity AssetInputEntityData{fieldsToValues={linked_entity=4ca90220-74c2-4369-9afa-a18bf068840e}, targetClass=class edu.ie3.datamodel.models.input.AssetInput") + actual.failure + actual.exception.get().class == SourceException + actual.exception.get().message.contains(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." } - - def "An EntitySource trying to optionally find a linked entity should fail, if corresponding UUID is malformed"() { + def "An EntitySource returns a failure if a given map does not contain the given uuid"() { given: - Map parameter = [ - "linked_entity" : "not-a-uuid", - ] - def entityData = new AssetInputEntityData(parameter, AssetInput) - - Map entityMap = map([GridTestData.nodeA]) + def uuid = GridTestData.profBroccoli.uuid + def entityMap = map([ + OperatorInput.NO_OPERATOR_ASSIGNED + ]) when: - def result = dummyEntitySource.optionallyEnrichEntityData(entityData, "linked_entity", entityMap, GridTestData.nodeB, NodeAssetInputEntityData::new) + def actual = extractFunction(uuid, entityMap) then: - result.isFailure() - result.getException().get().message == "Exception while trying to parse UUID of field \"linked_entity\" with value \"not-a-uuid\"" + actual.failure + actual.exception.get().message == "Entity with uuid f15105c4-a2de-4ab8-a621-4bc98e372d92 was not provided." } } diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/IdCoordinateSourceMock.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/IdCoordinateSourceMock.groovy index b6e2a909a..7d005677e 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/IdCoordinateSourceMock.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/IdCoordinateSourceMock.groovy @@ -6,13 +6,14 @@ package edu.ie3.datamodel.io.source import edu.ie3.datamodel.exceptions.SourceException +import edu.ie3.datamodel.exceptions.ValidationException import edu.ie3.util.geo.CoordinateDistance import org.locationtech.jts.geom.Point import tech.units.indriya.ComparableQuantity import javax.measure.quantity.Length -class IdCoordinateSourceMock implements IdCoordinateSource { +class IdCoordinateSourceMock extends IdCoordinateSource { @Override Optional> getSourceFields() throws SourceException { @@ -53,4 +54,8 @@ class IdCoordinateSourceMock implements IdCoordinateSource { List findCornerPoints(Point coordinate, ComparableQuantity distance) { return Collections.emptyList() } + + @Override + void validate() throws ValidationException { + } } 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 57e7a5566..aeb9f8829 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/SystemParticipantSourceTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/SystemParticipantSourceTest.groovy @@ -7,115 +7,45 @@ package edu.ie3.datamodel.io.source import static edu.ie3.test.helper.EntityMap.map -import edu.ie3.datamodel.io.factory.input.NodeAssetInputEntityData -import edu.ie3.datamodel.io.factory.input.participant.ChpInputEntityData -import edu.ie3.datamodel.io.factory.input.participant.HpInputEntityData +import edu.ie3.datamodel.io.factory.input.ConnectorInputEntityData import edu.ie3.datamodel.io.factory.input.participant.SystemParticipantEntityData -import edu.ie3.datamodel.io.factory.input.participant.SystemParticipantTypedEntityData -import edu.ie3.datamodel.models.input.system.ChpInput -import edu.ie3.datamodel.models.input.system.HpInput -import edu.ie3.datamodel.models.input.thermal.ThermalBusInput -import edu.ie3.datamodel.models.input.thermal.ThermalStorageInput +import edu.ie3.datamodel.models.input.OperatorInput +import edu.ie3.datamodel.models.input.connector.LineInput +import edu.ie3.datamodel.models.input.system.EvInput import edu.ie3.datamodel.utils.Try -import edu.ie3.test.common.SystemParticipantTestData +import edu.ie3.test.common.GridTestData +import edu.ie3.test.common.SystemParticipantTestData as sptd import spock.lang.Specification -import java.util.stream.Stream - class SystemParticipantSourceTest extends Specification { - def "A SystemParticipantSource should build system participant entity from valid and invalid input data as expected"() { - given: - def nodeAssetInputEntityData = Stream.of(new Try.Success<>(new NodeAssetInputEntityData(fieldsToAttributes, ChpInput, SystemParticipantTestData.chpInput.operator, SystemParticipantTestData.chpInput.node))) - - when: - def sysPartEntityDataStream = SystemParticipantSource.systemParticipantEntityStream(nodeAssetInputEntityData, map(emUnits)) - - then: - def element = sysPartEntityDataStream.findFirst().get() - element.success == resultIsPresent - element.data.ifPresent({ - typedEntityData -> - assert (typedEntityData == resultData) - }) - - where: - emUnits | fieldsToAttributes || resultIsPresent || resultData - [] | ["em": "977157f4-25e5-4c72-bf34-440edc778792"] || false || null - [SystemParticipantTestData.emInput] | ["bla": "foo"] || true || new SystemParticipantEntityData(["bla": "foo"], ChpInput, SystemParticipantTestData.chpInput.operator, SystemParticipantTestData.chpInput.node, null) - [SystemParticipantTestData.emInput] | [:] || true || new SystemParticipantEntityData([:], ChpInput, SystemParticipantTestData.chpInput.operator, SystemParticipantTestData.chpInput.node, null) - [SystemParticipantTestData.emInput] | ["em": "977157f4-25e5-4c72-bf34-440edc778793"] || false || null - [SystemParticipantTestData.emInput] | ["em": "977157f4-25e5-4c72-bf34-440edc778792"] || true || new SystemParticipantEntityData([:], ChpInput, SystemParticipantTestData.chpInput.operator, SystemParticipantTestData.chpInput.node, SystemParticipantTestData.emInput) - } - - def "A SystemParticipantSource should build typed entity from valid and invalid input data as expected"() { + def "An SystemParticipantSource participantEnricher should work as expected"() { given: - def systemParticipantEntityData = Stream.of(new Try.Success<>(new SystemParticipantEntityData(fieldsToAttributes, ChpInput, SystemParticipantTestData.chpInput.operator, SystemParticipantTestData.chpInput.node, null))) + def entityData = new ConnectorInputEntityData(["operators": "", "node": sptd.participantNode.uuid.toString(), "em": 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]) when: - def typedEntityDataStream = SystemParticipantSource.typedSystemParticipantEntityStream(systemParticipantEntityData, map(types)) + def actual = SystemParticipantSource.participantEnricher.apply(new Try.Success<>(entityData), operators, nodes, emUnits) then: - def element = typedEntityDataStream.findFirst().get() - element.success == resultIsPresent - element.data.ifPresent({ - typedEntityData -> - assert (typedEntityData == resultData) - }) - - where: - types | fieldsToAttributes || resultIsPresent || resultData - [] | ["type": "5ebd8f7e-dedb-4017-bb86-6373c4b68eb8"] || false || null - [SystemParticipantTestData.chpTypeInput] | ["bla": "foo"] || false || null - [SystemParticipantTestData.chpTypeInput] | [:] || false || null - [SystemParticipantTestData.chpTypeInput] | ["type": "5ebd8f7e-dedb-4017-bb86-6373c4b68eb9"] || false || null - [SystemParticipantTestData.chpTypeInput] | ["type": "5ebd8f7e-dedb-4017-bb86-6373c4b68eb8"] || true || new SystemParticipantTypedEntityData<>([:], ChpInput, SystemParticipantTestData.chpInput.operator, SystemParticipantTestData.chpInput.node, null, SystemParticipantTestData.chpTypeInput) + actual.success + actual.data.get().operatorInput == OperatorInput.NO_OPERATOR_ASSIGNED + actual.data.get().node == sptd.participantNode + actual.data.get().em == Optional.of(sptd.emInput) } - def "A SystemParticipantSource should build hp input entity from valid and invalid input data as expected"() { + def "An SystemParticipantSource can enrich SystemParticipantEntityData with SystemParticipantTypeInput correctly"() { given: - def sysPartTypedEntityData = Stream.of(new Try.Success<>(new SystemParticipantTypedEntityData<>(fieldsToAttributes, HpInput, SystemParticipantTestData.hpInput.operator, SystemParticipantTestData.hpInput.node, SystemParticipantTestData.emInput, SystemParticipantTestData.hpTypeInput))) + def entityData = new SystemParticipantEntityData(["type": sptd.evTypeInput.uuid.toString()], EvInput, sptd.evInput.node, sptd.emInput) + def types = map([sptd.evTypeInput]) when: - def hpInputEntityDataOpt = SystemParticipantSource.hpEntityStream(sysPartTypedEntityData, map(thermalBuses)) + def actual = SystemParticipantSource.enrichTypes(types).apply(new Try.Success<>(entityData)) then: - def element = hpInputEntityDataOpt.findFirst().get() - element.success == resultIsPresent - element.data.ifPresent({ - hpInputEntityData -> - assert (hpInputEntityData == resultData) - }) - - where: - thermalBuses | fieldsToAttributes || resultIsPresent || resultData - [] | ["thermalBus": "0d95d7f2-49fb-4d49-8636-383a5220384e"] || false || null - [SystemParticipantTestData.hpInput.thermalBus] | ["bla": "foo"] || false || null - [SystemParticipantTestData.hpInput.thermalBus] | [:] || false || null - [SystemParticipantTestData.hpInput.thermalBus] | ["thermalBus": "0d95d7f2-49fb-4d49-8636-383a5220384f"] || false || null - [SystemParticipantTestData.hpInput.thermalBus] | ["thermalBus": "0d95d7f2-49fb-4d49-8636-383a5220384e"] || true || new HpInputEntityData([:], SystemParticipantTestData.hpInput.operator, SystemParticipantTestData.hpInput.node, SystemParticipantTestData.emInput, SystemParticipantTestData.hpTypeInput, SystemParticipantTestData.hpInput.thermalBus) - } - - def "A SystemParticipantSource should build chp input entity from valid and invalid input data as expected"(List thermalStorages, List thermalBuses, Map fieldsToAttributes, boolean resultIsPresent, ChpInputEntityData resultData) { - given: - def sysPartTypedEntityData = Stream.of(new Try.Success<>(new SystemParticipantTypedEntityData<>(fieldsToAttributes, ChpInput, SystemParticipantTestData.chpInput.operator, SystemParticipantTestData.chpInput.node, SystemParticipantTestData.emInput, SystemParticipantTestData.chpTypeInput))) - - when: - def hpInputEntityDataOpt = SystemParticipantSource.chpEntityStream(sysPartTypedEntityData, map(thermalStorages), map(thermalBuses)) - - then: - def element = hpInputEntityDataOpt.findFirst().get() - element.success == resultIsPresent - element.data.ifPresent({ - hpInputEntityData -> - assert (hpInputEntityData == resultData) - }) - - where: - thermalStorages | thermalBuses | fieldsToAttributes || resultIsPresent | resultData - [] | [] | ["thermalBus": "0d95d7f2-49fb-4d49-8636-383a5220384e", "thermalStorage": "8851813b-3a7d-4fee-874b-4df9d724e4b3"] || false | null - [SystemParticipantTestData.chpInput.thermalStorage] | [SystemParticipantTestData.chpInput.thermalBus] | ["bla": "foo"] || false | null - [SystemParticipantTestData.chpInput.thermalStorage] | [SystemParticipantTestData.chpInput.thermalBus] | [:] || false | null - [SystemParticipantTestData.chpInput.thermalStorage] | [SystemParticipantTestData.chpInput.thermalBus] | ["thermalBus": "0d95d7f2-49fb-4d49-8636-383a5220384e", "thermalStorage": "8851813b-3a7d-4fee-874b-4df9d724e4b3"] || true | new ChpInputEntityData([:], SystemParticipantTestData.chpInput.operator, SystemParticipantTestData.chpInput.node, SystemParticipantTestData.emInput, SystemParticipantTestData.chpTypeInput, SystemParticipantTestData.chpInput.thermalBus, SystemParticipantTestData.chpInput.thermalStorage) + actual.success + actual.data.get().typeInput == sptd.evTypeInput } } diff --git a/src/test/groovy/edu/ie3/datamodel/io/source/ThermalSourceTest.groovy b/src/test/groovy/edu/ie3/datamodel/io/source/ThermalSourceTest.groovy index 224773490..99f771ff9 100644 --- a/src/test/groovy/edu/ie3/datamodel/io/source/ThermalSourceTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/io/source/ThermalSourceTest.groovy @@ -5,58 +5,33 @@ */ package edu.ie3.datamodel.io.source + import static edu.ie3.test.helper.EntityMap.map -import edu.ie3.datamodel.io.factory.input.AssetInputEntityData -import edu.ie3.datamodel.io.factory.input.ThermalUnitInputEntityData +import edu.ie3.datamodel.io.factory.EntityData import edu.ie3.datamodel.models.input.OperatorInput import edu.ie3.datamodel.models.input.thermal.ThermalBusInput -import edu.ie3.datamodel.models.input.thermal.ThermalUnitInput +import edu.ie3.datamodel.models.input.thermal.ThermalHouseInput import edu.ie3.datamodel.utils.Try import spock.lang.Specification -import java.util.stream.Collectors -import java.util.stream.Stream - class ThermalSourceTest extends Specification { - def "A ThermalSource should build thermal unit input entity from valid and invalid input data as expected"() { + def "A ThermalSource thermalUnitEnricher should work as expected"() { given: - def operator = new OperatorInput(UUID.fromString("8f9682df-0744-4b58-a122-f0dc730f6510"), "testOperator") - def validFieldsToAttributes = [ - "uuid" : "717af017-cc69-406f-b452-e022d7fb516a", - "id" : "test_thermal_unit", - "operator" : "8f9682df-0744-4b58-a122-f0dc730f6510", - "operatesFrom" : "2020-03-24 15:11:31", - "operatesUntil" : "2020-03-25 15:11:31", - "thermalBus" : "0d95d7f2-49fb-4d49-8636-383a5220384e" - ] - def assetInputEntityData = Stream.of(new Try.Success(new AssetInputEntityData(validFieldsToAttributes, ThermalUnitInput, operator))) + def bus = new ThermalBusInput(UUID.fromString("0d95d7f2-49fb-4d49-8636-383a5220384e"), "test_thermal_bus") + def entityData = new EntityData(["operators": "", "thermalbus": "0d95d7f2-49fb-4d49-8636-383a5220384e"], ThermalHouseInput) + def operators = map([OperatorInput.NO_OPERATOR_ASSIGNED]) + def buses = map([bus]) when: - def resultingDataOpt = ThermalSource.thermalUnitInputEntityDataStream(assetInputEntityData, map(thermalBuses)).collect(Collectors.toList()) + def actual = ThermalSource.thermalUnitEnricher.apply(new Try.Success<>(entityData), operators, buses) then: - resultingDataOpt.size() == 1 - resultingDataOpt.first().data.present == resultIsPresent - resultingDataOpt.first().data.ifPresent({ resultingData -> - assert (resultingData == expectedThermalUnitInputEntityData) - }) - - where: - thermalBuses || resultIsPresent | expectedThermalUnitInputEntityData - [] || false | null // thermal buses are not present -> method should return an empty optional -> do not check for thermal unit entity data - [ - new ThermalBusInput(UUID.fromString("0d95d7f2-49fb-4d49-8636-383a5220384e"), "test_thermal_bus") - ] || true | - new ThermalUnitInputEntityData([ - "uuid" : "717af017-cc69-406f-b452-e022d7fb516a", - "id" : "test_thermal_unit", - "operator" : "8f9682df-0744-4b58-a122-f0dc730f6510", - "operatesFrom" : "2020-03-24 15:11:31", - "operatesUntil": "2020-03-25 15:11:31"], - ThermalUnitInput, - new OperatorInput(UUID.fromString("8f9682df-0744-4b58-a122-f0dc730f6510"), "testOperator"), - new ThermalBusInput(UUID.fromString("0d95d7f2-49fb-4d49-8636-383a5220384e"), "test_thermal_bus")) + actual.success + actual.data.get().with { + assert it.operatorInput == OperatorInput.NO_OPERATOR_ASSIGNED + assert it.busInput == bus + } } } 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 61c7bc74e..9a7b15fc5 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,7 @@ class CsvGraphicSourceTest extends Specification implements CsvTestDataMeta { Exception ex = graphicElements.exception.get() ex.class == GraphicSourceException - ex.message.startsWith("1error(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: Linked line with UUID 91ec3bcf-1777-4d38-af67-0bf7c9fa73c7 was not found for entity") + 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.") } 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 ee1750e35..b3ad25998 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 @@ -5,20 +5,11 @@ */ package edu.ie3.datamodel.io.source.csv -import static edu.ie3.test.helper.EntityMap.map - import edu.ie3.datamodel.exceptions.SourceException -import edu.ie3.datamodel.io.factory.input.AssetInputEntityData -import edu.ie3.datamodel.io.factory.input.ConnectorInputEntityData -import edu.ie3.datamodel.io.factory.input.Transformer3WInputEntityData -import edu.ie3.datamodel.io.factory.input.TypedConnectorInputEntityData import edu.ie3.datamodel.io.source.RawGridSource import edu.ie3.datamodel.io.source.TypeSource 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.Transformer3WInput import edu.ie3.datamodel.models.input.container.RawGridElements import edu.ie3.datamodel.utils.Try import edu.ie3.test.common.GridTestData @@ -26,9 +17,6 @@ import edu.ie3.test.common.GridTestData as rgtd import spock.lang.Shared import spock.lang.Specification -import java.util.stream.Collectors -import java.util.stream.Stream - class CsvRawGridSourceTest extends Specification implements CsvTestDataMeta { @Shared RawGridSource source @@ -38,303 +26,6 @@ class CsvRawGridSourceTest extends Specification implements CsvTestDataMeta { source = new RawGridSource(typeSource, new CsvDataSource(csvSep, gridDefaultFolderPath, fileNamingStrategy)) } - def "The CsvRawGridSource is able to convert single valid AssetInputEntityData to ConnectorInputEntityData"() { - given: "valid input data" - def fieldsToAttributes = [ - "uuid" : "5dc88077-aeb6-4711-9142-db57287640b1", - "id" : "test_switch_AtoB", - "operator" : "8f9682df-0744-4b58-a122-f0dc730f6510", - "operatesFrom" : "2020-03-24T15:11:31Z", - "operatesUntil" : "2020-03-24T15:11:31Z", - "nodeA" : "4ca90220-74c2-4369-9afa-a18bf068840d", - "nodeB" : "47d29df0-ba2d-4d23-8e75-c82229c5c758", - "closed" : "true" - ] - - def expectedFieldsToAttributes = [ - "uuid" : "5dc88077-aeb6-4711-9142-db57287640b1", - "id" : "test_switch_AtoB", - "operator" : "8f9682df-0744-4b58-a122-f0dc730f6510", - "operatesFrom" : "2020-03-24T15:11:31Z", - "operatesUntil" : "2020-03-24T15:11:31Z", - "closed" : "true" - ] - - def validAssetEntityInputData = Stream.of(Try.Success.of(new AssetInputEntityData(fieldsToAttributes, SwitchInput))) - - def nodes = map([rgtd.nodeA, rgtd.nodeB]) - - when: "the source tries to convert it" - def connectorDataOption = source.untypedConnectorEntityDataStream(validAssetEntityInputData, nodes) - - then: "everything is fine" - connectorDataOption.forEach { actualTry -> - assert actualTry.isSuccess() - actualTry.data.get().with { - assert fieldsToValues == expectedFieldsToAttributes - assert targetClass == SwitchInput - assert nodeA == rgtd.nodeA - assert nodeB == rgtd.nodeB - } - } - } - - def "The CsvRawGridSource is NOT able to convert single invalid AssetInputEntityData to ConnectorInputEntityData"() { - given: "invalid input data" - def fieldsToAttributes = [ - "uuid" : "5dc88077-aeb6-4711-9142-db57287640b1", - "id" : "test_switch_AtoB", - "operator" : "8f9682df-0744-4b58-a122-f0dc730f6510", - "operatesFrom" : "2020-03-24T15:11:31Z", - "operatesUntil" : "2020-03-24T15:11:31Z", - "nodeA" : "4ca90220-74c2-4369-9afa-a18bf068840d", - "nodeB" : "620d35fc-34f8-48af-8020-3897fe75add7", - "closed" : "true" - ] - - def validAssetEntityInputData = Stream.of(Try.Success.of(new AssetInputEntityData(fieldsToAttributes, SwitchInput))) - - def nodes = map([rgtd.nodeA, rgtd.nodeB]) - - when: "the source tries to convert it" - def connectorDataOption = source.untypedConnectorEntityDataStream(validAssetEntityInputData, nodes) - - then: "it returns a Failure" - connectorDataOption.allMatch(Try::isFailure) - } - - - def "The CsvRawGridSource is able to convert a stream of valid AssetInputEntityData to ConnectorInputEntityData"() { - given: "valid input data" - def validStream = Stream.of( - Try.Success.of(new AssetInputEntityData([ - "uuid" : "5dc88077-aeb6-4711-9142-db57287640b1", - "id" : "test_switch_AtoB", - "operator" : "8f9682df-0744-4b58-a122-f0dc730f6510", - "operatesFrom" : "2020-03-24T15:11:31Z", - "operatesUntil" : "2020-03-24T15:11:31Z", - "nodeA" : "4ca90220-74c2-4369-9afa-a18bf068840d", - "nodeB" : "47d29df0-ba2d-4d23-8e75-c82229c5c758", - "closed" : "true" - ], SwitchInput)), - Try.Success.of(new AssetInputEntityData([ - "uuid" : "91ec3bcf-1777-4d38-af67-0bf7c9fa73c7", - "id" : "test_lineCtoD", - "operator" : "8f9682df-0744-4b58-a122-f0dc730f6510", - "operatesFrom" : "2020-03-24T15:11:31Z", - "operatesUntil" : "2020-03-24T15:11:31Z", - "nodeA" : "bd837a25-58f3-44ac-aa90-c6b6e3cd91b2", - "nodeB" : "6e0980e0-10f2-4e18-862b-eb2b7c90509b", - "parallelDevices" : "2", - "type" : "3bed3eb3-9790-4874-89b5-a5434d408088", - "length" : "0.003", - "geoPosition" : "{ \"type\": \"LineString\", \"coordinates\": [[7.411111, 51.492528], [7.414116, 51.484136]]}", - "olmCharacteristic" : "olm:{(0.0,1.0)}" - ], - LineInput) - )) - - def expectedSet = [ - new ConnectorInputEntityData([ - "uuid" : "5dc88077-aeb6-4711-9142-db57287640b1", - "id" : "test_switch_AtoB", - "operator" : "8f9682df-0744-4b58-a122-f0dc730f6510", - "operatesFrom" : "2020-03-24T15:11:31Z", - "operatesUntil" : "2020-03-24T15:11:31Z", - "closed" : "true" - ], - SwitchInput, - rgtd.nodeA, - rgtd.nodeB - ), - new ConnectorInputEntityData([ - "uuid" : "91ec3bcf-1777-4d38-af67-0bf7c9fa73c7", - "id" : "test_lineCtoD", - "operator" : "8f9682df-0744-4b58-a122-f0dc730f6510", - "operatesFrom" : "2020-03-24T15:11:31Z", - "operatesUntil" : "2020-03-24T15:11:31Z", - "parallelDevices" : "2", - "type" : "3bed3eb3-9790-4874-89b5-a5434d408088", - "length" : "0.003", - "geoPosition" : "{ \"type\": \"LineString\", \"coordinates\": [[7.411111, 51.492528], [7.414116, 51.484136]]}", - "olmCharacteristic" : "olm:{(0.0,1.0)}" - ], - LineInput, - rgtd.nodeC, - rgtd.nodeD - ) - ] as Set - - def nodes = map([ - rgtd.nodeA, - rgtd.nodeB, - rgtd.nodeC, - rgtd.nodeD - ]) - - when: "the source tries to convert it" - def actualSet = source.untypedConnectorEntityDataStream(validStream, nodes).collect(Collectors.toSet()) - - then: "everything is fine" - actualSet.size() == expectedSet.size() - def result = Try.scanCollection(actualSet, List) - - result.success - result.data.get().toList().containsAll(expectedSet) - } - - def "The CsvRawGridSource is able to convert a stream of valid ConnectorInputEntityData to TypedConnectorInputEntityData"() { - given: "valid input data" - def validStream = Stream.of(Try.Success.of( - new ConnectorInputEntityData([ - "uuid" : "91ec3bcf-1777-4d38-af67-0bf7c9fa73c7", - "id" : "test_lineCtoD", - "operator" : "8f9682df-0744-4b58-a122-f0dc730f6510", - "operatesFrom" : "2020-03-24T15:11:31Z", - "operatesUntil" : "2020-03-24T15:11:31Z", - "parallelDevices" : "2", - "type" : "3bed3eb3-9790-4874-89b5-a5434d408088", - "length" : "0.003", - "geoPosition" : "{ \"type\": \"LineString\", \"coordinates\": [[7.411111, 51.492528], [7.414116, 51.484136]]}", - "olmCharacteristic" : "olm:{(0.0,1.0)}" - ], - LineInput, - rgtd.nodeC, - rgtd.nodeD - )), - Try.Success.of(new ConnectorInputEntityData([ - "uuid" : "92ec3bcf-1777-4d38-af67-0bf7c9fa73c7", - "id" : "test_line_AtoB", - "operator" : "8f9682df-0744-4b58-a122-f0dc730f6510", - "operatesFrom" : "2020-03-24T15:11:31Z", - "operatesUntil" : "2020-03-24T15:11:31Z", - "parallelDevices" : "2", - "type" : "3bed3eb3-9790-4874-89b5-a5434d408088", - "length" : "0.003", - "geoPosition" : "{ \"type\": \"LineString\", \"coordinates\": [[7.411111, 51.492528], [7.414116, 51.484136]]}", - "olmCharacteristic" : "olm:{(0.0,1.0)}" - ], LineInput, - rgtd.nodeA, - rgtd.nodeB - ))) as Stream> - - def expectedSet = [ - new TypedConnectorInputEntityData<>([ - "uuid" : "91ec3bcf-1777-4d38-af67-0bf7c9fa73c7", - "id" : "test_lineCtoD", - "operator" : "8f9682df-0744-4b58-a122-f0dc730f6510", - "operatesFrom" : "2020-03-24T15:11:31Z", - "operatesUntil" : "2020-03-24T15:11:31Z", - "parallelDevices" : "2", - "length" : "0.003", - "geoPosition" : "{ \"type\": \"LineString\", \"coordinates\": [[7.411111, 51.492528], [7.414116, 51.484136]]}", - "olmCharacteristic" : "olm:{(0.0,1.0)}" - ], - LineInput, - rgtd.nodeC, - rgtd.nodeD, - rgtd.lineTypeInputCtoD - ), - new TypedConnectorInputEntityData<>([ - "uuid" : "92ec3bcf-1777-4d38-af67-0bf7c9fa73c7", - "id" : "test_line_AtoB", - "operator" : "8f9682df-0744-4b58-a122-f0dc730f6510", - "operatesFrom" : "2020-03-24T15:11:31Z", - "operatesUntil" : "2020-03-24T15:11:31Z", - "parallelDevices" : "2", - "length" : "0.003", - "geoPosition" : "{ \"type\": \"LineString\", \"coordinates\": [[7.411111, 51.492528], [7.414116, 51.484136]]}", - "olmCharacteristic" : "olm:{(0.0,1.0)}" - ], LineInput, - rgtd.nodeA, - rgtd.nodeB, - rgtd.lineTypeInputCtoD - ) - ] - - def availableTypes = map([rgtd.lineTypeInputCtoD]) - - when: "the source tries to convert it" - def actualSet = source.typedConnectorEntityDataStream(validStream, availableTypes).collect(Collectors.toSet()) - - then: "everything is fine" - actualSet.size() == expectedSet.size() - def result = Try.scanCollection(actualSet, List) - - result.success - result.data.get().toList().containsAll(expectedSet) - } - - def "The CsvRawGridSource is able to add the third node for a three winding transformer to a stream of candidates"() { - given: "suitable input data" - def inputStream = Stream.of(Try.of(() -> new TypedConnectorInputEntityData([ - "uuid" : "cc327469-7d56-472b-a0df-edbb64f90e8f", - "id" : "3w_test", - "operator" : "8f9682df-0744-4b58-a122-f0dc730f6510", - "operatesFrom" : "2020-03-24T15:11:31Z", - "operatesUntil" : "2020-03-24T15:11:31Z", - "nodeC" : "bd837a25-58f3-44ac-aa90-c6b6e3cd91b2", - "parallelDevices" : "1", - "tapPos" : "0", - "autoTap" : "true" - ], - Transformer3WInput, - rgtd.nodeA, - rgtd.nodeB, - rgtd.transformerTypeAtoBtoC), SourceException), - Try.of(() -> new TypedConnectorInputEntityData([ - "uuid" : "cc327469-7d56-472b-a0df-edbb64f90e8f", - "id" : "3w_test", - "operator" : "8f9682df-0744-4b58-a122-f0dc730f6510", - "operatesFrom" : "2020-03-24T15:11:31Z", - "operatesUntil" : "2020-03-24T15:11:31Z", - "nodeC" : "bd8927b4-0ca9-4dd3-b645-468e6e433160", - "parallelDevices" : "1", - "tapPos" : "0", - "autoTap" : "true" - ], - Transformer3WInput, - rgtd.nodeA, - rgtd.nodeB, - rgtd.transformerTypeAtoBtoC), SourceException)) - - def availableNodes = map([ - rgtd.nodeA, - rgtd.nodeB, - rgtd.nodeC - ]) - - def expected = new Transformer3WInputEntityData([ - "uuid" : "cc327469-7d56-472b-a0df-edbb64f90e8f", - "id" : "3w_test", - "operator" : "8f9682df-0744-4b58-a122-f0dc730f6510", - "operatesFrom" : "2020-03-24T15:11:31Z", - "operatesUntil" : "2020-03-24T15:11:31Z", - "parallelDevices" : "1", - "tapPos" : "0", - "autoTap" : "true" - ], - Transformer3WInput, - rgtd.nodeA, - rgtd.nodeB, - rgtd.nodeC, - rgtd.transformerTypeAtoBtoC) - - when: "the sources tries to add nodes" - def actualSet = source.transformer3WEntityDataStream(inputStream, availableNodes).collect(Collectors.toSet()) - def successes = actualSet.stream().filter { - it.success - }.toList() - def failures = actualSet.stream().filter { - it.failure - }.toList() - - then: "everything is fine" - actualSet.size() == 2 - successes.get(0).data.get() == expected - failures.get(0).exception.get().class == SourceException - } - def "The CsvRawGridSource is able to load all nodes from file"() { when: "loading all nodes from file" def actualSet = source.getNodes() @@ -518,34 +209,34 @@ class CsvRawGridSourceTest extends Specification implements CsvTestDataMeta { when: "loading a total grid structure from file" def actual = source.getGridData() def expected = new RawGridElements( - [ - rgtd.nodeA, - rgtd.nodeB, - rgtd.nodeC, - rgtd.nodeD, - rgtd.nodeE, - rgtd.nodeF, - rgtd.nodeG - ] as Set, - [ - rgtd.lineAtoB, - rgtd.lineCtoD - ] as Set, - [ - GridTestData.transformerBtoD, - GridTestData.transformerBtoE, - GridTestData.transformerCtoE, - GridTestData.transformerCtoF, - GridTestData.transformerCtoG - ] as Set, - [ - GridTestData.transformerAtoBtoC - ] as Set, - [rgtd.switchAtoB] as Set, - [ - rgtd.measurementUnitInput - ] as Set - ) + [ + rgtd.nodeA, + rgtd.nodeB, + rgtd.nodeC, + rgtd.nodeD, + rgtd.nodeE, + rgtd.nodeF, + rgtd.nodeG + ] as Set, + [ + rgtd.lineAtoB, + rgtd.lineCtoD + ] as Set, + [ + GridTestData.transformerBtoD, + GridTestData.transformerBtoE, + GridTestData.transformerCtoE, + GridTestData.transformerCtoF, + GridTestData.transformerCtoG + ] as Set, + [ + GridTestData.transformerAtoBtoC + ] as Set, + [rgtd.switchAtoB] as Set, + [ + rgtd.measurementUnitInput + ] as Set + ) then: "all elements are there" actual != null @@ -617,6 +308,6 @@ 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: Linked nodeA") + 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 ") } } \ 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 91486c5eb..67316ab30 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 @@ -10,8 +10,6 @@ import static edu.ie3.test.helper.EntityMap.map import edu.ie3.datamodel.exceptions.SourceException import edu.ie3.datamodel.exceptions.SystemParticipantsException import edu.ie3.datamodel.io.source.* -import edu.ie3.datamodel.models.input.OperatorInput -import edu.ie3.datamodel.models.input.system.* import edu.ie3.datamodel.utils.Try import edu.ie3.test.common.SystemParticipantTestData as sptd import spock.lang.Specification @@ -79,9 +77,9 @@ 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: " + - "Linked node with UUID 4ca90220-74c2-4369-9afa-a18bf068840d was not found for entity AssetInputEntityData") + "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.") } def "A SystemParticipantSource with csv input should return data from valid input file as expected"() { @@ -158,12 +156,10 @@ class CsvSystemParticipantSourceTest extends Specification implements CsvTestDat heatPumps.exception.get().class == SourceException where: - operators | types | thermalBuses || resultingSize | resultingSet - [] | [sptd.hpInput.type] | [sptd.hpInput.thermalBus] || 1 | [new HpInput(sptd.hpInput.uuid, sptd.hpInput.id, OperatorInput.NO_OPERATOR_ASSIGNED, sptd.hpInput.operationTime, sptd.hpInput.node, sptd.hpInput.thermalBus, sptd.hpInput.qCharacteristics, sptd.emInput, sptd.hpInput.type)] - [] | [] | [] || 0 | [] - [] | [] | [] || 0 | [] - [sptd.hpInput.operator] | [] | [] || 0 | [] - [sptd.hpInput.operator] | [sptd.hpInput.type] | [] || 0 | [] + operators | types | thermalBuses + [] | [] | [] + [sptd.hpInput.operator] | [] | [] + [sptd.hpInput.operator] | [sptd.hpInput.type] | [] } def "A SystemParticipantSource with csv input should throw an exception from a invalid chp input file as expected"() { @@ -184,12 +180,11 @@ class CsvSystemParticipantSourceTest extends Specification implements CsvTestDat chpUnits.exception.get().class == SourceException where: - operators | types | thermalBuses | thermalStorages || resultingSet - [] | [sptd.chpInput.type] | [sptd.chpInput.thermalBus] | [sptd.chpInput.thermalStorage] || [new ChpInput(sptd.chpInput.uuid, sptd.chpInput.id, OperatorInput.NO_OPERATOR_ASSIGNED, sptd.chpInput.operationTime, sptd.chpInput.node, sptd.chpInput.thermalBus, sptd.chpInput.qCharacteristics, sptd.emInput, sptd.chpInput.type, sptd.chpInput.thermalStorage, sptd.chpInput.marketReaction)] - [] | [] | [] | [] as List || [] - [] | [] | [] | [] as List || [] - [sptd.chpInput.operator] | [] | [] | [] as List || [] - [sptd.chpInput.operator] | [sptd.chpInput.type] | [] | [] as List || [] + operators | types | thermalBuses | thermalStorages + [] | [] | [] | [] as List + [] | [] | [] | [] as List + [sptd.chpInput.operator] | [] | [] | [] as List + [sptd.chpInput.operator] | [sptd.chpInput.type] | [] | [] as List } def "A SystemParticipantSource with csv input should throw an exception from invalid ev input file as expected"() { @@ -210,10 +205,9 @@ class CsvSystemParticipantSourceTest extends Specification implements CsvTestDat sysParts.exception.get().class == SourceException where: - operators | types || resultingSet - [] | [sptd.evInput.type] || [new EvInput(sptd.evInput.uuid, sptd.evInput.id, OperatorInput.NO_OPERATOR_ASSIGNED, sptd.evInput.operationTime, sptd.evInput.node, sptd.evInput.qCharacteristics, sptd.emInput, sptd.evInput.type)] - [sptd.evInput.operator] | [] || [] - [] | [] || [] + operators | types + [sptd.evInput.operator] | [] + [] | [] } def "A SystemParticipantSource with csv input should throw an exception from invalid wec input file as expected"() { @@ -234,10 +228,9 @@ class CsvSystemParticipantSourceTest extends Specification implements CsvTestDat sysParts.exception.get().class == SourceException where: - operators | types || resultingSet - [] | [sptd.wecInput.type] || [new WecInput(sptd.wecInput.uuid, sptd.wecInput.id, OperatorInput.NO_OPERATOR_ASSIGNED, sptd.wecInput.operationTime, sptd.wecInput.node, sptd.wecInput.qCharacteristics, sptd.emInput, sptd.wecInput.type, sptd.wecInput.marketReaction)] - [sptd.wecInput.operator] | [] || [] - [] | [] || [] + operators | types + [sptd.wecInput.operator] | [] + [] | [] } def "A SystemParticipantSource with csv input should throw an exception from invalid storage input file as expected"() { @@ -258,10 +251,9 @@ class CsvSystemParticipantSourceTest extends Specification implements CsvTestDat sysParts.exception.get().class == SourceException where: - operators | types || resultingSet - [] | [sptd.storageInput.type] || [new StorageInput(sptd.storageInput.uuid, sptd.storageInput.id, OperatorInput.NO_OPERATOR_ASSIGNED, sptd.storageInput.operationTime, sptd.storageInput.node, sptd.storageInput.qCharacteristics, sptd.emInput, sptd.storageInput.type)] - [sptd.storageInput.operator] | [] || [] - [] | [] || [] + operators | types + [sptd.storageInput.operator] | [] + [] | [] } def "A SystemParticipantSource with csv input should throw an exception from invalid bm input file as expected"() { @@ -282,11 +274,9 @@ class CsvSystemParticipantSourceTest extends Specification implements CsvTestDat sysParts.exception.get().class == SourceException where: - operators | types || resultingSet - [] | [sptd.bmInput.type] || [new BmInput(sptd.bmInput.uuid, sptd.bmInput.id, OperatorInput.NO_OPERATOR_ASSIGNED, sptd.bmInput.operationTime, sptd.bmInput.node, sptd.bmInput.qCharacteristics, sptd.emInput, sptd.bmInput.type, sptd.bmInput.marketReaction, sptd.bmInput.costControlled, sptd.bmInput.feedInTariff)] - [sptd.bmInput.operator] | [] || [] - [] | [] || [] - [] | [] || [] + operators | types + [sptd.bmInput.operator] | [] + [] | [] } def "A SystemParticipantSource with csv input should throw an exception from invalid ev charging station input file as expected"() { @@ -306,10 +296,9 @@ class CsvSystemParticipantSourceTest extends Specification implements CsvTestDat sysParts.exception.get().class == SourceException where: - nodes | operators || resultingSet - [sptd.evcsInput.node] | [] || [new EvcsInput(sptd.evcsInput.uuid, sptd.evcsInput.id, OperatorInput.NO_OPERATOR_ASSIGNED, sptd.evcsInput.operationTime, sptd.evcsInput.node, sptd.evcsInput.qCharacteristics, sptd.emInput, sptd.evcsInput.type, sptd.evcsInput.chargingPoints, sptd.evcsInput.cosPhiRated, sptd.evcsInput.locationType, sptd.evcsInput.v2gSupport)] - [] | [sptd.evcsInput.operator] || [] - [] | [] || [] + nodes | operators + [] | [sptd.evcsInput.operator] + [] | [] } def "A SystemParticipantSource with csv input should throw an exception from invalid load input file as expected"() { @@ -329,10 +318,9 @@ class CsvSystemParticipantSourceTest extends Specification implements CsvTestDat sysParts.exception.get().class == SourceException where: - nodes | operators || resultingSet - [sptd.loadInput.node] | [] || [new LoadInput(sptd.loadInput.uuid, sptd.loadInput.id, OperatorInput.NO_OPERATOR_ASSIGNED, sptd.loadInput.operationTime, sptd.loadInput.node, sptd.loadInput.qCharacteristics, sptd.emInput, sptd.loadInput.loadProfile, sptd.loadInput.dsm, sptd.loadInput.eConsAnnual, sptd.loadInput.sRated, sptd.loadInput.cosPhiRated)] - [] | [sptd.loadInput.operator] || [] - [] | [] || [] + nodes | operators + [] | [sptd.loadInput.operator] + [] | [] } def "A SystemParticipantSource with csv input should throw an exception from invalid pv input file as expected"() { @@ -352,10 +340,9 @@ class CsvSystemParticipantSourceTest extends Specification implements CsvTestDat sysParts.exception.get().class == SourceException where: - nodes | operators || resultingSet - [sptd.pvInput.node] | [] || [new PvInput(sptd.pvInput.uuid, sptd.pvInput.id, OperatorInput.NO_OPERATOR_ASSIGNED, sptd.pvInput.operationTime, sptd.pvInput.node, sptd.pvInput.qCharacteristics, sptd.emInput, sptd.pvInput.albedo, sptd.pvInput.azimuth, sptd.pvInput.etaConv, sptd.pvInput.elevationAngle, sptd.pvInput.kG, sptd.pvInput.kT, sptd.pvInput.marketReaction, sptd.pvInput.sRated, sptd.pvInput.cosPhiRated)] - [] | [sptd.pvInput.operator] || [] - [] | [] || [] + nodes | operators + [] | [sptd.pvInput.operator] + [] | [] } def "A SystemParticipantSource with csv input should throw an exception from invalid fixedFeedIn input file as expected"() { @@ -375,9 +362,8 @@ class CsvSystemParticipantSourceTest extends Specification implements CsvTestDat sysParts.exception.get().class == SourceException where: - nodes | operators || resultingSet - [sptd.fixedFeedInInput.node] | [] as List || [new FixedFeedInInput(sptd.fixedFeedInInput.uuid, sptd.fixedFeedInInput.id, OperatorInput.NO_OPERATOR_ASSIGNED, sptd.fixedFeedInInput.operationTime, sptd.fixedFeedInInput.node, sptd.fixedFeedInInput.qCharacteristics, sptd.emInput, sptd.fixedFeedInInput.sRated, sptd.fixedFeedInInput.cosPhiRated)] - [] | [sptd.fixedFeedInInput.operator] as List || [] - [] | [] as List || [] + nodes | operators + [] | [sptd.fixedFeedInInput.operator] + [] | [] } } diff --git a/src/test/groovy/edu/ie3/datamodel/utils/TryTest.groovy b/src/test/groovy/edu/ie3/datamodel/utils/TryTest.groovy index 1419f04f3..b7d636a15 100644 --- a/src/test/groovy/edu/ie3/datamodel/utils/TryTest.groovy +++ b/src/test/groovy/edu/ie3/datamodel/utils/TryTest.groovy @@ -8,6 +8,7 @@ package edu.ie3.datamodel.utils import edu.ie3.datamodel.exceptions.FailureException import edu.ie3.datamodel.exceptions.SourceException import edu.ie3.datamodel.exceptions.TryException +import org.apache.commons.lang3.tuple.Pair import spock.lang.Specification import java.util.stream.Stream @@ -343,6 +344,60 @@ class TryTest extends Specification { flatMapF.exception.get() == failure.get() } + def "Two Tries can be zipped correctly"() { + given: + def given = Try.of(() -> 1, SourceException) + + when: + def actual = given.zip(second) + + then: + actual.isSuccess() == isSuccess + actual.data == expectedData + + where: + second | isSuccess | expectedData + new Try.Failure(new SourceException("source exception")) | false | Optional.empty() + new Try.Success("1") | true | Optional.of(Pair.of(1, "1")) + } + + def "Two Tries can be zipped to any object correctly"() { + given: + def given = Try.of(() -> 1, SourceException) + def fcn = (i1, i2) -> i1 + i2 + + when: + def actual = given.zip(second, fcn) + + then: + actual.isSuccess() == isSuccess + actual.data == expectedData + + where: + second | isSuccess | expectedData + new Try.Failure(new SourceException("source exception")) | false | Optional.empty() + new Try.Success(10) | true | Optional.of(11) + } + + def "Two Tries can be extracted and zipped correctly"() { + given: + def given = Try.of(() -> 1, SourceException) + + def failureExtractor = f -> new Try.Failure(new SourceException("source exception")) + def successExtractor = s -> new Try.Success("10") + + when: + def failure = given.zip(failureExtractor) + def success = given.zip(successExtractor) + + then: + failure.isFailure() + + success.isSuccess() + success.data == Optional.of(Pair.of(1, "10")) + } + + def "The convert method should work correctly for successes"() { given: Try, SourceException> success = new Try.Success(Stream.of(1, 2, 3)) diff --git a/src/test/groovy/edu/ie3/test/common/WeatherTestData.groovy b/src/test/groovy/edu/ie3/test/common/WeatherTestData.groovy index 2eed3c090..b67801618 100644 --- a/src/test/groovy/edu/ie3/test/common/WeatherTestData.groovy +++ b/src/test/groovy/edu/ie3/test/common/WeatherTestData.groovy @@ -6,6 +6,7 @@ package edu.ie3.test.common import edu.ie3.datamodel.exceptions.SourceException +import edu.ie3.datamodel.exceptions.ValidationException import edu.ie3.datamodel.io.source.IdCoordinateSource import edu.ie3.datamodel.io.source.csv.CsvTestDataMeta import edu.ie3.util.geo.CoordinateDistance @@ -19,7 +20,7 @@ import javax.measure.quantity.Length abstract class WeatherTestData { - static final class DummyIdCoordinateSource implements CsvTestDataMeta, IdCoordinateSource { + static final class DummyIdCoordinateSource extends IdCoordinateSource implements CsvTestDataMeta { @Override Optional> getSourceFields() throws SourceException { @@ -85,6 +86,10 @@ abstract class WeatherTestData { List findCornerPoints(Point coordinate, ComparableQuantity distance) { throw new UnsupportedOperationException("This method is not supported!") } + + @Override + void validate() throws ValidationException { + } } public static final IdCoordinateSource coordinateSource = new DummyIdCoordinateSource() diff --git a/version.properties b/version.properties index ff80e02ad..18a1ed5d0 100644 --- a/version.properties +++ b/version.properties @@ -1,5 +1,5 @@ #Generated by the Semver Plugin for Gradle -#Wed Mar 06 14:01:24 CET 2024 +#Mon Jun 24 13:26:11 CEST 2024 version.buildmeta= version.major=6 version.minor=0