diff --git a/Middleware/.classpath b/Middleware/.classpath index 8b1b747d..ee4a5b45 100644 --- a/Middleware/.classpath +++ b/Middleware/.classpath @@ -32,8 +32,8 @@ - + diff --git a/Middleware/docs/examples/code/CalibrationExampleWithCITYdata.py b/Middleware/docs/examples/code/CalibrationExampleWithCITYdata.py index 01587ef0..c4801ec9 100644 --- a/Middleware/docs/examples/code/CalibrationExampleWithCITYdata.py +++ b/Middleware/docs/examples/code/CalibrationExampleWithCITYdata.py @@ -8,12 +8,12 @@ # USER CONFIGURATION # ========================== # Configuration -BASE_URL = "https://ngci.encs.concordia.ca/citydata" -USERNAME = username # Production username created by CITYdata team -PASSWORD = password # Production password created by CITYdata team -# BASE_URL = "http://localhost:8080/citydata" -# USERNAME = username # Local username created with the script (cf. README) -# PASSWORD = password # Local password created with the script (cf. README) +#BASE_URL = "https://ngci.encs.concordia.ca/citydata" +#USERNAME = "workshop" # Production username +#PASSWORD = "workshop2026" # Production password +BASE_URL = "http://localhost:8080" +USERNAME = "temp" # Local username +PASSWORD = "temp" # Local password @@ -33,7 +33,7 @@ def print_result(response): raw_data = response.get("result", "") raw_data = raw_data.strip("[]") - parts = raw_data.split(", ") + parts =raw_data.split(", ") print("\nResults:\n") for i in range(0, len(parts), 3): @@ -55,37 +55,39 @@ def fetch_consumption(base_url, token): "Authorization": f"Bearer {token}" } - # json_input = { - # "use": "ca.concordia.encs.citydata.producers.CalibrationProducer", - # "withParams": [ - # { "name": "filePath", "value": "src/test/resources/OMHM_natural_gas.csv" } - # ], - # "apply": [ - # { - # "name": "ca.concordia.encs.citydata.operations.CSVFilterOperation", - # "withParams": [ - # { "name": "addressFilter", "value": "H1W3J9" }, - # { "name": "dateFilter", "value": "2022-04-30" } - # ] - # } - # ] - # } - json_input = { - "use": "ca.concordia.encs.citydata.producers.CalibrationProducer", - "withParams": [ - { "name": "filePath", "value": "src/test/resources/OMHM_electricity.csv" } - ], - "apply": [ - { - "name": "ca.concordia.encs.citydata.operations.CSVFilterOperation", - "withParams": [ - { "name": "addressFilter", "value": "H1Z 0B3" }, - { "name": "dateFilter", "value": "2022-02-28" } - ] - } - ] - } + "use": "ca.concordia.encs.citydata.producers.CalibrationProducer", + "withParams": [ + { "name": "filePath", "value": "src/test/resources/OMHM_natural_gas.csv" } + ], + "apply": [ + { + "name": "ca.concordia.encs.citydata.operations.CSVFilterOperation", + "withParams": [ + { "name": "addressFilter", "value": "8431 Allée Léo-Bricault Montréal H1Z 0B3;8441 Allée Léo-Bricault Montréal H1Z 0B3;8425 Avenue 25e Montréal H1Z 4A9" }, + { "name": "startDateFilter", "value": "2022-01-31" }, + { "name": "endDateFilter", "value": "2022-12-31" } + ] + } + ] + } + + # json_input = { + # "use": "ca.concordia.encs.citydata.producers.CalibrationProducer", + # "withParams": [ + # { "name": "filePath", "value": "src/test/resources/OMHM_electricity.csv" } + # ], + # "apply": [ + # { + # "name": "ca.concordia.encs.citydata.operations.CSVFilterOperation", + # "withParams": [ + # { "name": "addressFilter", "value": "8431 Allée Léo-Bricault Montréal H1Z 0B3;8441 Allée Léo-Bricault Montréal H1Z 0B3;8425 Avenue 25e Montréal H1Z 4A9" }, + # { "name": "startDateFilter", "value": "2022-01-31" }, + # { "name": "endDateFilter", "value": "2022-12-31" } + # ] + # } + # ] + # } response = requests.post(sync_url, headers=headers, data=json.dumps(json_input)) diff --git a/Middleware/docs/examples/code/PortfolioManagerWithCITYDataTest.py b/Middleware/docs/examples/code/PortfolioManagerWithCITYDataTest.py index 9d60a093..7a708bc5 100644 --- a/Middleware/docs/examples/code/PortfolioManagerWithCITYDataTest.py +++ b/Middleware/docs/examples/code/PortfolioManagerWithCITYDataTest.py @@ -9,7 +9,7 @@ # USER CONFIGURATION # ========================== # Configuration -B ASE_URL = "https://ngci.encs.concordia.ca/citydata" +BASE_URL = "https://ngci.encs.concordia.ca/citydata" USERNAME = "workshop" # Production username PASSWORD = "workshop2026" # Production password #BASE_URL = "http://localhost:8080/citydata" diff --git a/Middleware/docs/examples/queries/filterPortfolioManagerProducerConsumption.json b/Middleware/docs/examples/queries/filterPortfolioManagerProducerConsumption.json index 24e21fe0..84024e1a 100644 --- a/Middleware/docs/examples/queries/filterPortfolioManagerProducerConsumption.json +++ b/Middleware/docs/examples/queries/filterPortfolioManagerProducerConsumption.json @@ -1,27 +1,16 @@ { - "use": "ca.concordia.encs.citydata.producers.PortfolioManagerProducer", + "use": "ca.concordia.encs.citydata.core.implementations.PortfolioManagerProducer", "withParams": [ - { - "name": "meterId", - "value": "299278275" - } + { "name": "meterId", "value": meter_id } ], "apply": [ - { - "use": "ca.concordia.encs.citydata.producers.PortfolioManagerProducer", - "withParams": [ - { "name": "meterId", "value": "299278275" } - ], - "apply": [ - { - "name": "ca.concordia.encs.citydata.operations.XmlToJsonFilterOperation", - "withParams": [ - { "name": "filterKey", "value": "startDate" }, - { "name": "from", "value": "2024-11-01" }, - { "name": "to", "value": "2024-12-31" } - ] - } - ] - } + { + "name": "ca.concordia.encs.citydata.operations.XmlToJsonFilterOperation", + "withParams": [ + { "name": "filterKey", "value": "startDate" }, + { "name": "from", "value": "2020-11-01" }, + { "name": "to", "value": "2023-12-31" } + ] + } ] } \ No newline at end of file diff --git a/Middleware/docs/examples/queries/mergeRandomNumberProducers.json b/Middleware/docs/examples/queries/mergeRandomNumberProducers.json deleted file mode 100644 index 0eec3c40..00000000 --- a/Middleware/docs/examples/queries/mergeRandomNumberProducers.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "use": "ca.concordia.encs.citydata.producers.RandomNumberProducer", - "withParams": [ - { - "name": "listSize", - "value": 10 - } - ], - "apply": [ - { - "name": "ca.concordia.encs.citydata.operations.AverageOperation", - "withParams": [ - { - "name": "roundingMethod", - "value": "floor" - } - ] - }, - { - "name": "ca.concordia.encs.citydata.operations.MergeOperation", - "withParams": [ - { - "name": "targetProducer", - "value": "ca.concordia.encs.citydata.producers.RandomNumberProducer" - }, - { - "name": "targetProducerParams", - "value": [ - { - "name": "listSize", - "value": 4 - } - ] - } - ] - } - ] -} \ No newline at end of file diff --git a/Middleware/docs/examples/queries/randomNumberProducerFloor.json b/Middleware/docs/examples/queries/randomNumberProducerFloor.json deleted file mode 100644 index 6d356b9f..00000000 --- a/Middleware/docs/examples/queries/randomNumberProducerFloor.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "use": "ca.concordia.encs.citydata.producers.RandomNumberProducer", - "withParams": [ - { - "name": "listSize", - "value": 10 - } - ], - "apply": [ - { - "name": "ca.concordia.encs.citydata.operations.AverageOperation", - "withParams": [ - { - "name": "roundingMethod", - "value": "floor" - } - ] - } - ] -} \ No newline at end of file diff --git a/Middleware/docs/examples/queries/stringProducerRandom.json b/Middleware/docs/examples/queries/stringProducerRandom.json deleted file mode 100644 index f2315582..00000000 --- a/Middleware/docs/examples/queries/stringProducerRandom.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "use": "ca.concordia.encs.citydata.producers.RandomStringProducer", - "withParams": [ - { - "name": "stringLength", - "value": 10 - } - ], - "apply": [] -} \ No newline at end of file diff --git a/Middleware/docs/examples/queries/stringProducerRandomWithParams.json b/Middleware/docs/examples/queries/stringProducerRandomWithParams.json deleted file mode 100644 index df2dce94..00000000 --- a/Middleware/docs/examples/queries/stringProducerRandomWithParams.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "use": "ca.concordia.encs.citydata.producers.RandomStringProducer", - "withParams": [ - { - "name": "stringLength", - "value": 50 - } - ], - "apply": [ - { - "name": "ca.concordia.encs.citydata.operations.StringReplaceOperation", - "withParams": [ - { - "name": "searchFor", - "value": "a" - }, - { - "name": "replaceBy", - "value": "==HELLO==" - } - ] - } - ] -} \ No newline at end of file diff --git a/Middleware/src/main/java/ca/concordia/encs/citydata/core/implementations/AbstractProducer.java b/Middleware/src/main/java/ca/concordia/encs/citydata/core/implementations/AbstractProducer.java index 81db21f1..40b537b0 100644 --- a/Middleware/src/main/java/ca/concordia/encs/citydata/core/implementations/AbstractProducer.java +++ b/Middleware/src/main/java/ca/concordia/encs/citydata/core/implementations/AbstractProducer.java @@ -38,8 +38,9 @@ * @since 2025-05-27 */ -public sealed abstract class AbstractProducer extends AbstractEntity implements IProducer permits JSONProducer, - CSVProducer, ExceptionProducer, FirebaseProducer, PortfolioManagerProducer, PortfolioManagerMetadataProducer { +public sealed abstract class AbstractProducer extends AbstractEntity implements IProducer + permits JSONProducer, CSVProducer, ExceptionProducer, FirebaseProducer, PortfolioManagerProducer, + PortfolioManagerMetadataProducer, JsonArrayProducer { private String filePath; private RequestOptions fileOptions; private IOperation operation; diff --git a/Middleware/src/main/java/ca/concordia/encs/citydata/core/implementations/JsonArrayProducer.java b/Middleware/src/main/java/ca/concordia/encs/citydata/core/implementations/JsonArrayProducer.java new file mode 100644 index 00000000..f9716e0c --- /dev/null +++ b/Middleware/src/main/java/ca/concordia/encs/citydata/core/implementations/JsonArrayProducer.java @@ -0,0 +1,55 @@ +package ca.concordia.encs.citydata.core.implementations; + +import java.io.OutputStream; +import java.util.ArrayList; + +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; + +import ca.concordia.encs.citydata.core.contracts.IProducer; +import ca.concordia.encs.citydata.core.utils.RequestOptions; + +/** +*This acts as a base producer for EnergyConsuimption Producer and any other producer that needs to return a JSON array. +* +* @author Sikandar Ejaz +* @since 2026-05-13 +*/ + +public non-sealed class JsonArrayProducer extends AbstractProducer implements IProducer { + + public JsonArrayProducer(final String filePath) { + super(filePath); + } + + public JsonArrayProducer(final String filePath, final RequestOptions fileOptions) { + super(filePath, fileOptions); + } + + @Override + public void fetch() { + final ArrayList jsonOutput = new ArrayList<>(); + + // Use ByteArrayOutputStream to fetch data + + OutputStream outputStream = this.fetchFromPath(); + String inputJson = outputStream.toString(); + + // Convert JSON string to object + final JsonElement inputJsonElement = JsonParser.parseString(inputJson); + + JsonObject outputJsonObject = new JsonObject(); + if (inputJsonElement.isJsonArray()) { + outputJsonObject.add("result", inputJsonElement); + } else { + outputJsonObject = inputJsonElement.getAsJsonObject(); + } + + jsonOutput.add(outputJsonObject); + this.setResult(jsonOutput); + this.applyOperation(); + } + +} diff --git a/Middleware/src/main/java/ca/concordia/encs/citydata/core/implementations/PortfolioManagerMetadataProducer.java b/Middleware/src/main/java/ca/concordia/encs/citydata/core/implementations/PortfolioManagerMetadataProducer.java index 81726e8e..d72fdb9e 100644 --- a/Middleware/src/main/java/ca/concordia/encs/citydata/core/implementations/PortfolioManagerMetadataProducer.java +++ b/Middleware/src/main/java/ca/concordia/encs/citydata/core/implementations/PortfolioManagerMetadataProducer.java @@ -29,6 +29,14 @@ public non-sealed class PortfolioManagerMetadataProducer extends AbstractProduce private IOperation operation; private IRunner runnerObserver; + public PortfolioManagerMetadataProducer() { + super(); + } + + public PortfolioManagerMetadataProducer(String filePath, RequestOptions fileOptions) { + super(filePath, fileOptions); + } + public void setAccountId(String accountId) { this.accountId = accountId; } diff --git a/Middleware/src/main/java/ca/concordia/encs/citydata/core/implementations/PortfolioManagerProducer.java b/Middleware/src/main/java/ca/concordia/encs/citydata/core/implementations/PortfolioManagerProducer.java index b172a4b4..6d5d3ca7 100644 --- a/Middleware/src/main/java/ca/concordia/encs/citydata/core/implementations/PortfolioManagerProducer.java +++ b/Middleware/src/main/java/ca/concordia/encs/citydata/core/implementations/PortfolioManagerProducer.java @@ -24,11 +24,20 @@ public non-sealed class PortfolioManagerProducer extends AbstractProducer implements IProducer { private String meterId; private final ArrayList intermediateResult = new ArrayList<>(); - - public void setMeterId(String meterId) { - this.meterId = meterId; - } - + + public PortfolioManagerProducer() { + super(); + } + + public PortfolioManagerProducer(String filePath, RequestOptions fileOptions) { + super(filePath, fileOptions); + } + + public void setMeterId(String meterId) { + System.out.println(">>> setMeterId called with: " + meterId); + this.meterId = meterId; + } + @SuppressWarnings("unchecked") private ArrayList getMeterMetadata(SingleStepRunner runner) { final InMemoryDataStore store = InMemoryDataStore.getInstance(); diff --git a/Middleware/src/main/java/ca/concordia/encs/citydata/operations/JsonArrayAverageOperation.java b/Middleware/src/main/java/ca/concordia/encs/citydata/operations/JsonArrayAverageOperation.java index 2bf3d633..8557c0b0 100644 --- a/Middleware/src/main/java/ca/concordia/encs/citydata/operations/JsonArrayAverageOperation.java +++ b/Middleware/src/main/java/ca/concordia/encs/citydata/operations/JsonArrayAverageOperation.java @@ -38,6 +38,7 @@ public ArrayList apply(ArrayList inputs) { // compute the average for (JsonArray list : inputs) { + floatAverage = 0.0f; for (JsonElement element : list) { floatAverage += element.getAsJsonObject().get(keyName).getAsFloat(); } diff --git a/Middleware/src/main/java/ca/concordia/encs/citydata/producers/CalibrationProducer.java b/Middleware/src/main/java/ca/concordia/encs/citydata/producers/CalibrationProducer.java index 150c18e2..a3001770 100644 --- a/Middleware/src/main/java/ca/concordia/encs/citydata/producers/CalibrationProducer.java +++ b/Middleware/src/main/java/ca/concordia/encs/citydata/producers/CalibrationProducer.java @@ -6,6 +6,7 @@ import ca.concordia.encs.citydata.core.exceptions.MiddlewareException; import ca.concordia.encs.citydata.core.implementations.CSVProducer; +import ca.concordia.encs.citydata.core.utils.RequestOptions; /** * This Producer outputs metadata about a building, such as floors, zones and sensors. @@ -19,6 +20,10 @@ public CalibrationProducer(String filePath) { super(filePath); } + public CalibrationProducer(String filePath, RequestOptions fileOptions) { + super(filePath, fileOptions); + } + @Override public void fetch() { System.out.println("Fetching file from path: " + this.getFilePath()); diff --git a/Middleware/src/main/java/ca/concordia/encs/citydata/producers/EnergyConsumptionProducer.java b/Middleware/src/main/java/ca/concordia/encs/citydata/producers/EnergyConsumptionProducer.java index f5886651..4b4c124f 100644 --- a/Middleware/src/main/java/ca/concordia/encs/citydata/producers/EnergyConsumptionProducer.java +++ b/Middleware/src/main/java/ca/concordia/encs/citydata/producers/EnergyConsumptionProducer.java @@ -16,7 +16,7 @@ import ca.concordia.encs.citydata.core.exceptions.MiddlewareException; import ca.concordia.encs.citydata.core.exceptions.MiddlewareException.DatasetNotFound; -import ca.concordia.encs.citydata.core.implementations.CSVProducer; +import ca.concordia.encs.citydata.core.implementations.JsonArrayProducer; import ca.concordia.encs.citydata.core.utils.RequestOptions; import ca.concordia.encs.citydata.core.utils.StringUtils; @@ -30,7 +30,7 @@ * @since 2025-05-28 */ -public class EnergyConsumptionProducer extends CSVProducer { +public class EnergyConsumptionProducer extends JsonArrayProducer { public EnergyConsumptionProducer(String filePath) { super(filePath); @@ -157,8 +157,8 @@ public void fetch() { resultRow.addProperty("error", e.getMessage()); resultsArray.add(resultRow); } finally { - final ArrayList updatedResult = this.getResult(); - updatedResult.add(resultsArray.toString()); + final ArrayList updatedResult = this.getResult(); + updatedResult.add(resultsArray); this.setResult(updatedResult); this.applyOperation(); } diff --git a/Middleware/src/main/java/ca/concordia/encs/citydata/producers/GeometryProducer.java b/Middleware/src/main/java/ca/concordia/encs/citydata/producers/GeometryProducer.java index 862bdd7a..5f5c56ff 100644 --- a/Middleware/src/main/java/ca/concordia/encs/citydata/producers/GeometryProducer.java +++ b/Middleware/src/main/java/ca/concordia/encs/citydata/producers/GeometryProducer.java @@ -1,6 +1,9 @@ package ca.concordia.encs.citydata.producers; import java.security.InvalidParameterException; +import java.util.ArrayList; + +import com.google.gson.JsonObject; import ca.concordia.encs.citydata.core.contracts.IOperation; import ca.concordia.encs.citydata.core.contracts.IRunner; @@ -15,9 +18,6 @@ */ public class GeometryProducer extends JSONProducer { - public GeometryProducer(String filePath, RequestOptions fileOptions) { - super(filePath, fileOptions); - } private JSONProducer jsonProducer; @@ -35,6 +35,19 @@ public void setOperation(IOperation operation) { this.jsonProducer.setOperation(operation); } + public GeometryProducer() { + super(null, null); + } + + public GeometryProducer(String filePath, RequestOptions fileOptions) { + super(filePath, fileOptions); + } + + @Override + public ArrayList getResult() { + return this.jsonProducer.getResult(); + } + @Override public void fetch() { this.jsonProducer.fetch(); diff --git a/Middleware/src/main/java/ca/concordia/encs/citydata/producers/RetrofitResultsProducer.java b/Middleware/src/main/java/ca/concordia/encs/citydata/producers/RetrofitResultsProducer.java index d077e146..fd52ffb4 100644 --- a/Middleware/src/main/java/ca/concordia/encs/citydata/producers/RetrofitResultsProducer.java +++ b/Middleware/src/main/java/ca/concordia/encs/citydata/producers/RetrofitResultsProducer.java @@ -31,6 +31,10 @@ public RetrofitResultsProducer(String filePath) { super(filePath); } + public RetrofitResultsProducer(String filePath, RequestOptions options) { + super(filePath, options); + } + private JsonArray buildingIds; private IOperation jsonProducerOperation; private IRunner runnerObserver; diff --git a/Middleware/src/main/resources/application.properties b/Middleware/src/main/resources/application.properties index 6cfc6966..f9fc9875 100644 --- a/Middleware/src/main/resources/application.properties +++ b/Middleware/src/main/resources/application.properties @@ -12,7 +12,7 @@ spring.data.mongodb.uri=mongodb://localhost:27017/citydata spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration,org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration # Portfolio Manager Energy Star Configuration -# TODO: If multiple Portfolio manager accounts are needed, a dedicated authentication producer should replace multiple entries in the file. It is unrelated to the JWT auth +#Warning, plan to create a portfolio manager auth producer if many instances of users will be managed portfoliomanager.base-url=https://portfoliomanager.energystar.gov/ws portfoliomanager.username=$PM_USERNAME portfoliomanager.password=$PM_USERNAME @@ -28,4 +28,4 @@ security.credentials.path=./src/main/resources/scripts/credentials/credentials.t # server.servlet.context-path=/citydata # Server port (8080 is the default from Spring) -# server.port=8084 +# server.port=8084 \ No newline at end of file diff --git a/Middleware/src/test/java/ca/concordia/encs/citydata/test/producers/ProducersSanityTest.java b/Middleware/src/test/java/ca/concordia/encs/citydata/test/producers/ProducersSanityTest.java index c2c72fbc..95af82b9 100644 --- a/Middleware/src/test/java/ca/concordia/encs/citydata/test/producers/ProducersSanityTest.java +++ b/Middleware/src/test/java/ca/concordia/encs/citydata/test/producers/ProducersSanityTest.java @@ -4,6 +4,7 @@ import org.junit.jupiter.api.Test; +import com.google.gson.JsonArray; import com.google.gson.JsonObject; import ca.concordia.encs.citydata.operations.StandardFilteringOperation; @@ -34,7 +35,7 @@ public void testEnergyConsumptionProducer() { producer1.validateParams(); producer1.buildQuery(); producer1.fetch(); - ArrayList result = producer1.getResult(); + ArrayList result = producer1.getResult(); System.out.println(result); }