diff --git a/.gitignore b/.gitignore index acb74c498e6f45d16d48a10480856e7401e0d2fd..c2fc2ba8f2690d85f2b029acbe02740b339f4316 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /target *.iml .classpath -.project \ No newline at end of file +.project +.settings \ No newline at end of file diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs deleted file mode 100644 index 18308defdbd17a8bd5837fef98d92d04e0014ed4..0000000000000000000000000000000000000000 --- a/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,6 +0,0 @@ -eclipse.preferences.version=1 -encoding//src/main/java=utf-8 -encoding//src/main/resources=utf-8 -encoding//src/test/java=utf-8 -encoding//src/test/resources=utf-8 -encoding/=UTF-8 diff --git a/.settings/org.eclipse.jdt.apt.core.prefs b/.settings/org.eclipse.jdt.apt.core.prefs deleted file mode 100644 index dfa4f3adb289a4f7d73e0694f9045f99325604d7..0000000000000000000000000000000000000000 --- a/.settings/org.eclipse.jdt.apt.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.apt.aptEnabled=true -org.eclipse.jdt.apt.genSrcDir=target/generated-sources/annotations -org.eclipse.jdt.apt.genTestSrcDir=target/generated-test-sources/test-annotations diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs deleted file mode 100644 index 87f474ba76f5340f448a1601feef33881f04043b..0000000000000000000000000000000000000000 --- a/.settings/org.eclipse.jdt.core.prefs +++ /dev/null @@ -1,9 +0,0 @@ -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=17 -org.eclipse.jdt.core.compiler.compliance=17 -org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled -org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning -org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore -org.eclipse.jdt.core.compiler.processAnnotations=enabled -org.eclipse.jdt.core.compiler.release=disabled -org.eclipse.jdt.core.compiler.source=17 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs deleted file mode 100644 index f897a7f1cb2389f85fe6381425d29f0a9866fb65..0000000000000000000000000000000000000000 --- a/.settings/org.eclipse.m2e.core.prefs +++ /dev/null @@ -1,4 +0,0 @@ -activeProfiles= -eclipse.preferences.version=1 -resolveWorkspaceProjects=true -version=1 diff --git a/Dockerfile b/Dockerfile index 08d8bc13d63e35aa8b69d9258c6360089a510d4d..b6f44cfdcca84c296430ea51d85aad099883cb87 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ FROM ibm-semeru-runtimes:open-17.0.7_7-jdk RUN mkdir /opt/shareclasses RUN mkdir -p /opt/openslice/lib/ -COPY target/org.etsi.osl.metrico-0.9-exec.jar /opt/openslice/lib/ -CMD ["java", "-Xshareclasses:cacheDir=/opt/shareclasses", "-jar", "/opt/openslice/lib/org.etsi.osl.metrico-0.9-exec.jar"] +COPY target/org.etsi.osl.metrico-1.0.0-exec.jar /opt/openslice/lib/ +CMD ["java", "-Xshareclasses:cacheDir=/opt/shareclasses", "-jar", "/opt/openslice/lib/org.etsi.osl.metrico-1.0.0-exec.jar"] diff --git a/Documentation/FlowDiagram.puml b/Documentation/FlowDiagram.puml index 288b565f4542eff08ec4397057974fce7fe507f6..2334bd61820cbec2071d2063a1eb824a72aa0d4d 100644 --- a/Documentation/FlowDiagram.puml +++ b/Documentation/FlowDiagram.puml @@ -1,39 +1,67 @@ -@startuml FlowDiagram -actor "ACTOR" as actor +@startuml +actor "USER" as actor participant "OSOM" as osom participant "TMF API" as tmf_api -queue amq as amq +queue "Message Bus" as amq participant "METRICO" as metrico -participant prometheus as prom +participant Prometheus as prom -actor -> tmf_api: CREATE: Service Order Monitoring aaS -osom -> osom: PROCESS ORDER +actor -> tmf_api: Create Service Order Monitoring aaS +osom -> osom: Process order -osom -> tmf_api: CREATE: service instance of monitoring aaS (RFS)(Initial Status: Reseved) -osom -> tmf_api: CREATE: service instance of monitoring aaS (CFS)(Initial Status: Reseved) +osom -> tmf_api: Create Service instance of monitoring aaS (CFS) (Initial Status: Reserved) +osom -> tmf_api: Create Service instance of monitoring aaS (RFS) (Initial Status: Reserved) +osom -> amq: Create Resource Message \njms:queue:CATALOG.ADD.RESOURCE \npayload: Status = "Reserved" & Characteristic _MT_MCJ_REF = "PENDING" +amq -> tmf_api: LISTENS FOR: Create Resource Message \njms:queue:CATALOG.ADD.RESOURCE +tmf_api -> tmf_api: Create Resource +tmf_api --> amq: RESPONSE: Resource +amq --> osom: RESPONSE: Resource -osom -> amq: CREATE: TMF628 Measurement Collection Job \nqueue:PM_MEASUREMENT_COLLECTION_JOB_ADD \npayload: MeasurementCollectionJobFVO -amq -> tmf_api: CREATE: TMF628 Measurement Collection Job \nqueue:PM_MEASUREMENT_COLLECTION_JOB_ADD \npayload: MeasurementCollectionJobFVO (Here I can find the MCJ ID) -tmf_api -> amq: CREATE: TMF628 Measurement Collection Job \nqueue:PM_MEASUREMENT_COLLECTION_JOB_ADD \npayload: MeasurementCollectionJob (Here I can find the MCJ ID) -osom -> tmf_api: CREATE: Resource Instance (Initial Status: Reseved)(associate to RFS)(add the MCJ UUID) -amq -> osom: CREATE: TMF628 Measurement Collection Job \nqueue:PM_MEASUREMENT_COLLECTION_JOB_ADD \npayload: MeasurementCollectionJob (Here I can find the MCJ ID) -tmf_api -> amq: PUBLISH EVENT: Monitoring Job Created\ntopic: PM_MEASUREMENT_COLLECTION_JOB_CREATED\npayload: Measurement Collection Job Ref -amq -> metrico: RECEIVE EVENT: Monitoring Job Created\ntopic: PM_MEASUREMENT_COLLECTION_JOB_CREATED\npayload: Measurement Collection Job Ref -metrico -> tmf_api: fetch Measurement Collection Job from ref -tmf_api -> metrico: fetch Measurement Collection Job from ref -metrico -> metrico: create METRICO job -metrico -> amq: UPDATE Measurement Collection Job Status +osom -> amq: Create TMF628 Measurement Collection Job Message \njms:queue:PM.MEASUREMENTCOLLECTIONJOB.ADD \npayload: MeasurementCollectionJobFVO +amq -> tmf_api: LISTENS FOR: Create TMF628 Measurement Collection Job Message \njms:queue:PM.MEASUREMENTCOLLECTIONJOB.ADD +tmf_api -> tmf_api: Create Measurement Collection Job (MCJ) +tmf_api -> amq: Publish Measurement Collection Job Creation Event\njms:topic:EVENT.MEASUREMENTCOLLECTIONJOB.CREATE\npayload: Measurement Collection Job Ref +tmf_api --> amq: RESPONSE: Create TMF628 Measurement Collection Job Message \njms:queue:PM.MEASUREMENTCOLLECTIONJOB.ADD \npayload: MeasurementCollectionJob (Includes MCJ ID) -group "java job" - metrico -> metrico : set how often job is done - metrico -> prom : send prom req - prom -> metrico : reply to prom req - metrico -> metrico : parse data from reply and cast them to data access endpoint +amq --> osom: RESPONSE: MeasurementCollectionJob +osom -> tmf_api: Update RFS \n(Characteristic _MT_MCJ_REFID = MCJ ID) \n(associate with RFS) + +amq -> metrico: LISTENS FOR: Measurement Collection Job Creation Event\njms:topic:EVENT.MEASUREMENTCOLLECTIONJOB.CREATE\npayload: Measurement Collection Job Ref +metrico -> amq: Retrieve Measurement Collection Job by ID\njms:queue:PM.MEASUREMENTCOLLECTIONJOB.GET_BY_ID\npayload: Measurement Collection Job ID + +amq -> tmf_api: LISTENS FOR: Retrieve Measurement Collection Job by ID\njms:queue:PM.MEASUREMENTCOLLECTIONJOB.GET_BY_ID +tmf_api --> amq: RESPONSE: Measurement Collection Job + +amq --> metrico: RESPONSE: Measurement Collection Job + +metrico -> metrico: create METRICO job from Measurement\nCollection Job and get its state + +metrico -> amq: Update Measurement Collection Job Message \njms:queue:PM.MEASUREMENTCOLLECTIONJOB.UPDATE\npayload: Measure Collection Job (update execution state) +amq -> tmf_api: LISTENS FOR: Update Measurement Collection Job Message \njms:queue:PM.MEASUREMENTCOLLECTIONJOB.UPDATE + +metrico -> amq: Retrieve Service by ID Message\njms:queue:CATALOG.GET.SERVICE\npayload: MCJ Producing Application ID (RFS ID) +amq -> tmf_api: LISTENS FOR: Retrieve Service by ID Message\njms:queue:CATALOG.GET.SERVICE +tmf_api --> amq: RESPONSE: Service (RFS with related Resource) +amq --> metrico: RESPONSE: Service (RFS with related Resource) + + +metrico -> amq: Update Resource Message\njms:queue:CATALOG.UPD.RESOURCE\npayload: Characteristic _MT_MCJ_REF = MCJ ID \n& Status = "AVAILABLE" +amq -> tmf_api: LISTENS FOR: Update Resource Message\njms:queue:CATALOG.UPD.RESOURCE +tmf_api --> amq: RESPONSE: Updated Resource +amq --> metrico: RESPONSE: Updated Resource + +group "METRICO job" + metrico -> metrico : Set job schedule and interval + metrico -> prom : Send Prometheus query + prom --> metrico : Prometheus response + + metrico -> amq : Update Service Message\njms:queue:CATALOG.UPD.SERVICE \npayload: Characteristic named MCJ.outputFormat \nis updated with Prometheus response + amq -> tmf_api: LISTENS FOR: Update Service Message\njms:queue:CATALOG.UPD.SERVICE - metrico -> amq : UPDATE: Related service to the Service Inventory\nqueue:jms:queue:CATALOG.UPD.SERVICE \npayload: ServiceUpdate, serviceId - amq -> tmf_api: UPDATE: Related service to the Service Inventory\nqueue:jms:queue:CATALOG.UPD.SERVICE \npayload: ServiceUpdate, serviceId end -@enduml \ No newline at end of file +tmf_api -> actor: Retrieve Monitoring data from the updated Service + +@enduml diff --git a/pom.xml b/pom.xml index 932fca3e36ba6295899c70f2e40199ff04a1c806..e64f8eab6ca3d3051c0863ce3632ce220208a743 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.etsi.osl org.etsi.osl.main - 2024Q4 + 2025Q2 ../org.etsi.osl.main @@ -29,7 +29,7 @@ 4.0.0-RC1 1.7.5 1.7.28 - ${mysql.connector.version} + 1.5.3.Final @@ -84,13 +84,27 @@ ${org.etsi.osl.centrallog.client.version} - + org.projectlombok lombok provided + + + org.mapstruct + mapstruct + ${mapstruct.version} + + + + org.mapstruct + mapstruct-processor + ${mapstruct.version} + + + org.springframework.boot spring-boot-starter @@ -188,14 +202,6 @@ slf4j-api - - mysql - mysql-connector-java - runtime - ${mysql-connector.version} - - - org.junit.jupiter @@ -208,11 +214,6 @@ 5.7.0 test - - com.h2database - h2 - test - org.springframework.boot spring-boot-test-autoconfigure @@ -226,8 +227,16 @@ test - org.springframework.data - spring-data-jpa + org.etsi.osl + org.etsi.osl.tmf.api + 1.2.0-SNAPSHOT + compile + + + org.apache.camel + camel-test-spring-junit5 + 3.20.2 + test @@ -251,6 +260,11 @@ lombok 1.18.28 + + org.mapstruct + mapstruct-processor + ${mapstruct.version} + diff --git a/src/main/java/org/etsi/osl/metrico/JsonUtil.java b/src/main/java/org/etsi/osl/metrico/JsonUtil.java index a801f496c5f22d232892748989ed761609770583..b22256bb3acc9c77f086171559f46a3297c4de62 100644 --- a/src/main/java/org/etsi/osl/metrico/JsonUtil.java +++ b/src/main/java/org/etsi/osl/metrico/JsonUtil.java @@ -3,7 +3,6 @@ package org.etsi.osl.metrico; import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; -import org.etsi.osl.tmf.pm628.model.MeasurementCollectionJobMVO; import java.io.IOException; @@ -16,6 +15,9 @@ public class JsonUtil { } public static String toJsonString(T object) { + if (object == null) { + return null; + } ObjectMapper mapper = new ObjectMapper(); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); try { diff --git a/src/main/java/org/etsi/osl/metrico/LocalMysqlDialect.java b/src/main/java/org/etsi/osl/metrico/LocalMysqlDialect.java deleted file mode 100644 index 1d8566cf19b079f1a5e574bb55443a0f4e6694cf..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/LocalMysqlDialect.java +++ /dev/null @@ -1,29 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * org.etsi.osl.tmf.api - * %% - * Copyright (C) 2019 openslice.io - * %% - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * =========================LICENSE_END================================== - */ -package org.etsi.osl.metrico; - -import org.hibernate.dialect.MySQLDialect; ; - -public class LocalMysqlDialect extends MySQLDialect { - @Override - public String getTableTypeString() { - return " DEFAULT CHARSET=utf8"; - } -} diff --git a/src/main/java/org/etsi/osl/metrico/MetricoCommonMethods.java b/src/main/java/org/etsi/osl/metrico/MetricoCommonMethods.java new file mode 100644 index 0000000000000000000000000000000000000000..b19467380f9450841aef0d07bb45a0a5988ce1f4 --- /dev/null +++ b/src/main/java/org/etsi/osl/metrico/MetricoCommonMethods.java @@ -0,0 +1,391 @@ +package org.etsi.osl.metrico; + +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.validation.constraints.NotNull; +import org.apache.camel.ProducerTemplate; +import org.apache.camel.builder.RouteBuilder; +import org.etsi.osl.tmf.common.model.Any; +import org.etsi.osl.tmf.common.model.service.ResourceRef; +import org.etsi.osl.tmf.pm628.model.ExecutionStateType; +import org.etsi.osl.tmf.pm628.model.MeasurementCollectionJob; +import org.etsi.osl.tmf.pm628.model.MeasurementCollectionJobMVO; +import org.etsi.osl.tmf.pm628.model.MeasurementCollectionJobRef; +import org.etsi.osl.tmf.rcm634.model.LogicalResourceSpecification; +import org.etsi.osl.tmf.rcm634.model.ResourceSpecificationCreate; +import org.etsi.osl.tmf.ri639.model.*; +import org.etsi.osl.tmf.scm633.model.ServiceSpecification; +import org.etsi.osl.tmf.sim638.model.Service; +import org.etsi.osl.tmf.sim638.model.ServiceUpdate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Component +public class MetricoCommonMethods extends RouteBuilder { + private static final Logger logger = LoggerFactory.getLogger(MetricoCommonMethods.class); + + @Value("${PM_MEASUREMENT_COLLECTION_JOB_UPDATE}") + private String PM_MEASUREMENT_COLLECTION_JOB_UPDATE = ""; + @Value("${PM_MEASUREMENT_COLLECTION_GET_JOB_BY_ID}") + private String PM_MEASUREMENT_COLLECTION_GET_JOB_BY_ID = ""; + @Value("${PM_MEASUREMENT_COLLECTION_JOBS_GET}") + private String PM_MEASUREMENT_COLLECTION_JOBS_GET = ""; + @Value("${CATALOG_GET_SERVICE_BY_ID}") + private String CATALOG_GET_SERVICE_BY_ID = ""; + @Value("${CATALOG_UPD_SERVICE}") + private String CATALOG_UPD_SERVICE = ""; + @Value("${CATALOG_GET_RESOURCE_BY_ID}") + private String CATALOG_GET_RESOURCE_BY_ID = ""; + @Value("${CATALOG_UPD_RESOURCE}") + private String CATALOG_UPD_RESOURCE = ""; + @Value("${CATALOG_UPDADD_RESOURCESPEC}") + private String CATALOG_UPDADD_RESOURCESPEC = ""; + @Value("${PM_MEASUREMENT_COLLECTION_JOB_GET_INPROGRESS_OR_PENDING}") + private String PM_MEASUREMENT_COLLECTION_JOB_GET_INPROGRESS_OR_PENDING; + @Value("${CATALOG_GET_SERVICESPEC_BY_ID}") + private String CATALOG_GET_SERVICESPEC_BY_ID = ""; + + + private ProducerTemplate template; + + public MetricoCommonMethods(ProducerTemplate template) { + this.template = template; + } + + @Override + public void configure() throws Exception { + // TODO Auto-generated method stub + } + + /** + * Retrieves a Measurement Collection Job from the database using the given job ID. + * + * @param mcjId the ID of the Measurement Collection Job to retrieve + * @return the retrieved Measurement Collection Job, or null if the job could not be retrieved + */ + public MeasurementCollectionJob retrieveMeasurementCollectionJob(String mcjId) { + + logger.debug("will retrieve Measurement Collection Job with mcjId = {}.", mcjId); + try { + Object response = template.requestBody(PM_MEASUREMENT_COLLECTION_GET_JOB_BY_ID, mcjId); + if (!(response instanceof String)) { + logger.error("Measurement Collection Job object is wrong."); + return null; + } + logger.debug("retrieveMeasurementCollectionJobById response is: " + response); + MeasurementCollectionJob mcj = JsonUtil.toJsonObj((String) response, MeasurementCollectionJob.class); + return mcj; + } catch (Exception e) { + logger.error("Cannot retrieve Measurement Collection Job details from database. " + e.toString()); + } + return null; + } + + /** + * Retrieves a Measurement Collection Job from the database using the given job reference. + * + * @param mcjRef the reference of the Measurement Collection Job to retrieve + * @return the retrieved Measurement Collection Job, or null if the job could not be retrieved + */ + public MeasurementCollectionJob retrieveMeasurementCollectionJob(MeasurementCollectionJobRef mcjRef) { + String mcjId = mcjRef.getId(); + + return retrieveMeasurementCollectionJob(mcjId); + } + + /** + * Retrieves a list of all Measurement Collection Jobs from the database. + * + * @return a list of all Measurement Collection Jobs, or null if the jobs could not be retrieved + */ + public List listMeasurementCollectionJob() { + + logger.debug("will retrieve all Measurement Collection Jobs from database"); + try { + Object response = template.requestBody(PM_MEASUREMENT_COLLECTION_JOBS_GET, ""); + if (!(response instanceof String)) { + logger.error("List object is wrong."); + return null; + } + logger.debug("listMeasurementCollectionJob response is: " + response); + //List allMcjs = JsonUtil.toJsonObj((String) response, List allMcjs = mapper.readValue((String) response, mapper.getTypeFactory().constructCollectionType(List.class, MeasurementCollectionJob.class)); + return allMcjs; + + } catch (Exception e) { + logger.error("Cannot retrieve Measurement Collection Job details from database: {}. ", e.toString()); + } + return null; + } + + /** + * Retrieves a list of Measurement Collection Jobs from the database that have an execution state of either Pending or InProgress. + * + * @return a list of unfinished Measurement Collection Jobs, or null if no jobs match the criteria or if an error occurs + */ + public ArrayList listPendingOrInProgressMeasurementCollectionJobs() { + logger.debug("===== Will try to retrieve Measurement Collection Jobs with ExecutionStateType Pending or InProgress from the database ===="); + + ArrayList pendingOrInProgressMeasurementCollectionJobs = null; + + try { + Object response = template.requestBody(PM_MEASUREMENT_COLLECTION_JOB_GET_INPROGRESS_OR_PENDING, ""); + + logger.debug("will retrieve Measurement Collection Jobs with Execution State " + ExecutionStateType.PENDING.toString() + " from catalog response: " + response.getClass()); + if (!(response instanceof String)) { + logger.error("===== List object is wrong ===="); + return null; + } else if (((String) response).isEmpty() || ((String) response).equals("[]")) { + logger.debug("===== No PENDING OR IN_PROGRESS Measurement Collection Jobs from previous sessions ====="); + return null; + } else { + logger.debug("listPendingOrInProgressMeasurementCollectionJobs response is: " + response); + + ObjectMapper objectMapper = new ObjectMapper(); + pendingOrInProgressMeasurementCollectionJobs = objectMapper.readValue( + (String) response, + objectMapper.getTypeFactory().constructCollectionType(ArrayList.class, MeasurementCollectionJob.class) + ); + + logger.info("===== Found PENDING or IN_PROGRESS Measurement Collection Jobs from previous sessions ====="); + } + } catch (Exception e) { + logger.error("Cannot retrieve/filter Measurement Collection Job details from the database. {}", e.toString()); + } + return pendingOrInProgressMeasurementCollectionJobs; + } + + + /** + * Updates the related resource state based on the given Measurement Collection Job. + * + * @param givenMCJ the Measurement Collection Job containing the related Service UUID and execution state + */ + public void updateRelatedResource(@NotNull MeasurementCollectionJob givenMCJ) { + if(givenMCJ.getExecutionState()==null){ + givenMCJ.setExecutionState(ExecutionStateType.PENDING); + } + String servUUID = givenMCJ.getProducingApplicationId();//this contains the related ServiceUUID with this MCJ + logger.debug("Update Resource related to Service with ServiceId {}.", servUUID); + Service aService = retrieveService(servUUID); + + if (aService != null && aService.getSupportingResource().size() > 0) { + ResourceRef resRef = aService.getSupportingResource().stream().findFirst().get(); + logger.debug("Update Resource with ResourceId {}.", resRef.getId()); + + ResourceUpdate rup = new ResourceUpdate(); + Characteristic resCharacteristicItem = new Characteristic(); + resCharacteristicItem.setName("_MT_MCJ_REF"); + resCharacteristicItem.setValueType("TEXT"); + Any val = new Any(); + val.setValue(givenMCJ.getUuid()); + val.setAlias(""); + resCharacteristicItem.setValue(val); + rup.addResourceCharacteristicItem(resCharacteristicItem); + + if (givenMCJ.getExecutionState().equals(ExecutionStateType.FAILED)) { + rup.setResourceStatus(ResourceStatusType.SUSPENDED); + } else { + rup.setResourceStatus(ResourceStatusType.AVAILABLE); + } + updateResourceById(resRef.getId(), rup); + } else { + logger.error("No related Resource found for Service with Service Id {}.", servUUID); + } + } + + + /** + * Creates or updates a LogicalResourceSpecification in the catalog using the given name, category, and version. + * + * @param s the ResourceSpecificationCreate object containing the specification details + * @return the created or updated LogicalResourceSpecification instance, or null if the operation failed + */ + public LogicalResourceSpecification createOrUpdateResourceSpecByNameCategoryVersion(ResourceSpecificationCreate s) { + logger.info("==== Will try to Create or Update a Resource Specification for METRICO ===="); + try { + Map map = new HashMap<>(); + map.put("aname", s.getName()); + map.put("aversion", s.getVersion()); + map.put("acategory", s.getCategory()); + logger.info("will createOrUpdateResourceSpecByNameCategoryVersion "); + Object response = template.requestBodyAndHeaders(CATALOG_UPDADD_RESOURCESPEC, JsonUtil.toJsonString(s), map); + assert response instanceof String : "ResourceSpecification object is wrong."; + LogicalResourceSpecification rs = JsonUtil.toJsonObj((String) response, LogicalResourceSpecification.class); + logger.info("==== Created or Updated a Resource Specification for METRICO ===="); + return rs; + } catch (Exception e) { + logger.error("Cannot create ResourceSpecification"); + e.printStackTrace(); + } + return null; + } + + + /** + * Updates a Service in the catalog using the given service ID and update information. + * + * @param serviceId the ID of the service to update + * @param serviceUpdate the update information for the service + * @param triggerServiceActionQueue flag to trigger the service action queue + * @return the updated Service instance, or null if the service could not be updated + */ + public Service updateService(String serviceId, ServiceUpdate serviceUpdate, boolean triggerServiceActionQueue) { + logger.info("will update Service : " + serviceId); + try { + Map map = new HashMap<>(); + map.put("serviceid", serviceId); + map.put("triggerServiceActionQueue", triggerServiceActionQueue); + + Object response = template.requestBodyAndHeaders(CATALOG_UPD_SERVICE, JsonUtil.toJsonString(serviceUpdate), map); + + assert response instanceof String : "Service Instance object is wrong."; + Service serviceInstance = JsonUtil.toJsonObj((String) response, Service.class); + return serviceInstance; + + + } catch (Exception e) { + logger.error("Cannot update Service with serviceId {} : {}", serviceId, e.toString()); + } + return null; + + } + + /** + * Updates a Resource in the catalog using the given resource ID and update information. + * + * @param oslResourceId the ID of the resource to update + * @param rs the update information for the resource + * @return the updated LogicalResource instance, or null if the resource could not be updated + */ + public Resource updateResourceById(String oslResourceId, ResourceUpdate rs) { + logger.debug("will update Resource with id: " + oslResourceId); + try { + Map map = new HashMap<>(); + map.put("resourceId", oslResourceId); + map.put("triggerServiceActionQueue", false); + + Object response = template.requestBodyAndHeaders(CATALOG_UPD_RESOURCE, JsonUtil.toJsonString(rs), map); + assert response instanceof String : "Service Instance object is wrong."; + LogicalResource resourceInstance = JsonUtil.toJsonObj((String) response, LogicalResource.class); + return resourceInstance; + } catch (Exception e) { + e.printStackTrace(); + logger.error("Cannot update Service with id {} : {} ", oslResourceId, e.toString()); + } + return null; + } + + + /** + * Retrieves a Service instance from the catalog using the given service ID. + * + * @param serviceID the ID of the service to retrieve + * @return the retrieved Service instance, or null if the service could not be retrieved + */ + public Service retrieveService(String serviceID) { + logger.info("will retrieve Service instance from catalog serviceID=" + serviceID); + try { + Object response = template.requestBody(CATALOG_GET_SERVICE_BY_ID, serviceID); + + if (!(response instanceof String)) { + logger.error("Service object is wrong."); + return null; + } + return JsonUtil.toJsonObj((String) response, Service.class); + + } catch (Exception e) { + logger.error("Cannot retrieve Service details from catalog. " + e.toString()); + } + return null; + } + + + /** + * Retrieves a Resource instance from the catalog using the given resource ID. + * + * @param resourceID the ID of the resource to retrieve + * @return the retrieved LogicalResource instance, or null if the resource could not be retrieved + */ + public Resource retrieveResource(@NotNull String resourceID) { + logger.info("will retrieve Resource instance from catalog: resourceID = {}", resourceID); + try { + Object response = template.requestBody(CATALOG_GET_RESOURCE_BY_ID, resourceID); + + if (!(response instanceof String)) { + logger.error("resource object is wrong."); + return null; + } + LogicalResource resourceInstance = JsonUtil.toJsonObj((String) response, LogicalResource.class); + + return resourceInstance; + + } catch (Exception e) { + logger.error("Cannot retrieve LogicalResource details from catalog. {}", e.toString()); + } + return null; + + } + + + /** + * Updates a Measurement Collection Job in the database using the given job ID and update information. + * + * @param mcjId the ID of the Measurement Collection Job to update + * @param mcjMVO the update information for the Measurement Collection Job + * @return the updated Measurement Collection Job, or null if the job could not be updated + */ + public MeasurementCollectionJob updateMeasurementCollectionJobById(String mcjId, MeasurementCollectionJobMVO mcjMVO) { + MeasurementCollectionJob measurementCollectionJob; + logger.debug("will update MeasurementCollectionJob with id {} and \nMeasurementCollectionJobMVO.toString():\n{}", mcjId, JsonUtil.toJsonString(mcjMVO)); + + try { + Map map = new HashMap<>(); + map.put("mcjid", mcjId); + + Object response = template.requestBodyAndHeaders(PM_MEASUREMENT_COLLECTION_JOB_UPDATE, JsonUtil.toJsonString(mcjMVO), map); + logger.debug("JsonUtil.toJsonString(mcjMVO): \n{}", JsonUtil.toJsonString(mcjMVO)); + if (!(response instanceof String)) { + logger.error("MeasurementCollectionJob object is wrong."); + return null; + } + measurementCollectionJob = JsonUtil.toJsonObj((String) response, MeasurementCollectionJob.class); + logger.info("response from PM_MEASUREMENT_COLLECTION_JOB_UPDATE: \n{}", response); + return measurementCollectionJob; + } catch (Exception e) { + e.printStackTrace(); + logger.error("Cannot update MeasurementCollectionJob with id {} : {}", mcjId, e.toString()); + } + return null; + } + + public ServiceSpecification retrieveServiceSpecificationById(String serviceSpecId) { + + logger.debug("will retrieve Service Specification with id = {}.", serviceSpecId); + try { + Object response = template.requestBody(CATALOG_GET_SERVICESPEC_BY_ID, serviceSpecId); + if (!(response instanceof String)) { + logger.error("Service Specification object is wrong."); + return null; + } + logger.debug("retrieveServiceSpecificationById response is: {}", response); + ServiceSpecification serviceSpec = JsonUtil.toJsonObj((String) response, ServiceSpecification.class); + return serviceSpec; + } catch (Exception e) { + logger.error("Cannot retrieve Service Specification details from database. " + e.toString()); + } + return null; + } + + public boolean notNullOrEmpty(String str) { + return str != null && !str.isEmpty(); + } + +} diff --git a/src/main/java/org/etsi/osl/metrico/MetricoSpringBoot.java b/src/main/java/org/etsi/osl/metrico/MetricoSpringBoot.java index 1040f0d5d3c861295cfe551fff73ba0c46cb3643..6c361e8adc91f1f33fe86c03ab3bf0ca0a8ad25c 100644 --- a/src/main/java/org/etsi/osl/metrico/MetricoSpringBoot.java +++ b/src/main/java/org/etsi/osl/metrico/MetricoSpringBoot.java @@ -1,75 +1,48 @@ package org.etsi.osl.metrico; -import org.etsi.osl.metrico.services.MetricoService; -import org.etsi.osl.tmf.pm628.model.MeasurementCollectionJob; -import org.etsi.osl.tmf.pm628.model.MeasurementCollectionJobRef; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.boot.ExitCodeGenerator; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.domain.EntityScan; -import org.springframework.boot.context.event.ApplicationStartedEvent; import org.springframework.context.ApplicationContext; -import org.springframework.context.event.EventListener; -import org.springframework.data.jpa.repository.config.EnableJpaRepositories; -import jakarta.validation.constraints.NotNull; @SpringBootApplication -@EnableJpaRepositories("org.etsi.osl.metrico.repo") -@EntityScan( basePackages = { - "org.etsi.osl.metrico.repo", - "org.etsi.osl.metrico.model", +@EntityScan(basePackages = { "org.etsi.osl.metrico", - "org.etsi.osl.metrico.reposervices", + "org.etsi.osl.metrico.mapper", + "org.etsi.osl.metrico.model", + "org.etsi.osl.metrico.prometheus", "org.etsi.osl.metrico.services" }) - public class MetricoSpringBoot implements CommandLineRunner { +public class MetricoSpringBoot implements CommandLineRunner { - private static final Logger logger = - LoggerFactory.getLogger(MetricoSpringBoot.class.getSimpleName()); - -// -// @Autowired -// private MetricoService aMetricoService; - - - @Override - public void run(String... arg0) { - if (arg0.length > 0 && arg0[0].equals("exitcode")) { - throw new ExitException(); - } - + private static final Logger logger = LoggerFactory.getLogger(MetricoSpringBoot.class.getSimpleName()); -// @NotNull -// MeasurementCollectionJob mcj = new MeasurementCollectionJob(); -// -// @NotNull -// MeasurementCollectionJobRef mjref = new MeasurementCollectionJobRef(); -// mjref.setId("268cd191-21ac-4a81-84d8-933445a65ec1"); -// aMetricoService.startPeriodicQueryToPrometheusRef(mjref ); - } - + public static void main(String[] args) { + logger.info("============================== STARTING METRICO =============================="); + ApplicationContext applicationContext = new SpringApplication(MetricoSpringBoot.class).run(args); - public static void main(String[] args) { - logger.info("============================== STARTING METRICO =============================="); - ApplicationContext applicationContext = new SpringApplication(MetricoSpringBoot.class).run(args); - - - - - } + } - static class ExitException extends RuntimeException implements ExitCodeGenerator { - private static final long serialVersionUID = 1L; @Override - public int getExitCode() { - return 10; + public void run(String... arg0) { + if (arg0.length > 0 && arg0[0].equals("exitcode")) { + throw new ExitException(); + } + } + + static class ExitException extends RuntimeException implements ExitCodeGenerator { + private static final long serialVersionUID = 1L; + + @Override + public int getExitCode() { + return 10; + } } - } } diff --git a/src/main/java/org/etsi/osl/metrico/mapper/AttachmentRefMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/AttachmentRefMapper.java deleted file mode 100644 index f5138b6a7b033e0c4b3328f1b82c3af07d4af825..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/AttachmentRefMapper.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.common.model.AttachmentRef; -import org.etsi.osl.tmf.pm628.model.AttachmentRefMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface AttachmentRefMapper { - AttachmentRefMapper INSTANCE = Mappers.getMapper(AttachmentRefMapper.class); - - @Mapping(source = "id", target = "id") - @Mapping(source = "description", target = "description") - @Mapping(source = "url", target = "url") - @Mapping(source = "referredType", target = "referredType") - @Mapping(source = "type", target = "type") - @Mapping(source = "atBaseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "href", target = "href") - AttachmentRef toAttachmentRef(AttachmentRefMVO attachmentRefMVO); - - @Mapping(source = "id", target = "id") - @Mapping(source = "description", target = "description") - @Mapping(source = "url", target = "url") - @Mapping(source = "referredType", target = "referredType") - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "href", target = "href") - AttachmentRefMVO toAttachmentRefMVO(AttachmentRef attachmentRef); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/CharacteristicMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/CharacteristicMapper.java deleted file mode 100644 index 8aebd1e460cebb387b198531bfa110feea5e3035..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/CharacteristicMapper.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.pm628.model.Characteristic; -import org.etsi.osl.tmf.pm628.model.CharacteristicMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper(uses = {CharacteristicRelationshipMapper.class}) -public interface CharacteristicMapper { - CharacteristicMapper INSTANCE = Mappers.getMapper(CharacteristicMapper.class); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "uuid", target = "uuid") - @Mapping(source = "name", target = "name") - @Mapping(source = "valueType", target = "valueType") - @Mapping(source = "characteristicRelationship", target = "characteristicRelationship") - Characteristic toCharacteristic(CharacteristicMVO characteristicMVO); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "uuid", target = "uuid") - @Mapping(source = "name", target = "name") - @Mapping(source = "valueType", target = "valueType") - @Mapping(source = "characteristicRelationship", target = "characteristicRelationship") - CharacteristicMVO toCharacteristicMVO(Characteristic characteristic); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/CharacteristicRelationshipMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/CharacteristicRelationshipMapper.java deleted file mode 100644 index 00d87e52254b760e9bc54c65cf84798fc8cf296d..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/CharacteristicRelationshipMapper.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.pm628.model.CharacteristicRelationship; -import org.etsi.osl.tmf.pm628.model.CharacteristicRelationshipMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface CharacteristicRelationshipMapper { - CharacteristicRelationshipMapper INSTANCE = Mappers.getMapper(CharacteristicRelationshipMapper.class); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "uuid", target = "uuid") - @Mapping(source = "relationshipType", target = "relationshipType") - CharacteristicRelationship toCharacteristicRelationship(CharacteristicRelationshipMVO characteristicRelationshipMVO); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "uuid", target = "uuid") - @Mapping(source = "relationshipType", target = "relationshipType") - CharacteristicRelationshipMVO toCharacteristicRelationshipMVO(CharacteristicRelationship characteristicRelationship); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/DataAccessEndpointMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/DataAccessEndpointMapper.java index 96188c5cfea4f9507820c31c0d7d00ad19e1af24..e2fc0ca888cc5580604a5eeaa749bde056cde914 100644 --- a/src/main/java/org/etsi/osl/metrico/mapper/DataAccessEndpointMapper.java +++ b/src/main/java/org/etsi/osl/metrico/mapper/DataAccessEndpointMapper.java @@ -1,45 +1,28 @@ package org.etsi.osl.metrico.mapper; import org.etsi.osl.tmf.pm628.model.DataAccessEndpoint; +import org.etsi.osl.tmf.pm628.model.DataAccessEndpointFVO; import org.etsi.osl.tmf.pm628.model.DataAccessEndpointMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; +import org.mapstruct.*; -@Mapper +@Mapper( + nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT, + nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, + collectionMappingStrategy = CollectionMappingStrategy.ACCESSOR_ONLY, // Collection- or map-typed properties of the target bean to be updated will be cleared and then populated with the values from the corresponding source collection or map + uses = { + PartyRefOrPartyRoleRefMapper.class, + ResourceRefOrValueMapper.class + } +) public interface DataAccessEndpointMapper { - DataAccessEndpointMapper INSTANCE = Mappers.getMapper(DataAccessEndpointMapper.class); - @Mapping(target = "type", source = "type") - @Mapping(target = "baseType", source = "baseType") - @Mapping(target = "schemaLocation", source = "schemaLocation") - @Mapping(target = "href", source = "href") - @Mapping(target = "uuid", source = "uuid") - @Mapping(target = "category", source = "category") - @Mapping(target = "description", source = "description") - @Mapping(target = "name", source = "name") - @Mapping(target = "endOperatingDate", source = "endOperatingDate") - @Mapping(target = "administrativeState", source = "administrativeState") - @Mapping(target = "operationalState", source = "operationalState") - @Mapping(target = "resourceStatus", source = "resourceStatus") - @Mapping(target = "usageState", source = "usageState") - @Mapping(target = "validFor", source = "validFor") - @Mapping(target = "note", source = "note") - @Mapping(target = "resourceOrderItem", source = "resourceOrderItem") - @Mapping(target = "place", source = "place") - @Mapping(target = "relatedParty", source = "relatedParty") - @Mapping(target = "resourceRelationship", source = "resourceRelationship") - @Mapping(target = "resourceCharacteristic", source = "resourceCharacteristic") - @Mapping(target = "attachment", source = "attachment") - @Mapping(target = "resourceSpecification", source = "resourceSpecification") - @Mapping(target = "startOperatingDate", source = "startOperatingDate") - @Mapping(target = "resourceVersion", source = "resourceVersion") - @Mapping(target = "activationFeature", source = "activationFeature") - @Mapping(target = "intent", source = "intent") - @Mapping(target = "externalIdentifier", source = "externalIdentifier") - @Mapping(target = "value", source = "value") - @Mapping(target = "uri", source = "uri") - @Mapping(target = "uriQueryFilter", source = "uriQueryFilter") - @Mapping(target = "apiType", source = "apiType") - DataAccessEndpointMVO toDataAccessEndpointMVO(DataAccessEndpoint dataAccessEndpoint); + DataAccessEndpoint createDataAccessEndpoint(DataAccessEndpointFVO dataAccessEndpointFVO); + + @Mapping(target = "type", ignore = true) + @Mapping(target = "baseType", ignore = true) + @Mapping(target = "schemaLocation", ignore = true) + @Mapping(target = "href", ignore = true) + @Mapping(target = "uuid", ignore = true) + @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) + DataAccessEndpoint updateDataAccessEndpoint(DataAccessEndpointMVO dataAccessEndpointMVO, @MappingTarget DataAccessEndpoint dataAccessEndpoint); } \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/DataFilterMapItemMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/DataFilterMapItemMapper.java deleted file mode 100644 index cc2586162422c2d00476d84e6cbc4732ad4745b5..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/DataFilterMapItemMapper.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.pm628.model.DataFilterMapItem; -import org.etsi.osl.tmf.pm628.model.DataFilterMapItemMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -//@Mapper(uses = { -// DataFilterTemplateMapper.class, -// DataFilterAttributeStringArrayMapper.class -//}) -public interface DataFilterMapItemMapper { - DataFilterMapItemMapper INSTANCE = Mappers.getMapper(DataFilterMapItemMapper.class); - - @Mapping(source = "filterTemplate", target = "filterTemplate") - @Mapping(source = "stringArray", target = "stringArray") - DataFilterMapItem toDataFilterMapItem(DataFilterMapItemMVO dataFilterMapItemMVO); - - @Mapping(source = "filterTemplate", target = "filterTemplate") - @Mapping(source = "stringArray", target = "stringArray") - DataFilterMapItemMVO toDataFilterMapItemMVO(DataFilterMapItem dataFilterMapItem); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/DataFilterMapMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/DataFilterMapMapper.java deleted file mode 100644 index a61597f5734fdd99c0dfac7fbfc724afe77b670f..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/DataFilterMapMapper.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.pm628.model.DataFilterMap; -import org.etsi.osl.tmf.pm628.model.DataFilterMapMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper(uses = { - DataFilterMapItemMapper.class -}) -public interface DataFilterMapMapper { - DataFilterMapMapper INSTANCE = Mappers.getMapper(DataFilterMapMapper.class); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "mappings", target = "mappings") - DataFilterMap toDataFilterMap(DataFilterMapMVO dataFilterMapMVO); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "mappings", target = "mappings") - DataFilterMapMVO toDataFilterMapMVO(DataFilterMap dataFilterMap); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/DataFilterTemplateMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/DataFilterTemplateMapper.java deleted file mode 100644 index 64c4f110dfd4703f65a71027844c3aaba60502ea..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/DataFilterTemplateMapper.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.pm628.model.DataFilterTemplate; -import org.etsi.osl.tmf.pm628.model.DataFilterTemplateMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface DataFilterTemplateMapper { - DataFilterTemplateMapper INSTANCE = Mappers.getMapper(DataFilterTemplateMapper.class); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "id", target = "id") - @Mapping(source = "href", target = "href") - @Mapping(source = "name", target = "name") - @Mapping(source = "description", target = "description") - DataFilterTemplate toDataFilterTemplate(DataFilterTemplateMVO dataFilterTemplateMVO); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "id", target = "id") - @Mapping(source = "href", target = "href") - @Mapping(source = "name", target = "name") - @Mapping(source = "description", target = "description") - DataFilterTemplateMVO toDataFilterTemplateMVO(DataFilterTemplate dataFilterTemplate); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/DayOfMonthRecurrenceMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/DayOfMonthRecurrenceMapper.java deleted file mode 100644 index 62836b015fc418e2f0530d81898212830fc997dc..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/DayOfMonthRecurrenceMapper.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.pm628.model.DayOfMonthRecurrence; -import org.etsi.osl.tmf.pm628.model.DayOfMonthRecurrenceMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface DayOfMonthRecurrenceMapper { - DayOfMonthRecurrenceMapper INSTANCE = Mappers.getMapper(DayOfMonthRecurrenceMapper.class); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "dates", target = "dates") - DayOfMonthRecurrence toDayOfMonthRecurrence(DayOfMonthRecurrenceMVO dayOfMonthRecurrenceMVO); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "dates", target = "dates") - DayOfMonthRecurrenceMVO toDayOfMonthRecurrenceMVO(DayOfMonthRecurrence dayOfMonthRecurrence); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/DayOfWeekRecurrenceMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/DayOfWeekRecurrenceMapper.java deleted file mode 100644 index a4b857d59ddb3d26f8cce251977cc89eb59f94d9..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/DayOfWeekRecurrenceMapper.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.pm628.model.DayOfWeekRecurrence; -import org.etsi.osl.tmf.pm628.model.DayOfWeekRecurrenceMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface DayOfWeekRecurrenceMapper { - DayOfWeekRecurrenceMapper INSTANCE = Mappers.getMapper(DayOfWeekRecurrenceMapper.class); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "dates", target = "dates") - DayOfWeekRecurrence toDayOfWeekRecurrence(DayOfWeekRecurrenceMVO dayOfWeekRecurrenceMVO); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "dates", target = "dates") - DayOfWeekRecurrenceMVO toDayOfWeekRecurrenceMVO(DayOfWeekRecurrence dayOfWeekRecurrence); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/ExternalIdentifierMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/ExternalIdentifierMapper.java deleted file mode 100644 index 0e825648d205cfe94d3cb5b264c3dd1a7fa44ad1..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/ExternalIdentifierMapper.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.pm628.model.ExternalIdentifier; -import org.etsi.osl.tmf.pm628.model.ExternalIdentifierMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface ExternalIdentifierMapper { - ExternalIdentifierMapper INSTANCE = Mappers.getMapper(ExternalIdentifierMapper.class); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "owner", target = "owner") - @Mapping(source = "externalIdentifierType", target = "externalIdentifierType") - @Mapping(source = "id", target = "id") - ExternalIdentifier toExternalIdentifier(ExternalIdentifierMVO externalIdentifierMVO); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "owner", target = "owner") - @Mapping(source = "externalIdentifierType", target = "externalIdentifierType") - @Mapping(source = "id", target = "id") - ExternalIdentifierMVO toExternalIdentifierMVO(ExternalIdentifier externalIdentifier); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/FeatureMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/FeatureMapper.java deleted file mode 100644 index fff7bcdb75fe934e833ff719c4bdaa092e393466..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/FeatureMapper.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.pm628.model.Feature; -import org.etsi.osl.tmf.pm628.model.FeatureMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface FeatureMapper { - FeatureMapper INSTANCE = Mappers.getMapper(FeatureMapper.class); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "name", target = "name") - @Mapping(source = "isBundle", target = "isBundle") - @Mapping(source = "featureRelationship", target = "featureRelationship") - @Mapping(source = "featureCharacteristic", target = "featureCharacteristic") - @Mapping(source = "policyConstraint", target = "policyConstraint") - @Mapping(source = "isEnabled", target = "isEnabled") - Feature toFeature(FeatureMVO featureMVO); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "name", target = "name") - @Mapping(source = "isBundle", target = "isBundle") - @Mapping(source = "featureRelationship", target = "featureRelationship") - @Mapping(source = "featureCharacteristic", target = "featureCharacteristic") - @Mapping(source = "policyConstraint", target = "policyConstraint") - @Mapping(source = "isEnabled", target = "isEnabled") - FeatureMVO toFeatureMVO(Feature feature); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/FileTransferDataMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/FileTransferDataMapper.java deleted file mode 100644 index 33f90d79b712cc7cd2c0394163d31c7b5aa300a0..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/FileTransferDataMapper.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.pm628.model.FileTransferData; -import org.etsi.osl.tmf.pm628.model.FileTransferDataMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface FileTransferDataMapper { - FileTransferDataMapper INSTANCE = Mappers.getMapper(FileTransferDataMapper.class); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "fileLocation", target = "fileLocation") - @Mapping(source = "fileFormat", target = "fileFormat") - @Mapping(source = "compressionType", target = "compressionType") - @Mapping(source = "retentionPeriod", target = "retentionPeriod") - @Mapping(source = "packingType", target = "packingType") - FileTransferDataMVO toFileTransferDataMVO(FileTransferData fileTransferData); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "fileLocation", target = "fileLocation") - @Mapping(source = "fileFormat", target = "fileFormat") - @Mapping(source = "compressionType", target = "compressionType") - @Mapping(source = "retentionPeriod", target = "retentionPeriod") - @Mapping(source = "packingType", target = "packingType") - FileTransferData toFileTransferData(FileTransferDataMVO fileTransferDataMVO); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/IntentRefMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/IntentRefMapper.java deleted file mode 100644 index f631d622522ed4fff54a8e4a3bf391592595a9a8..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/IntentRefMapper.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.pm628.model.IntentRef; -import org.etsi.osl.tmf.pm628.model.IntentRefMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface IntentRefMapper { - IntentRefMapper INSTANCE = Mappers.getMapper(IntentRefMapper.class); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "href", target = "href") - @Mapping(source = "id", target = "id") - @Mapping(source = "name", target = "name") - @Mapping(source = "referredType", target = "referredType") - IntentRef toIntentRef(IntentRefMVO intentRefMVO); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "href", target = "href") - @Mapping(source = "id", target = "id") - @Mapping(source = "name", target = "name") - @Mapping(source = "referredType", target = "referredType") - IntentRefMVO toIntentRefMVO(IntentRef intentRef); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/JobMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/JobMapper.java index 0597011eb7e51f6691cf84307bb924a00f9309ab..13083ede4f345ad6f03595e8e68ca0fa827c394d 100644 --- a/src/main/java/org/etsi/osl/metrico/mapper/JobMapper.java +++ b/src/main/java/org/etsi/osl/metrico/mapper/JobMapper.java @@ -1,12 +1,15 @@ package org.etsi.osl.metrico.mapper; -import jakarta.validation.Valid; import org.etsi.osl.metrico.model.Job; import org.etsi.osl.metrico.model.SupportedDataAccessEndpoints; -import org.etsi.osl.tmf.pm628.model.*; +import org.etsi.osl.tmf.pm628.model.DataAccessEndpoint; +import org.etsi.osl.tmf.pm628.model.Granularity; +import org.etsi.osl.tmf.pm628.model.MeasurementCollectionJob; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -60,14 +63,27 @@ public class JobMapper { job.setEndDateTime(measurementCollectionJob.getScheduleDefinition().get(0).getScheduleDefinitionEndTime()); } + if (job.getStartDateTime() == null) { + job.setStartDateTime(OffsetDateTime.now()); + } else if (job.getEndDateTime().getOffset() != ZoneOffset.UTC) { + OffsetDateTime startDateTimeUTC = job.getStartDateTime().withOffsetSameInstant(ZoneOffset.UTC); + job.setStartDateTime(startDateTimeUTC); + } + + if (job.getEndDateTime() == null) { + job.setEndDateTime(job.getStartDateTime().plusHours(1)); + } else if (job.getEndDateTime().getOffset() != ZoneOffset.UTC) { + OffsetDateTime endDateTimeUTC = job.getEndDateTime().withOffsetSameInstant(ZoneOffset.UTC); + job.setEndDateTime(endDateTimeUTC); + } + if (measurementCollectionJob.getGranularity() != null){ Granularity granularity = measurementCollectionJob.getGranularity(); job.setExecutionInterval(convertGranularityToSeconds(granularity.getValue())); } - - logger.atDebug().setMessage("Received MeasurementCollectionJob:\n" + measurementCollectionJob + "\nConverted it to Job:\n" + job).log(); + logger.atDebug().setMessage("Received MeasurementCollectionJob and converted it to Job").log(); return job; } diff --git a/src/main/java/org/etsi/osl/metrico/mapper/LogicalResourceMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/LogicalResourceMapper.java deleted file mode 100644 index 181ecc2e6b9fbfb38a16231ec7f5ef61e9a2f8f0..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/LogicalResourceMapper.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.pm628.model.LogicalResource; -import org.etsi.osl.tmf.pm628.model.LogicalResourceMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper(uses = ResourceMapper.class) -public interface LogicalResourceMapper { - LogicalResourceMapper INSTANCE = Mappers.getMapper(LogicalResourceMapper.class); - - @Mapping(source = "value", target = "value") - LogicalResource toLogicalResource(LogicalResourceMVO logicalResourceMVO); - - @Mapping(source = "value", target = "value") - LogicalResourceMVO toLogicalResourceMVO(LogicalResource logicalResource); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/ManagementJobMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/ManagementJobMapper.java deleted file mode 100644 index c0ba58e3c843cf86c8504181061ff6531a012b5f..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/ManagementJobMapper.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.pm628.model.ManagementJob; -import org.etsi.osl.tmf.pm628.model.ManagementJobMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper(uses = { - FileTransferDataMapper.class, - DataAccessEndpointMapper.class, - ScheduleDefinitionMapper.class -}) -public interface ManagementJobMapper { - ManagementJobMapper INSTANCE = Mappers.getMapper(ManagementJobMapper.class); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "href", target = "href") - @Mapping(source = "uuid", target = "uuid") - @Mapping(source = "fileTransferData", target = "fileTransferData") - @Mapping(source = "dataAccessEndpoint", target = "dataAccessEndpoint") - @Mapping(source = "scheduleDefinition", target = "scheduleDefinition") - ManagementJob toManagementJob(ManagementJobMVO managementJobMVO); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "href", target = "href") - @Mapping(source = "uuid", target = "uuid") - @Mapping(source = "fileTransferData", target = "fileTransferData") - @Mapping(source = "dataAccessEndpoint", target = "dataAccessEndpoint") - @Mapping(source = "scheduleDefinition", target = "scheduleDefinition") - ManagementJobMVO toManagementJobMVO(ManagementJob managementJob); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/MeasurementCollectionJobMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/MeasurementCollectionJobMapper.java index 5238a66dfab581253df29ade7c5c8e73521dc185..acd02b8c9862cb0df7554fb048576a328847b9ce 100644 --- a/src/main/java/org/etsi/osl/metrico/mapper/MeasurementCollectionJobMapper.java +++ b/src/main/java/org/etsi/osl/metrico/mapper/MeasurementCollectionJobMapper.java @@ -1,44 +1,42 @@ package org.etsi.osl.metrico.mapper; -import org.etsi.osl.tmf.pm628.model.MeasurementCollectionJob; -import org.etsi.osl.tmf.pm628.model.MeasurementCollectionJobMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; +import org.etsi.osl.tmf.pm628.model.*; +import org.mapstruct.*; -@Mapper(uses = { - DataFilterMapMapper.class, - PerformanceIndicatorGroupSpecificationMapper.class, - PerformanceIndicatorSpecificationRefOrValueMapper.class, - TrackingRecordMapper.class, - FileTransferDataMapper.class, - DataAccessEndpointMapper.class, - ScheduleDefinitionMapper.class -}) +import java.util.List; + +@Mapper( + nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT, + nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, + collectionMappingStrategy = CollectionMappingStrategy.ACCESSOR_ONLY, // Collection- or map-typed properties of the target bean to be updated will be cleared and then populated with the values from the corresponding source collection or map + uses = { + PerformanceIndicatorSpecificationRefOrValueMapper.class, + PartyRefOrPartyRoleRefMapper.class, + ResourceRefOrValueMapper.class + } +) public interface MeasurementCollectionJobMapper { - MeasurementCollectionJobMapper INSTANCE = Mappers.getMapper(MeasurementCollectionJobMapper.class); - @Mapping(source = "reportingPeriod", target = "reportingPeriod") - @Mapping(source = "jobCollectionFilter", target = "jobCollectionFilter") - @Mapping(source = "searchTaskFilter", target = "searchTaskFilter") - @Mapping(source = "jobOnDemand", target = "jobOnDemand") - @Mapping(source = "performanceIndicatorGroupSpecification", target = "performanceIndicatorGroupSpecification") - @Mapping(source = "performanceIndicatorSpecification", target = "performanceIndicatorSpecification") - @Mapping(source = "trackingRecord", target = "trackingRecord") - @Mapping(source = "fileTransferData", target = "fileTransferData") - @Mapping(source = "dataAccessEndpoint", target = "dataAccessEndpoint") - @Mapping(source = "scheduleDefinition", target = "scheduleDefinition") - MeasurementCollectionJob toMeasurementCollectionJob(MeasurementCollectionJobMVO measurementCollectionJobMVO); + MeasurementCollectionJob createMeasurementCollectionJob(MeasurementCollectionJobFVO measurementCollectionJobFVO); + + @Mapping(target = "type", ignore = true) + @Mapping(target = "baseType", ignore = true) + @Mapping(target = "schemaLocation", ignore = true) + @Mapping(target = "href", ignore = true) + @Mapping(target = "uuid", ignore = true) + @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) + MeasurementCollectionJob updateMeasurementCollectionJob(MeasurementCollectionJobMVO measurementCollectionJobMVO, @MappingTarget MeasurementCollectionJob measurementCollectionJob); - @Mapping(source = "reportingPeriod", target = "reportingPeriod") - @Mapping(source = "jobCollectionFilter", target = "jobCollectionFilter") - @Mapping(source = "searchTaskFilter", target = "searchTaskFilter") - @Mapping(source = "jobOnDemand", target = "jobOnDemand") - @Mapping(source = "performanceIndicatorGroupSpecification", target = "performanceIndicatorGroupSpecification") - @Mapping(source = "performanceIndicatorSpecification", target = "performanceIndicatorSpecification") - @Mapping(source = "trackingRecord", target = "trackingRecord") - @Mapping(source = "fileTransferData", target = "fileTransferData") - @Mapping(source = "dataAccessEndpoint", target = "dataAccessEndpoint") - @Mapping(source = "scheduleDefinition", target = "scheduleDefinition") - MeasurementCollectionJobMVO toMeasurementCollectionJobMVO(MeasurementCollectionJob measurementCollectionJob); -} \ No newline at end of file + @IterableMapping(nullValueMappingStrategy = NullValueMappingStrategy.RETURN_NULL) + List dataAccessEndpointMVOListToDataAccessEndpointList(List list); + @IterableMapping(nullValueMappingStrategy = NullValueMappingStrategy.RETURN_NULL) + List performanceIndicatorGroupSpecificationMVOListToPerformanceIndicatorGroupSpecificationList(List list); + @IterableMapping(nullValueMappingStrategy = NullValueMappingStrategy.RETURN_NULL) + List performanceIndicatorSpecificationMVOListToPerformanceIndicatorSpecificationList(List list); + @IterableMapping(nullValueMappingStrategy = NullValueMappingStrategy.RETURN_NULL) + List trackingRecordMVOListToTrackingRecordList(List list); + @IterableMapping(nullValueMappingStrategy = NullValueMappingStrategy.RETURN_NULL) + List fileTransferDataMVOListToFileTransferDataList(List list); + @IterableMapping(nullValueMappingStrategy = NullValueMappingStrategy.RETURN_NULL) + List scheduleDefinitionMVOListToScheduleDefinitionList(List list); +} diff --git a/src/main/java/org/etsi/osl/metrico/mapper/MeasurementJobMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/MeasurementJobMapper.java deleted file mode 100644 index 8d6ed6d876e147b29c127ccc2d8e44ec9282e688..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/MeasurementJobMapper.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.pm628.model.MeasurementJob; -import org.etsi.osl.tmf.pm628.model.MeasurementJobMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper(uses = { - FileTransferDataMapper.class, - DataAccessEndpointMapper.class, - ScheduleDefinitionMapper.class, - PerformanceIndicatorGroupSpecificationMapper.class, - PerformanceIndicatorSpecificationRefOrValueMapper.class, - TrackingRecordMapper.class -}) -public interface MeasurementJobMapper { - MeasurementJobMapper INSTANCE = Mappers.getMapper(MeasurementJobMapper.class); - - @Mapping(source = "consumingApplicationId", target = "consumingApplicationId") - @Mapping(source = "producingApplicationId", target = "producingApplicationId") - @Mapping(source = "granularity", target = "granularity") - @Mapping(source = "performanceIndicatorGroupSpecification", target = "performanceIndicatorGroupSpecification") - @Mapping(source = "performanceIndicatorSpecification", target = "performanceIndicatorSpecification") - @Mapping(source = "trackingRecord", target = "trackingRecord") - MeasurementJob toMeasurementJob(MeasurementJobMVO measurementJobMVO); - - @Mapping(source = "consumingApplicationId", target = "consumingApplicationId") - @Mapping(source = "producingApplicationId", target = "producingApplicationId") - @Mapping(source = "granularity", target = "granularity") - @Mapping(source = "performanceIndicatorGroupSpecification", target = "performanceIndicatorGroupSpecification") - @Mapping(source = "performanceIndicatorSpecification", target = "performanceIndicatorSpecification") - @Mapping(source = "trackingRecord", target = "trackingRecord") - MeasurementJobMVO toMeasurementJobMVO(MeasurementJob measurementJob); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/MonthlyScheduleDayOfWeekDefinitionMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/MonthlyScheduleDayOfWeekDefinitionMapper.java deleted file mode 100644 index e1dbf960da723c4bd8f4e09fb4db6cd29f5eb07c..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/MonthlyScheduleDayOfWeekDefinitionMapper.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.pm628.model.MonthlyScheduleDayOfWeekDefinition; -import org.etsi.osl.tmf.pm628.model.MonthlyScheduleDayOfWeekDefinitionMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper(uses = { - DayOfMonthRecurrenceMapper.class -}) -public interface MonthlyScheduleDayOfWeekDefinitionMapper { - MonthlyScheduleDayOfWeekDefinitionMapper INSTANCE = Mappers.getMapper(MonthlyScheduleDayOfWeekDefinitionMapper.class); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "dayOfMonthRecurrence", target = "dayOfMonthRecurrence") - @Mapping(source = "recurringDaySequence", target = "recurringDaySequence") - MonthlyScheduleDayOfWeekDefinition toMonthlyScheduleDayOfWeekDefinition(MonthlyScheduleDayOfWeekDefinitionMVO monthlyScheduleDayOfWeekDefinitionMVO); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "dayOfMonthRecurrence", target = "dayOfMonthRecurrence") - @Mapping(source = "recurringDaySequence", target = "recurringDaySequence") - MonthlyScheduleDayOfWeekDefinitionMVO toMonthlyScheduleDayOfWeekDefinitionMVO(MonthlyScheduleDayOfWeekDefinition monthlyScheduleDayOfWeekDefinition); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/NoteMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/NoteMapper.java deleted file mode 100644 index 6f25a3788b754ecb22c1dd29396f2f6329549c79..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/NoteMapper.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.common.model.service.Note; -import org.etsi.osl.tmf.pm628.model.NoteMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface NoteMapper { - NoteMapper INSTANCE = Mappers.getMapper(NoteMapper.class); - - @Mapping(source = "uuid", target = "uuid") - @Mapping(source = "author", target = "author") - @Mapping(source = "date", target = "date") - @Mapping(source = "text", target = "text") - Note toNote(NoteMVO noteMVO); - - @Mapping(source = "uuid", target = "uuid") - @Mapping(source = "author", target = "author") - @Mapping(source = "date", target = "date") - @Mapping(source = "text", target = "text") - NoteMVO toNoteMVO(Note note); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/PartyRefOrPartyRoleRefMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/PartyRefOrPartyRoleRefMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..8ec5e72887b61cde6bd29a8cc0f896e9a58a3254 --- /dev/null +++ b/src/main/java/org/etsi/osl/metrico/mapper/PartyRefOrPartyRoleRefMapper.java @@ -0,0 +1,21 @@ +package org.etsi.osl.metrico.mapper; + +import org.etsi.osl.tmf.pm628.model.*; +import org.mapstruct.*; + +@Mapper( + nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT, + nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, + subclassExhaustiveStrategy = SubclassExhaustiveStrategy.RUNTIME_EXCEPTION +) +public interface PartyRefOrPartyRoleRefMapper { + + @SubclassMapping(source = PartyRefFVO.class, target = PartyRef.class) + @SubclassMapping(source = PartyRoleRefFVO.class, target = PartyRoleRef.class) + PartyRefOrPartyRoleRef map(PartyRefOrPartyRoleRefFVO source); + + @SubclassMapping(source = PartyRefMVO.class, target = PartyRef.class) + @SubclassMapping(source = PartyRoleRefMVO.class, target = PartyRoleRef.class) + PartyRefOrPartyRoleRef map(PartyRefOrPartyRoleRefMVO source); +} + diff --git a/src/main/java/org/etsi/osl/metrico/mapper/PerformanceIndicatorGroupSpecificationMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/PerformanceIndicatorGroupSpecificationMapper.java deleted file mode 100644 index 1af6d2eddebd60685f70f13d30afe4480180bdcd..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/PerformanceIndicatorGroupSpecificationMapper.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.pm628.model.PerformanceIndicatorGroupSpecification; -import org.etsi.osl.tmf.pm628.model.PerformanceIndicatorGroupSpecificationMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper(uses = { - PerformanceIndicatorSpecificationRefOrValueMapper.class -}) -public interface PerformanceIndicatorGroupSpecificationMapper { - PerformanceIndicatorGroupSpecificationMapper INSTANCE = Mappers.getMapper(PerformanceIndicatorGroupSpecificationMapper.class); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "uuid", target = "uuid") - @Mapping(source = "name", target = "name") - @Mapping(source = "groupCategory", target = "groupCategory") - @Mapping(source = "performanceIndicatorSpecification", target = "performanceIndicatorSpecification") - PerformanceIndicatorGroupSpecification toPerformanceIndicatorGroupSpecification(PerformanceIndicatorGroupSpecificationMVO performanceIndicatorGroupSpecificationMVO); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "uuid", target = "uuid") - @Mapping(source = "name", target = "name") - @Mapping(source = "groupCategory", target = "groupCategory") - @Mapping(source = "performanceIndicatorSpecification", target = "performanceIndicatorSpecification") - PerformanceIndicatorGroupSpecificationMVO toPerformanceIndicatorGroupSpecificationMVO(PerformanceIndicatorGroupSpecification performanceIndicatorGroupSpecification); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/PerformanceIndicatorSpecRelationshipMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/PerformanceIndicatorSpecRelationshipMapper.java deleted file mode 100644 index cefb15ae575f42cde28e6eaed2da63147fcbe493..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/PerformanceIndicatorSpecRelationshipMapper.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.pm628.model.PerformanceIndicatorSpecRelationship; -import org.etsi.osl.tmf.pm628.model.PerformanceIndicatorSpecRelationshipMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface PerformanceIndicatorSpecRelationshipMapper { - PerformanceIndicatorSpecRelationshipMapper INSTANCE = Mappers.getMapper(PerformanceIndicatorSpecRelationshipMapper.class); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "href", target = "href") - @Mapping(source = "uuid", target = "uuid") - @Mapping(source = "relationshipType", target = "relationshipType") - @Mapping(source = "role", target = "role") - @Mapping(source = "validFor", target = "validFor") - PerformanceIndicatorSpecRelationship toPerformanceIndicatorSpecRelationship(PerformanceIndicatorSpecRelationshipMVO performanceIndicatorSpecRelationshipMVO); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "href", target = "href") - @Mapping(source = "uuid", target = "uuid") - @Mapping(source = "relationshipType", target = "relationshipType") - @Mapping(source = "role", target = "role") - @Mapping(source = "validFor", target = "validFor") - PerformanceIndicatorSpecRelationshipMVO toPerformanceIndicatorSpecRelationshipMVO(PerformanceIndicatorSpecRelationship performanceIndicatorSpecRelationship); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/PerformanceIndicatorSpecificationMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/PerformanceIndicatorSpecificationMapper.java index f58269c99e213df365f263d64e6ba6bca19d1897..6851198a592e5712661a55f8f8a64eecf7b30d70 100644 --- a/src/main/java/org/etsi/osl/metrico/mapper/PerformanceIndicatorSpecificationMapper.java +++ b/src/main/java/org/etsi/osl/metrico/mapper/PerformanceIndicatorSpecificationMapper.java @@ -1,50 +1,24 @@ package org.etsi.osl.metrico.mapper; import org.etsi.osl.tmf.pm628.model.PerformanceIndicatorSpecification; +import org.etsi.osl.tmf.pm628.model.PerformanceIndicatorSpecificationFVO; import org.etsi.osl.tmf.pm628.model.PerformanceIndicatorSpecificationMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; +import org.mapstruct.*; -@Mapper(uses = { - PerformanceIndicatorSpecRelationshipMapper.class, -}) +@Mapper( + nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT, + nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, + collectionMappingStrategy = CollectionMappingStrategy.ACCESSOR_ONLY // Collection- or map-typed properties of the target bean to be updated will be cleared and then populated with the values from the corresponding source collection or map +) public interface PerformanceIndicatorSpecificationMapper { - PerformanceIndicatorSpecificationMapper INSTANCE = Mappers.getMapper(PerformanceIndicatorSpecificationMapper.class); - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "href", target = "href") - @Mapping(source = "uuid", target = "uuid") - @Mapping(source = "name", target = "name") - @Mapping(source = "description", target = "description") - @Mapping(source = "perspective", target = "perspective") - @Mapping(source = "indicatorCategory", target = "indicatorCategory") - @Mapping(source = "indicatorType", target = "indicatorType") - @Mapping(source = "derivationAlgorithm", target = "derivationAlgorithm") - @Mapping(source = "derivationMethod", target = "derivationMethod") - @Mapping(source = "validFor", target = "validFor") - @Mapping(source = "collectionType", target = "collectionType") - @Mapping(source = "indicatorUnit", target = "indicatorUnit") - @Mapping(source = "performanceIndicatorSpecRelationship", target = "performanceIndicatorSpecRelationship") - PerformanceIndicatorSpecification toPerformanceIndicatorSpecification(PerformanceIndicatorSpecificationMVO performanceIndicatorSpecificationMVO); + PerformanceIndicatorSpecification createPerformanceIndicatorSpecification(PerformanceIndicatorSpecificationFVO performanceIndicatorSpecificationFVO); - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "href", target = "href") - @Mapping(source = "uuid", target = "uuid") - @Mapping(source = "name", target = "name") - @Mapping(source = "description", target = "description") - @Mapping(source = "perspective", target = "perspective") - @Mapping(source = "indicatorCategory", target = "indicatorCategory") - @Mapping(source = "indicatorType", target = "indicatorType") - @Mapping(source = "derivationAlgorithm", target = "derivationAlgorithm") - @Mapping(source = "derivationMethod", target = "derivationMethod") - @Mapping(source = "validFor", target = "validFor") - @Mapping(source = "collectionType", target = "collectionType") - @Mapping(source = "indicatorUnit", target = "indicatorUnit") - @Mapping(source = "performanceIndicatorSpecRelationship", target = "performanceIndicatorSpecRelationship") - PerformanceIndicatorSpecificationMVO toPerformanceIndicatorSpecificationMVO(PerformanceIndicatorSpecification performanceIndicatorSpecification); + @Mapping(target = "type", ignore = true) + @Mapping(target = "baseType", ignore = true) + @Mapping(target = "schemaLocation", ignore = true) + @Mapping(target = "href", ignore = true) + @Mapping(target = "uuid", ignore = true) + @BeanMapping(nullValuePropertyMappingStrategy = NullValuePropertyMappingStrategy.IGNORE) + PerformanceIndicatorSpecification updatePerformanceIndicatorSpecification(PerformanceIndicatorSpecificationMVO performanceIndicatorSpecificationMVO, @MappingTarget PerformanceIndicatorSpecification performanceIndicatorSpecification); } \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/PerformanceIndicatorSpecificationRefMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/PerformanceIndicatorSpecificationRefMapper.java deleted file mode 100644 index 0e56edb6c9cc36c3c937ef525b64ffd9cd28c7d1..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/PerformanceIndicatorSpecificationRefMapper.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.pm628.model.PerformanceIndicatorSpecificationRef; -import org.etsi.osl.tmf.pm628.model.PerformanceIndicatorSpecificationRefMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface PerformanceIndicatorSpecificationRefMapper { - PerformanceIndicatorSpecificationRefMapper INSTANCE = Mappers.getMapper(PerformanceIndicatorSpecificationRefMapper.class); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "href", target = "href") - @Mapping(source = "uuid", target = "uuid") - @Mapping(source = "name", target = "name") - @Mapping(source = "referredType", target = "referredType") - @Mapping(source = "version", target = "version") - PerformanceIndicatorSpecificationRef toPerformanceIndicatorSpecificationRef(PerformanceIndicatorSpecificationRefMVO performanceIndicatorSpecificationRefMVO); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "href", target = "href") - @Mapping(source = "uuid", target = "uuid") - @Mapping(source = "name", target = "name") - @Mapping(source = "referredType", target = "referredType") - @Mapping(source = "version", target = "version") - PerformanceIndicatorSpecificationRefMVO toPerformanceIndicatorSpecificationRefMVO(PerformanceIndicatorSpecificationRef performanceIndicatorSpecificationRef); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/PerformanceIndicatorSpecificationRefOrValueMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/PerformanceIndicatorSpecificationRefOrValueMapper.java deleted file mode 100644 index b78ed7c1f637dbcef828c2c2052a0a5778207a6b..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/PerformanceIndicatorSpecificationRefOrValueMapper.java +++ /dev/null @@ -1,22 +0,0 @@ -package org.etsi.osl.metrico.mapper; - - -import org.etsi.osl.tmf.pm628.model.PerformanceIndicatorSpecificationRefOrValue; -import org.etsi.osl.tmf.pm628.model.PerformanceIndicatorSpecificationRefOrValueMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper(uses = { - PerformanceIndicatorSpecificationMapper.class, - PerformanceIndicatorSpecificationRefMapper.class -}) -public interface PerformanceIndicatorSpecificationRefOrValueMapper { - PerformanceIndicatorSpecificationRefOrValueMapper INSTANCE = Mappers.getMapper(PerformanceIndicatorSpecificationRefOrValueMapper.class); - - @Mapping(source = "type", target = "type") - PerformanceIndicatorSpecificationRefOrValue toPerformanceIndicatorSpecificationRefOrValue(PerformanceIndicatorSpecificationRefOrValueMVO performanceIndicatorSpecificationRefOrValueMVO); - - @Mapping(source = "type", target = "type") - PerformanceIndicatorSpecificationRefOrValueMVO toPerformanceIndicatorSpecificationRefOrValueMVO(PerformanceIndicatorSpecificationRefOrValue performanceIndicatorSpecificationRefOrValue); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/PolicyRefMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/PolicyRefMapper.java deleted file mode 100644 index 851e0b43c93ba98e46dd57137bda9b7392b01ad9..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/PolicyRefMapper.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.pm628.model.PolicyRef; -import org.etsi.osl.tmf.pm628.model.PolicyRefMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface PolicyRefMapper { - PolicyRefMapper INSTANCE = Mappers.getMapper(PolicyRefMapper.class); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "href", target = "href") - @Mapping(source = "uuid", target = "uuid") - @Mapping(source = "name", target = "name") - @Mapping(source = "referredType", target = "referredType") - @Mapping(source = "version", target = "version") - PolicyRef toPolicyRef(PolicyRefMVO policyRefMVO); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "href", target = "href") - @Mapping(source = "uuid", target = "uuid") - @Mapping(source = "name", target = "name") - @Mapping(source = "referredType", target = "referredType") - @Mapping(source = "version", target = "version") - PolicyRefMVO toPolicyRefMVO(PolicyRef policyRef); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/RelatedPartyRefOrPartyRoleRefMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/RelatedPartyRefOrPartyRoleRefMapper.java deleted file mode 100644 index bc6f59a94ff472a49b7f5ea4193d6aae1e2b25ce..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/RelatedPartyRefOrPartyRoleRefMapper.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.pm628.model.RelatedPartyRefOrPartyRoleRef; -import org.etsi.osl.tmf.pm628.model.RelatedPartyRefOrPartyRoleRefMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface RelatedPartyRefOrPartyRoleRefMapper { - RelatedPartyRefOrPartyRoleRefMapper INSTANCE = Mappers.getMapper(RelatedPartyRefOrPartyRoleRefMapper.class); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "role", target = "role") - @Mapping(source = "partyOrPartyRole", target = "partyOrPartyRole") - RelatedPartyRefOrPartyRoleRef toRelatedPartyRefOrPartyRoleRef(RelatedPartyRefOrPartyRoleRefMVO relatedPartyRefOrPartyRoleRefMVO); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "role", target = "role") - @Mapping(source = "partyOrPartyRole", target = "partyOrPartyRole") - RelatedPartyRefOrPartyRoleRefMVO toRelatedPartyRefOrPartyRoleRefMVO(RelatedPartyRefOrPartyRoleRef relatedPartyRefOrPartyRoleRef); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/RelatedPlaceRefMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/RelatedPlaceRefMapper.java deleted file mode 100644 index 9d60c1ae9175bc5e20edbdb6d0ebdf4a99fadae5..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/RelatedPlaceRefMapper.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.pm628.model.RelatedPlaceRef; -import org.etsi.osl.tmf.pm628.model.RelatedPlaceRefMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface RelatedPlaceRefMapper { - RelatedPlaceRefMapper INSTANCE = Mappers.getMapper(RelatedPlaceRefMapper.class); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "role", target = "role") - @Mapping(source = "place", target = "place") - RelatedPlaceRef toRelatedPlaceRef(RelatedPlaceRefMVO relatedPlaceRefMVO); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "role", target = "role") - @Mapping(source = "place", target = "place") - RelatedPlaceRefMVO toRelatedPlaceRefMVO(RelatedPlaceRef relatedPlaceRef); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/RelatedResourceOrderItemMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/RelatedResourceOrderItemMapper.java deleted file mode 100644 index 60c1ad80087c919f687d9951e756a372f812d9e0..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/RelatedResourceOrderItemMapper.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.pm628.model.RelatedResourceOrderItem; -import org.etsi.osl.tmf.pm628.model.RelatedResourceOrderItemMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface RelatedResourceOrderItemMapper { - RelatedResourceOrderItemMapper INSTANCE = Mappers.getMapper(RelatedResourceOrderItemMapper.class); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "referredType", target = "referredType") - @Mapping(source = "resourceOrderHref", target = "resourceOrderHref") - @Mapping(source = "resourceOrderId", target = "resourceOrderId") - @Mapping(source = "itemAction", target = "itemAction") - @Mapping(source = "itemId", target = "itemId") - @Mapping(source = "role", target = "role") - RelatedResourceOrderItem toRelatedResourceOrderItem(RelatedResourceOrderItemMVO relatedResourceOrderItemMVO); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "referredType", target = "referredType") - @Mapping(source = "resourceOrderHref", target = "resourceOrderHref") - @Mapping(source = "resourceOrderId", target = "resourceOrderId") - @Mapping(source = "itemAction", target = "itemAction") - @Mapping(source = "itemId", target = "itemId") - @Mapping(source = "role", target = "role") - RelatedResourceOrderItemMVO toRelatedResourceOrderItemMVO(RelatedResourceOrderItem relatedResourceOrderItem); -} diff --git a/src/main/java/org/etsi/osl/metrico/mapper/ResourceMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/ResourceMapper.java deleted file mode 100644 index 18a5b4290ae2690a0bdbe6f6cada3d91c7e98900..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/ResourceMapper.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.pm628.model.Resource; -import org.etsi.osl.tmf.pm628.model.ResourceMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper(uses = { - NoteMapper.class, - RelatedResourceOrderItemMapper.class, - RelatedPlaceRefMapper.class, - RelatedPartyRefOrPartyRoleRefMapper.class, - ResourceRelationshipMapper.class, - CharacteristicMapper.class, - AttachmentRefMapper.class, - ResourceSpecificationRefMapper.class, - FeatureMapper.class, - IntentRefMapper.class, - ExternalIdentifierMapper.class -}) -public interface ResourceMapper { - ResourceMapper INSTANCE = Mappers.getMapper(ResourceMapper.class); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "href", target = "href") - @Mapping(source = "uuid", target = "uuid") - @Mapping(source = "category", target = "category") - @Mapping(source = "description", target = "description") - @Mapping(source = "name", target = "name") - @Mapping(source = "endOperatingDate", target = "endOperatingDate") - @Mapping(source = "administrativeState", target = "administrativeState") - @Mapping(source = "operationalState", target = "operationalState") - @Mapping(source = "resourceStatus", target = "resourceStatus") - @Mapping(source = "usageState", target = "usageState") - @Mapping(source = "validFor", target = "validFor") - @Mapping(source = "note", target = "note") - @Mapping(source = "resourceOrderItem", target = "resourceOrderItem") - @Mapping(source = "place", target = "place") - @Mapping(source = "relatedParty", target = "relatedParty") - @Mapping(source = "resourceRelationship", target = "resourceRelationship") - @Mapping(source = "resourceCharacteristic", target = "resourceCharacteristic") - @Mapping(source = "attachment", target = "attachment") - @Mapping(source = "resourceSpecification", target = "resourceSpecification") - @Mapping(source = "startOperatingDate", target = "startOperatingDate") - @Mapping(source = "resourceVersion", target = "resourceVersion") - @Mapping(source = "activationFeature", target = "activationFeature") - @Mapping(source = "intent", target = "intent") - @Mapping(source = "externalIdentifier", target = "externalIdentifier") - Resource toResource(ResourceMVO resourceMVO); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "href", target = "href") - @Mapping(source = "uuid", target = "uuid") - @Mapping(source = "category", target = "category") - @Mapping(source = "description", target = "description") - @Mapping(source = "name", target = "name") - @Mapping(source = "endOperatingDate", target = "endOperatingDate") - @Mapping(source = "administrativeState", target = "administrativeState") - @Mapping(source = "operationalState", target = "operationalState") - @Mapping(source = "resourceStatus", target = "resourceStatus") - @Mapping(source = "usageState", target = "usageState") - @Mapping(source = "validFor", target = "validFor") - @Mapping(source = "note", target = "note") - @Mapping(source = "resourceOrderItem", target = "resourceOrderItem") - @Mapping(source = "place", target = "place") - @Mapping(source = "relatedParty", target = "relatedParty") - @Mapping(source = "resourceRelationship", target = "resourceRelationship") - @Mapping(source = "resourceCharacteristic", target = "resourceCharacteristic") - @Mapping(source = "attachment", target = "attachment") - @Mapping(source = "resourceSpecification", target = "resourceSpecification") - @Mapping(source = "startOperatingDate", target = "startOperatingDate") - @Mapping(source = "resourceVersion", target = "resourceVersion") - @Mapping(source = "activationFeature", target = "activationFeature") - @Mapping(source = "intent", target = "intent") - @Mapping(source = "externalIdentifier", target = "externalIdentifier") - ResourceMVO toResourceMVO(Resource resource); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/ResourceRefOrValueMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/ResourceRefOrValueMapper.java index 2fae4c84907986a03cb3f9c53027fc6dc7b9345f..3d3ec0fe5cdad2cb8f7b0e2e9935a690a08c343c 100644 --- a/src/main/java/org/etsi/osl/metrico/mapper/ResourceRefOrValueMapper.java +++ b/src/main/java/org/etsi/osl/metrico/mapper/ResourceRefOrValueMapper.java @@ -1,18 +1,24 @@ package org.etsi.osl.metrico.mapper; -import org.etsi.osl.tmf.pm628.model.ResourceRefOrValue; -import org.etsi.osl.tmf.pm628.model.ResourceRefOrValueMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; +import org.etsi.osl.tmf.pm628.model.*; +import org.mapstruct.*; -@Mapper +@Mapper( + nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT, + nullValueCheckStrategy = NullValueCheckStrategy.ALWAYS, + subclassExhaustiveStrategy = SubclassExhaustiveStrategy.RUNTIME_EXCEPTION, + uses = {PartyRefOrPartyRoleRefMapper.class}) public interface ResourceRefOrValueMapper { - ResourceRefOrValueMapper INSTANCE = Mappers.getMapper(ResourceRefOrValueMapper.class); - @Mapping(source = "type", target = "type") - ResourceRefOrValueMVO toResourceRefOrValueMVO(ResourceRefOrValue resourceRefOrValue); + @SubclassMapping(source = DataAccessEndpointFVO.class, target = DataAccessEndpoint.class) + @SubclassMapping(source = LogicalResourceFVO.class, target = LogicalResource.class) + @SubclassMapping(source = ResourceFVO.class, target = Resource.class) + @SubclassMapping(source = ResourceRefFVO.class, target = ResourceRef.class) + ResourceRefOrValue map(ResourceRefOrValueFVO source); - @Mapping(source = "type", target = "type") - ResourceRefOrValue toResourceRefOrValue(ResourceRefOrValueMVO resourceRefOrValueMVO); + @SubclassMapping(source = DataAccessEndpointMVO.class, target = DataAccessEndpoint.class) + @SubclassMapping(source = LogicalResourceMVO.class, target = LogicalResource.class) + @SubclassMapping(source = ResourceMVO.class, target = Resource.class) + @SubclassMapping(source = ResourceRefMVO.class, target = ResourceRef.class) + ResourceRefOrValue map(ResourceRefOrValueMVO source); } diff --git a/src/main/java/org/etsi/osl/metrico/mapper/ResourceRelationshipMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/ResourceRelationshipMapper.java deleted file mode 100644 index f91ba647bc066da1db065c0bd6ce6e6b18f9d271..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/ResourceRelationshipMapper.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.pm628.model.ResourceRelationship; -import org.etsi.osl.tmf.pm628.model.ResourceRelationshipMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface ResourceRelationshipMapper { - ResourceRelationshipMapper INSTANCE = Mappers.getMapper(ResourceRelationshipMapper.class); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "uuid", target = "uuid") - @Mapping(source = "resourceRelationshipCharacteristic", target = "resourceRelationshipCharacteristic") - @Mapping(source = "resource", target = "resource") - @Mapping(source = "relationshipType", target = "relationshipType") - ResourceRelationship toResourceRelationship(ResourceRelationshipMVO resourceRelationshipMVO); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "uuid", target = "uuid") - @Mapping(source = "resourceRelationshipCharacteristic", target = "resourceRelationshipCharacteristic") - @Mapping(source = "resource", target = "resource") - @Mapping(source = "relationshipType", target = "relationshipType") - ResourceRelationshipMVO toResourceRelationshipMVO(ResourceRelationship resourceRelationship); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/ResourceSpecificationRefMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/ResourceSpecificationRefMapper.java deleted file mode 100644 index 9041cab49b41f33f603ee31a3758769c5e07caf1..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/ResourceSpecificationRefMapper.java +++ /dev/null @@ -1,32 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.rcm634.model.ResourceSpecificationRef; -import org.etsi.osl.tmf.pm628.model.ResourceSpecificationRefMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper -public interface ResourceSpecificationRefMapper { - ResourceSpecificationRefMapper INSTANCE = Mappers.getMapper(ResourceSpecificationRefMapper.class); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "href", target = "href") - @Mapping(source = "id", target = "id") - @Mapping(source = "name", target = "name") - @Mapping(source = "referredType", target = "referredType") - @Mapping(source = "version", target = "version") - ResourceSpecificationRef toResourceSpecificationRef(ResourceSpecificationRefMVO resourceSpecificationRefMVO); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "href", target = "href") - @Mapping(source = "id", target = "id") - @Mapping(source = "name", target = "name") - @Mapping(source = "referredType", target = "referredType") - @Mapping(source = "version", target = "version") - ResourceSpecificationRefMVO toResourceSpecificationRefMVO(ResourceSpecificationRef resourceSpecificationRef); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/ScheduleDefinitionMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/ScheduleDefinitionMapper.java deleted file mode 100644 index 8d62b206256e32bf66a472825ce03be0980431f9..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/ScheduleDefinitionMapper.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.pm628.model.ScheduleDefinition; -import org.etsi.osl.tmf.pm628.model.ScheduleDefinitionMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper(uses = { - DayOfWeekRecurrenceMapper.class, - MonthlyScheduleDayOfWeekDefinitionMapper.class -}) -public interface ScheduleDefinitionMapper { - ScheduleDefinitionMapper INSTANCE = Mappers.getMapper(ScheduleDefinitionMapper.class); - - @Mapping(source = "scheduleDefinitionStartTime", target = "scheduleDefinitionStartTime") - @Mapping(source = "scheduleDefinitionEndTime", target = "scheduleDefinitionEndTime") - @Mapping(source = "recurringFrequency", target = "recurringFrequency") - @Mapping(source = "excludedDate", target = "excludedDate") - @Mapping(source = "scheduleDefinitionHourRange", target = "scheduleDefinitionHourRange") - @Mapping(source = "weeklyScheduledDefinition", target = "weeklyScheduledDefinition") - @Mapping(source = "monthlyScheduleDayOfMonthDefinition", target = "monthlyScheduleDayOfMonthDefinition") - @Mapping(source = "monthlyScheduleDayOfWeekDefinition", target = "monthlyScheduleDayOfWeekDefinition") - @Mapping(source = "dateScheduleDefintion", target = "dateScheduleDefintion") - ScheduleDefinition toScheduleDefinition(ScheduleDefinitionMVO scheduleDefinitionMVO); - - @Mapping(source = "scheduleDefinitionStartTime", target = "scheduleDefinitionStartTime") - @Mapping(source = "scheduleDefinitionEndTime", target = "scheduleDefinitionEndTime") - @Mapping(source = "recurringFrequency", target = "recurringFrequency") - @Mapping(source = "excludedDate", target = "excludedDate") - @Mapping(source = "scheduleDefinitionHourRange", target = "scheduleDefinitionHourRange") - @Mapping(source = "weeklyScheduledDefinition", target = "weeklyScheduledDefinition") - @Mapping(source = "monthlyScheduleDayOfMonthDefinition", target = "monthlyScheduleDayOfMonthDefinition") - @Mapping(source = "monthlyScheduleDayOfWeekDefinition", target = "monthlyScheduleDayOfWeekDefinition") - @Mapping(source = "dateScheduleDefintion", target = "dateScheduleDefintion") - ScheduleDefinitionMVO toScheduleDefinitionMVO(ScheduleDefinition scheduleDefinition); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/mapper/TrackingRecordMapper.java b/src/main/java/org/etsi/osl/metrico/mapper/TrackingRecordMapper.java deleted file mode 100644 index fceb1057193f93ebf5c436cc71e98db3aa13fe62..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/mapper/TrackingRecordMapper.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.etsi.osl.metrico.mapper; - -import org.etsi.osl.tmf.pm628.model.TrackingRecord; -import org.etsi.osl.tmf.pm628.model.TrackingRecordMVO; -import org.mapstruct.Mapper; -import org.mapstruct.Mapping; -import org.mapstruct.factory.Mappers; - -@Mapper(uses = { - CharacteristicMapper.class -}) -public interface TrackingRecordMapper { - TrackingRecordMapper INSTANCE = Mappers.getMapper(TrackingRecordMapper.class); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "description", target = "description") - @Mapping(source = "characteristic", target = "characteristic") - @Mapping(source = "systemId", target = "systemId") - @Mapping(source = "time", target = "time") - @Mapping(source = "user", target = "user") - @Mapping(source = "uuid", target = "uuid") - TrackingRecord toTrackingRecord(TrackingRecordMVO trackingRecordMVO); - - @Mapping(source = "type", target = "type") - @Mapping(source = "baseType", target = "baseType") - @Mapping(source = "schemaLocation", target = "schemaLocation") - @Mapping(source = "description", target = "description") - @Mapping(source = "characteristic", target = "characteristic") - @Mapping(source = "systemId", target = "systemId") - @Mapping(source = "time", target = "time") - @Mapping(source = "user", target = "user") - @Mapping(source = "uuid", target = "uuid") - TrackingRecordMVO toTrackingRecordMVO(TrackingRecord trackingRecord); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/model/Job.java b/src/main/java/org/etsi/osl/metrico/model/Job.java index 653a10ccea7826fdb3b02ddb4ee6164d49746056..cd90ecd43f9e4e9e4ca1df3299fc12d309e47f4b 100644 --- a/src/main/java/org/etsi/osl/metrico/model/Job.java +++ b/src/main/java/org/etsi/osl/metrico/model/Job.java @@ -1,12 +1,10 @@ package org.etsi.osl.metrico.model; import com.fasterxml.jackson.annotation.JsonIgnore; -import jakarta.persistence.*; +import jakarta.persistence.Transient; import lombok.Getter; import lombok.Setter; -import org.etsi.osl.tmf.pm628.model.DataFilterMap; import org.etsi.osl.tmf.pm628.model.ExecutionStateType; -import org.hibernate.annotations.GenericGenerator; import org.springframework.format.annotation.DateTimeFormat; import java.net.URI; @@ -17,15 +15,8 @@ import java.util.concurrent.ScheduledFuture; @Getter @Setter -@Entity -@Table(name = "MetJob") public class Job{ - @Id - @GeneratedValue(generator = "UUID") - @GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator") - private UUID uuid; - private ExecutionStateType state; @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) @@ -36,15 +27,11 @@ public class Job{ private Integer executionInterval; - private UUID dataAccessEndPointRef; // Get the prometheus IP (uri) and its state + private UUID dataAccessEndPointRef; - private UUID scheduleDefinitionRef; //Get the startDateTime, endDateTime and executionInterval (recurringFrequency) + private UUID scheduleDefinitionRef; - // Get the reporting period and collection granularity(the periods are too big), - // Consuming / producing application id, - // scheduleDefinitionRef -> Get the startDateTime, endDateTime and executionInterval (recurringFrequency) - // Should I check the granularity or the scheduleDefinitionRef for the recurringFrequency? - private UUID measurementCollectionJobRef; + private UUID measurementCollectionJobRef; // 1:1 relationship between Job and MeasurementCollectionJob. It will be used as an id for the Job. private URI dataAccessEndPointUri; @@ -57,14 +44,12 @@ public class Job{ private final Runnable task = new Runnable() { @Override public void run() { - } }; @Transient private ScheduledFuture future; - public Job() { this.state = ExecutionStateType.PENDING; this.executionInterval = 10; @@ -89,8 +74,7 @@ public class Job{ @Override public String toString() { return "Job{" + - "uuid=" + uuid + - ", state=" + state + + "state=" + state + ", startDateTime=" + startDateTime + ", endDateTime=" + endDateTime + ", executionInterval=" + executionInterval + @@ -101,51 +85,4 @@ public class Job{ '}'; } - public void setUuid(UUID uuid) { - this.uuid = uuid; - } - - public void setState(ExecutionStateType state) { - this.state = state; - } - - public void setStartDateTime(OffsetDateTime startDateTime) { - this.startDateTime = startDateTime; - } - - public void setEndDateTime(OffsetDateTime endDateTime) { - this.endDateTime = endDateTime; - } - - public void setExecutionInterval(Integer executionInterval) { - this.executionInterval = executionInterval; - } - - public void setDataAccessEndPointRef(UUID dataAccessEndPointRef) { - this.dataAccessEndPointRef = dataAccessEndPointRef; - } - - public void setScheduleDefinitionRef(UUID scheduleDefinitionRef) { - this.scheduleDefinitionRef = scheduleDefinitionRef; - } - - public void setMeasurementCollectionJobRef(UUID measurementCollectionJobRef) { - this.measurementCollectionJobRef = measurementCollectionJobRef; - } - - public void setDataAccessEndPointUri(URI dataAccessEndPointUri) { - this.dataAccessEndPointUri = dataAccessEndPointUri; - } - - public void setApiType(String apiType) { - this.apiType = apiType; - } - - public void setDeleted(boolean deleted) { - this.deleted = deleted; - } - - public void setFuture(ScheduledFuture future) { - this.future = future; - } } diff --git a/src/main/java/org/etsi/osl/metrico/prometheus/PrometheusQueries.java b/src/main/java/org/etsi/osl/metrico/prometheus/PrometheusQueries.java index f84a10640227008f87c1899a87522ca36f9149d5..985aec7c301c977be6603cf8fc997c4dd6f46948 100644 --- a/src/main/java/org/etsi/osl/metrico/prometheus/PrometheusQueries.java +++ b/src/main/java/org/etsi/osl/metrico/prometheus/PrometheusQueries.java @@ -1,164 +1,101 @@ package org.etsi.osl.metrico.prometheus; -import java.io.IOException; -import java.time.Duration; -import java.time.OffsetDateTime; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.TimeUnit; -import javax.net.ssl.SSLException; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.apache.camel.ProducerTemplate; +import org.etsi.osl.metrico.MetricoCommonMethods; import org.etsi.osl.metrico.model.Job; import org.etsi.osl.metrico.services.JobService; import org.etsi.osl.tmf.common.model.Any; import org.etsi.osl.tmf.common.model.service.Characteristic; import org.etsi.osl.tmf.pm628.model.ExecutionStateType; import org.etsi.osl.tmf.pm628.model.MeasurementCollectionJob; -import org.etsi.osl.tmf.rcm634.model.LogicalResourceSpecification; -import org.etsi.osl.tmf.rcm634.model.ResourceSpecificationCreate; -import org.etsi.osl.tmf.ri639.model.LogicalResource; -import org.etsi.osl.tmf.ri639.model.Resource; -import org.etsi.osl.tmf.ri639.model.ResourceUpdate; import org.etsi.osl.tmf.sim638.model.ServiceUpdate; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.core.ParameterizedTypeReference; import org.springframework.http.HttpStatusCode; import org.springframework.stereotype.Component; import org.springframework.web.reactive.function.client.WebClient; import org.springframework.web.util.UriComponentsBuilder; -import jakarta.validation.constraints.NotNull; import reactor.core.publisher.Mono; +import java.time.Duration; +import java.time.OffsetDateTime; +import java.util.concurrent.TimeUnit; + @Component public class PrometheusQueries { private static final Logger logger = LoggerFactory.getLogger(PrometheusQueries.class); - private final JobService jobService; - - - @Value("${CATALOG_GET_SERVICE_BY_ID}") - private String CATALOG_GET_SERVICE_BY_ID = ""; - - - @Value("${CATALOG_GET_RESOURCE_BY_ID}") - private String CATALOG_GET_RESOURCE_BY_ID = ""; - - @Value("${CATALOG_UPD_RESOURCE}") - private String CATALOG_UPD_RESOURCE = ""; - - - @Value("${CATALOG_UPD_SERVICE}") - private String CATALOG_UPD_SERVICE = ""; - - @Value("${CATALOG_UPDADD_RESOURCESPEC}") - private String CATALOG_UPDADD_RESOURCESPEC = ""; - - + private final JobService jobService; + private final MetricoCommonMethods metricoCommonMethods; - @Autowired - private ProducerTemplate template; - - public PrometheusQueries(JobService jobService) { + public PrometheusQueries(JobService jobService, MetricoCommonMethods metricoCommonMethods) { this.jobService = jobService; + this.metricoCommonMethods = metricoCommonMethods; } public String sendQueryToPrometheus(String prometheusUrl, String query, MeasurementCollectionJob mcj, Job job) { - //RestTemplate restTemplate = new RestTemplate(); - - UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(prometheusUrl) - .path("/api/v1/query") - .query(query); + UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(prometheusUrl).path("/api/v1/query").query(query); logger.atInfo().log("Sent query at prometheus with URL: " + prometheusUrl + " with query: " + query); - logger.atInfo().log("Sent query builder.toUriString(): " + builder.toUriString() ); + logger.atInfo().log("Sent query builder.toUriString(): " + builder.toUriString()); - //ResponseEntity response = restTemplate.getForEntity(builder.toUriString(), String.class); - WebClient webclient = WebClient.create(); + String response; - String response=""; - - if ( webclient!=null ) { - - try { - - String url = builder.toUriString(); - - response = webclient.get() - .uri(url) - //.header("Authorization", "Basic " + encodedClientData) + if (webclient != null) { + try { + String url = builder.toUriString(); + response = webclient.get().uri(url) + //.header("Authorization", "Basic " + encodedClientData) //.attributes( ServletOAuth2AuthorizedClientExchangeFilterFunction.clientRegistrationId("authOpensliceProvider")) - .retrieve() - .onStatus(HttpStatusCode::is4xxClientError, r -> { + .retrieve().onStatus(HttpStatusCode::is4xxClientError, r -> { logger.error("4xx eror"); return Mono.error(new RuntimeException("4xx")); - }) - .onStatus(HttpStatusCode::is5xxServerError, r -> { - logger.error("5xx eror"); + }).onStatus(HttpStatusCode::is5xxServerError, r -> { + logger.error("5xx eror"); return Mono.error(new RuntimeException("5xx")); - }) - .bodyToMono( new ParameterizedTypeReference() {}) - .block(); - - logger.atDebug().log("Received " + response); - - String [] promResponse =response.split("\n"); - - - - }catch (Exception e) { + }).bodyToMono(new ParameterizedTypeReference() { + }).block(); + logger.atDebug().log("Received " + response); + String[] promResponse = response.split("\n"); + } catch (Exception e) { logger.error(" error on web client request"); - response = "{\"status\":\""+ e.getLocalizedMessage() +"\""; + response = "{\"status\":\"" + e.getLocalizedMessage() + "\""; e.printStackTrace(); } - - } else { - logger.error("WebClient is null. Cannot be created."); - response = "{\"status\":\"Cannot connect\""; - } - - - - ServiceUpdate su = new ServiceUpdate(); + } else { + logger.error("WebClient is null. Cannot be created."); + response = "{\"status\":\"Cannot connect\""; + } - //patch TMF service - String serviceUUID = mcj.getConsumingApplicationId(); - logger.atDebug().log("serviceUUID= " + serviceUUID); - Characteristic serviceCharacteristicItem = new Characteristic(); - serviceCharacteristicItem.setName( mcj.getOutputFormat() ); - serviceCharacteristicItem.setValueType( "TEXT" ); - Any val = new Any(); - val.setValue( response ); - val.setAlias( ""); - serviceCharacteristicItem.setValue( val ); - su.addServiceCharacteristicItem(serviceCharacteristicItem); - updateService(serviceUUID, su , true); - - return response; + ServiceUpdate su = new ServiceUpdate(); + //patch TMF service + String serviceUUID = mcj.getConsumingApplicationId(); + logger.atDebug().log("serviceUUID= " + serviceUUID); + Characteristic serviceCharacteristicItem = new Characteristic(); + serviceCharacteristicItem.setName(mcj.getOutputFormat()); + serviceCharacteristicItem.setValueType("TEXT"); + Any val = new Any(); + val.setValue(response); + val.setAlias(""); + serviceCharacteristicItem.setValue(val); + su.addServiceCharacteristicItem(serviceCharacteristicItem); + metricoCommonMethods.updateService(serviceUUID, su, true); + + return response; } - - + public Job startPeriodicQuery(String prometheusUrl, String query, final Job ajob, MeasurementCollectionJob mcj) { - Job job = ajob; - if (job.getStartDateTime() == null){ - job.setStartDateTime(OffsetDateTime.now()); - } - if (job.getEndDateTime() == null){ - job.setEndDateTime(job.getStartDateTime().plusHours(1)); - } - if(job.getExecutionInterval() == null){ - job.setExecutionInterval(180); - } - + Job job = ajob; + + + if (job.getExecutionInterval() == null) { + job.setExecutionInterval(180); + } + final Runnable queryHandler = () -> sendQueryToPrometheus(prometheusUrl, query, mcj, ajob); job = jobService.startJob(queryHandler, job); @@ -168,167 +105,15 @@ public class PrometheusQueries { } if (job.getEndDateTime() != null) { - long stopAfterSeconds = Duration.between(OffsetDateTime.now(), job.getEndDateTime() ).getSeconds(); + long stopAfterSeconds = Duration.between(OffsetDateTime.now(), job.getEndDateTime()).getSeconds(); JobService.getScheduler().schedule(() -> { jobService.stopJob(ajob); - }, stopAfterSeconds, TimeUnit.SECONDS); } return job; } - - - - public Resource retrieveResource(@NotNull String resourceID) { - logger.info("will retrieve Resource instance from catalog resourceID=" + resourceID ); - try { - Object response = template. - requestBody( CATALOG_GET_RESOURCE_BY_ID, resourceID); - - if ( !(response instanceof String)) { - logger.error("resource object is wrong."); - return null; - } - LogicalResource rInstance = toJsonObj( (String)response, LogicalResource.class); - - return rInstance; - - }catch (Exception e) { - logger.error("Cannot retrieve LogicalResource details from catalog. " + e.toString()); - } - return null; - - } - - /** - * Ger service instance via bus - * @param serviceID - * @return - */ - public org.etsi.osl.tmf.sim638.model.Service retrieveService(String serviceID) { - logger.info("will retrieve Service instance from catalog serviceID=" + serviceID ); - try { - Object response = template. - requestBody( CATALOG_GET_SERVICE_BY_ID, serviceID); - - if ( !(response instanceof String)) { - logger.error("Service object is wrong."); - return null; - } - org.etsi.osl.tmf.sim638.model.Service serviceInstance = toJsonObj( (String)response, org.etsi.osl.tmf.sim638.model.Service.class); - //logger.debug("retrieveService response is: " + response); - return serviceInstance; - - }catch (Exception e) { - logger.error("Cannot retrieve Service details from catalog. " + e.toString()); - } - return null; - } - - - public Resource updateResourceById(String oslResourceId, ResourceUpdate rs) { - - - logger.debug("will update Resource : " + oslResourceId ); - try { - Map map = new HashMap<>(); - map.put("resourceId", oslResourceId ); - map.put("triggerServiceActionQueue", false ); - - Object response = template.requestBodyAndHeaders( CATALOG_UPD_RESOURCE, toJsonString(rs), map); - - if ( !(response instanceof String)) { - logger.error("Service Instance object is wrong."); - } - - LogicalResource resourceInstance = toJsonObj( (String)response, LogicalResource.class); - //logger.debug("createService response is: " + response); - return resourceInstance; - - - }catch (Exception e) { - e.printStackTrace(); - logger.error("Cannot update Service: " + oslResourceId + ": " + e.toString()); - } - return null; - } - - - /** - * @param serviceId - * @param s - * @param triggerServiceActionQueue is a cryptic thing. However it is used as follows: if FALSE, to just update the service status in catalog without further taking any action. - * if TRUE then the ServiceUpdate will trigger a ServiceActionQueue to further process the update. So this is needed to avoid these kinds of deadlocks - * @return - */ - public org.etsi.osl.tmf.sim638.model.Service updateService(String serviceId, ServiceUpdate s, boolean triggerServiceActionQueue) { - logger.info("will update Service : " + serviceId ); - try { - Map map = new HashMap<>(); - map.put("serviceid", serviceId ); - map.put("triggerServiceActionQueue", triggerServiceActionQueue ); - - Object response = template.requestBodyAndHeaders( CATALOG_UPD_SERVICE, toJsonString(s), map); - - if ( !(response instanceof String)) { - logger.error("Service Instance object is wrong."); - } - - org.etsi.osl.tmf.sim638.model.Service serviceInstance = toJsonObj( (String)response, org.etsi.osl.tmf.sim638.model.Service.class); - //logger.debug("createService response is: " + response); - return serviceInstance; - - - }catch (Exception e) { - logger.error("Cannot update Service: " + serviceId + ": " + e.toString()); - } - return null; - - } - - - - public LogicalResourceSpecification createOrUpdateResourceSpecByNameCategoryVersion( ResourceSpecificationCreate s) { - logger.info("will createOrUpdateResourceSpecByNameCategoryVersion " ); - try { - Map map = new HashMap<>(); - map.put("aname", s.getName()); - map.put("aversion", s.getVersion()); - map.put("acategory", s.getCategory()); - - Object response = template.requestBodyAndHeaders( CATALOG_UPDADD_RESOURCESPEC, toJsonString(s), map); - - if ( !(response instanceof String)) { - logger.error("ResourceSpecification object is wrong."); - } - - LogicalResourceSpecification rs = toJsonObj( (String)response, LogicalResourceSpecification.class); - return rs; - - - }catch (Exception e) { - logger.error("Cannot create ResourceSpecification"); - e.printStackTrace(); - } - return null; - - } - - static T toJsonObj(String content, Class valueType) throws IOException { - ObjectMapper mapper = new ObjectMapper(); - mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - return mapper.readValue( content, valueType); - } - - static String toJsonString(Object object) throws IOException { - ObjectMapper mapper = new ObjectMapper(); - mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); - return mapper.writeValueAsString(object); - } - - } diff --git a/src/main/java/org/etsi/osl/metrico/repo/JobRepository.java b/src/main/java/org/etsi/osl/metrico/repo/JobRepository.java deleted file mode 100644 index 17988b874539a8a9d02890da172c8900dca3746c..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/repo/JobRepository.java +++ /dev/null @@ -1,20 +0,0 @@ -package org.etsi.osl.metrico.repo; - -import org.etsi.osl.metrico.model.Job; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; -import org.springframework.stereotype.Repository; - -import java.util.List; -import java.util.Optional; -import java.util.UUID; - -@Repository -public interface JobRepository extends JpaRepository { - @Query("SELECT j FROM Job j WHERE j.deleted = false") - List findAllActiveJobs(); - - @Query("SELECT j FROM Job j WHERE j.uuid = :id AND j.deleted = false") - Optional findActiveById(@Param("id") UUID id); -} \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/reposervices/JobRepoService.java b/src/main/java/org/etsi/osl/metrico/reposervices/JobRepoService.java deleted file mode 100644 index 59522ea0550b63ce3fc7f58e83bafbbef10264d0..0000000000000000000000000000000000000000 --- a/src/main/java/org/etsi/osl/metrico/reposervices/JobRepoService.java +++ /dev/null @@ -1,87 +0,0 @@ -package org.etsi.osl.metrico.reposervices; - -import org.etsi.osl.metrico.model.Job; -import org.etsi.osl.metrico.repo.JobRepository; -import org.etsi.osl.tmf.pm628.model.ExecutionStateType; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Service; - -import java.time.OffsetDateTime; -import java.util.List; -import java.util.UUID; - -@Service -public class JobRepoService { - - private static final Logger logger = LoggerFactory.getLogger(JobRepoService.class); - - private void logJobNotFoundError(UUID jobId) { - logger.error("Job with ID {} not found.", jobId); - } - private JobRepository jobRepository; - - @Autowired - public JobRepoService(JobRepository jobRepository) { - this.jobRepository = jobRepository; - if (jobRepository == null) { - logger.error("JobRepository is null. Dependency injection failed."); - } - } - - - - public Job createAndSaveJob( Job job ) { - // Set properties on the job object as needed - return jobRepository.save(job); // This will persist the job to the database - } - - public Job updateJob(UUID jobId, ExecutionStateType newState, OffsetDateTime newStartDateTime, OffsetDateTime newEndDateTime, Integer newExecutionInterval) { - // Retrieve the existing Job - Job job = jobRepository.findById(jobId).orElse(null); - if (job == null) { - logJobNotFoundError(jobId); - return null; - } - // Update the fields as needed - if (newState != null) job.setState(newState); - if (newStartDateTime != null) job.setStartDateTime(newStartDateTime); - if (newEndDateTime != null) job.setEndDateTime(newEndDateTime); - if (newExecutionInterval != null) job.setExecutionInterval(newExecutionInterval); - - // Save the updated Job back to the database - return jobRepository.save(job); - } - - public Job updateJob(UUID jobId, ExecutionStateType newState) { - // Retrieve the existing Job - Job job = jobRepository.findById(jobId).orElse(null); - if (job == null) { - logJobNotFoundError(jobId); - return null; - } - // Update the fields as needed - if (newState != null) job.setState(newState); - // Save the updated Job back to the database - return jobRepository.save(job); - } - - public boolean softDeleteJob(Job ajob) { - Job job = jobRepository.findById(ajob.getUuid()).orElse(null); - if (job == null) { - logJobNotFoundError( ajob.getUuid() ); - return false; - } - logger.error("Job with ID {} will be DELETED.", ajob.getUuid() ); - job.setDeleted(true); - jobRepository.delete(job); - return true; - } - - public List findAll() { - - return (List) this.jobRepository.findAll(); - } - -} diff --git a/src/main/java/org/etsi/osl/metrico/services/JobService.java b/src/main/java/org/etsi/osl/metrico/services/JobService.java index 35519975ebb58f9014f5b1cf399c6d67cff4416a..bd42a54ad3d41b8bf5b5a8238b21927cfa1cc83a 100644 --- a/src/main/java/org/etsi/osl/metrico/services/JobService.java +++ b/src/main/java/org/etsi/osl/metrico/services/JobService.java @@ -1,23 +1,17 @@ package org.etsi.osl.metrico.services; import lombok.Getter; +import org.etsi.osl.metrico.MetricoCommonMethods; import org.etsi.osl.metrico.model.Job; -import org.etsi.osl.metrico.reposervices.JobRepoService; import org.etsi.osl.tmf.pm628.model.ExecutionStateType; -import org.etsi.osl.tmf.pm628.model.MeasurementCollectionJobRef; +import org.etsi.osl.tmf.pm628.model.MeasurementCollectionJobMVO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.context.event.ApplicationStartedEvent; -import org.springframework.context.event.EventListener; import org.springframework.stereotype.Service; import java.time.Duration; import java.time.OffsetDateTime; -import java.util.List; -import java.util.Map; -import java.util.UUID; import java.util.concurrent.*; @Service @@ -29,109 +23,129 @@ public class JobService { private static int threadPoolSize; @Getter private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(threadPoolSize); + @Getter + private final ConcurrentMap runningJobs = new ConcurrentHashMap<>(); - private final JobRepoService jobRepoService; - public JobService(JobRepoService jobRepoService) { - this.jobRepoService = jobRepoService; + private final MetricoCommonMethods metricoCommonMethods; + public JobService(MetricoCommonMethods metricoCommonMethods) { + this.metricoCommonMethods = metricoCommonMethods; } - - - - /** - * Schedules a new job to be executed periodically based on the provided parameters. - *

- * This method initializes a new {@link Job} instance with the specified start and end date times, and execution interval. - * It calculates the initial delay as the difference in seconds between the current time and the start date time. - * The job is initially set to a PENDING state. It then attempts to schedule the job to run at a fixed rate, - * starting after the initial delay and subsequently with the specified execution interval. - * If the job is successfully scheduled, its state is updated to INPROGRESS, and it is logged. - * In case of a scheduling failure due to a {@link RejectedExecutionException}, the job's state is set to FAILED, - * and the error is logged. - *

+ * Starts a job for the given MeasurementCollectionJob. * - * @param task the {@link Runnable} task that the job will execute - * @param startDateTime the {@link OffsetDateTime} specifying when the job should start - * @param endDateTime the {@link OffsetDateTime} specifying when the job should end - * @param executionInterval the interval, in seconds, between successive executions of the job - * @return the newly created and scheduled {@link Job} instance - * @throws RejectedExecutionException if the task cannot be scheduled for execution + * @param task the task to be executed + * @param job the job to be started + * @return the updated job + * @throws NullPointerException if the job or task is null + * @throws IllegalArgumentException if the job's start or end date is invalid + * @throws RejectedExecutionException if the job could not be scheduled */ - public Job startJob(Runnable task, Job job) { - - - if ( job.getEndDateTime().isBefore( OffsetDateTime.now() )) { - job.setState(ExecutionStateType.FAILED); - logger.error("Job with ID {} End Date is before now, the job will not be scheduled.", job.getUuid()); - return job; - } - - long initialDelay = Duration.between(OffsetDateTime.now(), job.getStartDateTime()).getSeconds(); - if (initialDelay<0) { - initialDelay = 0; - } - job = jobRepoService.createAndSaveJob(job); - - try { - ScheduledFuture future = scheduler.scheduleAtFixedRate(task, initialDelay, job.getExecutionInterval(), TimeUnit.SECONDS); - job.setFuture(future); - job.setState(ExecutionStateType.INPROGRESS); - logger.info("Job with ID {} started successfully.", job.getUuid()); - } catch (RejectedExecutionException e) { + public synchronized Job startJob(Runnable task, Job job) { + logger.debug("Starting Job for MeasurementCollectionJob with ID {}.", job.getMeasurementCollectionJobRef()); + MeasurementCollectionJobMVO mcjMVO = new MeasurementCollectionJobMVO(); + + if (job.getEndDateTime().isBefore(OffsetDateTime.now())) { job.setState(ExecutionStateType.FAILED); - logger.error("Job with ID {} could not be scheduled.", job.getUuid(), e); - } - + mcjMVO.setExecutionState(ExecutionStateType.FAILED); + logger.error("Job for MeasurementCollectionJob with ID {} End Date is before now, the MeasurementCollectionJob will not be scheduled.", job.getMeasurementCollectionJobRef().toString()); + } else { + long initialDelay = Duration.between(OffsetDateTime.now(), job.getStartDateTime()).getSeconds(); + if (initialDelay < 0) { + initialDelay = 0; + } + try { + ScheduledFuture future = scheduler.scheduleAtFixedRate( + task, + initialDelay, + job.getExecutionInterval(), + TimeUnit.SECONDS + ); - job = jobRepoService.updateJob( job.getUuid(), job.getState()); - + job.setFuture(future); + job.setState(ExecutionStateType.INPROGRESS); + mcjMVO.setExecutionState(ExecutionStateType.INPROGRESS); + runningJobs.put(job.getMeasurementCollectionJobRef().toString(), job); + logger.info("Job for MeasurementCollectionJob with ID {} started successfully.", job.getMeasurementCollectionJobRef().toString()); + } catch (RejectedExecutionException e) { + job.setState(ExecutionStateType.FAILED); + mcjMVO.setExecutionState(ExecutionStateType.FAILED); + logger.error("Job for MeasurementCollectionJob with ID {} could not be scheduled.", job.getMeasurementCollectionJobRef().toString(), e); + } + } + metricoCommonMethods.updateMeasurementCollectionJobById(job.getMeasurementCollectionJobRef().toString(), mcjMVO); return job; } /** - * Attempts to stop a job identified by its UUID. - *

- * This method checks if the job exists and its current state. If the job is already in a - * {@link ExecutionStateType#CANCELLED} or {@link ExecutionStateType#COMPLETED} state, it logs - * the status and returns. Otherwise, it attempts to cancel the job's future execution. - * If the cancellation is successful, the job's state is set to {@link ExecutionStateType#CANCELLED}, - * and it logs the successful stop. If the job cannot be stopped (e.g., already completed or cancelled), - * its state is set to {@link ExecutionStateType#PENDING}, and a warning is logged. If the job does not - * exist, it logs a warning. - *

+ * Stops the given job. * - * @param jobId the UUID of the job to stop + *

This method retrieves the associated MeasurementCollectionJob from the database and updates its state. + * If the job is already cancelled or completed, it removes the job from the runningJobs map and logs the status. + * If the job is still running, it attempts to cancel the job's future task and updates the job's state accordingly. + * The job is then removed from the runningJobs map and the MeasurementCollectionJob is updated in the database.

+ * + * @param job the job to be stopped */ - public void stopJob(Job job) { + public synchronized void stopJob(Job job) { - if (job != null) { - - if (job.getState() == ExecutionStateType.CANCELLED ) { - logger.info("Job with ID {} is already CANCELED.", job.getUuid()); - jobRepoService.softDeleteJob( job ); - return; - } else if (job.getState() == ExecutionStateType.COMPLETED) { - logger.info("Job with ID {} is already COMPLETED.", job.getUuid()); - jobRepoService.softDeleteJob( job ); - return; - } - if (job.getFuture() != null) { - boolean wasCancelled = job.getFuture().cancel(true); - if (wasCancelled) { - job.setState(ExecutionStateType.CANCELLED); - jobRepoService.updateJob(job.getUuid(), job.getState()); - logger.info("Job with ID {} stopped successfully.", job.getUuid()); - } else { - job.setState(ExecutionStateType.PENDING); - jobRepoService.updateJob( job.getUuid(), job.getState()); - logger.warn("Job with ID {} could not be stopped because it has already completed, has been cancelled, or could not be cancelled for some other reason.", job.getUuid()); - } + MeasurementCollectionJobMVO mcjMVO = new MeasurementCollectionJobMVO(); + + if (job.getState() == ExecutionStateType.CANCELLED) { + logger.debug("Job for MeasurementCollectionJob with ID {} is already CANCELED.", job.getMeasurementCollectionJobRef().toString()); + runningJobs.remove(job.getMeasurementCollectionJobRef().toString()); + return; + } else if (job.getState() == ExecutionStateType.COMPLETED) { + logger.debug("Job for MeasurementCollectionJob with ID {} is already COMPLETED.", job.getMeasurementCollectionJobRef().toString()); + runningJobs.remove(job.getMeasurementCollectionJobRef().toString()); + return; + } + if (job.getFuture() != null) { + boolean wasCancelled = job.getFuture().cancel(true); + if (wasCancelled) { + job.setState(ExecutionStateType.CANCELLED); + mcjMVO.setExecutionState(ExecutionStateType.CANCELLED); + runningJobs.remove(job.getMeasurementCollectionJobRef().toString()); + logger.debug("Job for MeasurementCollectionJob with ID {} stopped successfully.", job.getMeasurementCollectionJobRef().toString()); + } else { + job.setState(ExecutionStateType.PENDING); + mcjMVO.setExecutionState(ExecutionStateType.PENDING); + logger.debug("Job for MeasurementCollectionJob with ID {} could not be stopped because it has already completed, has been cancelled, or could not be cancelled for some other reason.", + job.getMeasurementCollectionJobRef().toString()); } + metricoCommonMethods.updateMeasurementCollectionJobById(job.getMeasurementCollectionJobRef().toString(), mcjMVO); + } + } + + /** + * Stops the job associated with the given Measurement Collection Job UUID. + * + *

This method retrieves the job from the runningJobs map using the provided UUID. + * If the job is found, it calls the existing stopJob method to stop the job. + * If the job is not found, it logs a warning message.

+ * + * @param measurementCollectionJobUuid the UUID of the Measurement Collection Job + */ + public synchronized void stopJob(String measurementCollectionJobUuid) { + Job job = runningJobs.get(measurementCollectionJobUuid); + if (job != null) { + stopJob(job); } else { - logger.warn("Job does not exist."); + logger.warn("No job found with associated with MeasurementCollectionJob with UUID: {}", measurementCollectionJobUuid); + } + } + + /** + * Stops all running jobs. + * + *

This method iterates over all jobs in the runningJobs map, stops each job, and then clears the map.

+ */ + public synchronized void stopAllJobs() { + for (Job job : runningJobs.values()) { + stopJob(job); } + runningJobs.clear(); } } \ No newline at end of file diff --git a/src/main/java/org/etsi/osl/metrico/services/MetricoService.java b/src/main/java/org/etsi/osl/metrico/services/MetricoService.java index 04b4d92680da9801fa81695483600080861d51a0..e3b54f3443e9d4c98865ccfb41f95f07aafaf6bf 100644 --- a/src/main/java/org/etsi/osl/metrico/services/MetricoService.java +++ b/src/main/java/org/etsi/osl/metrico/services/MetricoService.java @@ -1,289 +1,357 @@ package org.etsi.osl.metrico.services; +import jakarta.annotation.PreDestroy; import jakarta.validation.constraints.NotNull; -import org.apache.camel.ProducerTemplate; import org.apache.camel.builder.RouteBuilder; -import org.etsi.osl.metrico.JsonUtil; -import org.etsi.osl.metrico.mapper.DataAccessEndpointMapper; +import org.etsi.osl.metrico.MetricoCommonMethods; import org.etsi.osl.metrico.mapper.JobMapper; import org.etsi.osl.metrico.model.Job; import org.etsi.osl.metrico.prometheus.PrometheusQueries; -import org.etsi.osl.metrico.repo.JobRepository; -import org.etsi.osl.metrico.reposervices.JobRepoService; -import org.etsi.osl.tmf.common.model.Any; import org.etsi.osl.tmf.common.model.ELifecycle; import org.etsi.osl.tmf.common.model.EValueType; -import org.etsi.osl.tmf.common.model.service.ResourceRef; +import org.etsi.osl.tmf.common.model.Notification; +import org.etsi.osl.tmf.common.model.service.Characteristic; +import org.etsi.osl.tmf.common.model.service.ServiceStateType; import org.etsi.osl.tmf.pm628.model.*; import org.etsi.osl.tmf.rcm634.model.LogicalResourceSpecification; import org.etsi.osl.tmf.rcm634.model.ResourceSpecificationCreate; -import org.etsi.osl.tmf.ri639.model.LogicalResource; -import org.etsi.osl.tmf.ri639.model.Resource; -import org.etsi.osl.tmf.ri639.model.ResourceUpdate; -import org.etsi.osl.tmf.so641.model.ServiceOrder; +import org.etsi.osl.tmf.rcm634.model.ResourceSpecificationRef; +import org.etsi.osl.tmf.scm633.model.ServiceSpecification; +import org.etsi.osl.tmf.sim638.model.ServiceAttributeValueChangeNotification; +import org.etsi.osl.tmf.sim638.model.ServiceDeleteNotification; +import org.etsi.osl.tmf.sim638.model.ServiceStateChangeNotification; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.event.ApplicationStartedEvent; import org.springframework.context.event.EventListener; import org.springframework.stereotype.Service; -import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; import java.time.OffsetDateTime; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.databind.ObjectMapper; @Service public class MetricoService extends RouteBuilder { - private static final Logger logger = LoggerFactory.getLogger(JobService.class); - - public static final String OSL_METRICO_RSPEC_NAME = "METRICO_Resource_Specification"; - public static final String OSL_METRICO_RSPEC_VERSION = "0.0.1"; + public static final String OSL_METRICO_RSPEC_VERSION = "1.0.0"; public static final String OSL_METRICO_RSPEC_CATEGORY = "metrico.osl.etsi.org/v1"; - public static final String OSL_METRICO_RESOURCE_CATEGORY = "metrico.osl.etsi.org/v1"; public static final String OSL_METRICO_RSPEC_TYPE = "LogicalResourceSpecification"; public static final String OSL_METRICO_RSPEC_DESCRIPTION = "This Specification is used to describe a generic METRICO job resource"; + private static final Logger logger = LoggerFactory.getLogger(MetricoService.class); + private static String OSL_METRICO_RSPEC_ID = null; - @Value("${PM_MEASUREMENT_COLLECTION_JOB_UPDATE}") - private String PM_MEASUREMENT_COLLECTION_JOB_UPDATE = ""; - - @Value("${PM_MEASUREMENT_COLLECTION_GET_JOB_BY_ID}") - private String PM_MEASUREMENT_COLLECTION_GET_JOB_BY_ID = ""; - - @Autowired - private JobRepoService jobRepoService; - - - @Autowired - private JobRepository jobRepository; - - - @Autowired + private final MetricoCommonMethods metricoCommonMethods; private final PrometheusQueries prometheusQueries; - private final ProducerTemplate producerTemplate; + private final JobService jobService; - public MetricoService(PrometheusQueries prometheusQueries, ProducerTemplate producerTemplate) { + public MetricoService(PrometheusQueries prometheusQueries, MetricoCommonMethods metricoCommonMethods, JobService jobService) { this.prometheusQueries = prometheusQueries; - this.producerTemplate = producerTemplate; + this.metricoCommonMethods = metricoCommonMethods; + this.jobService = jobService; } - - - /** - * This one is executed when the cridge service application starts - * @param event - */ + + @Override + public void configure() throws Exception { + // TODO Auto-generated method stub + } + @EventListener(ApplicationStartedEvent.class) public void onApplicationEvent() { - - registerMetricoResourceSpec(); - - List jobsPending = jobRepoService.findAll(); - logger.info("===== Pending jobs from previous sessions ====="); - for (Job job : jobsPending) { - logger.info("try to resume jobuuid: {}, state:{}, start: {}, end:{}, mcjid: {} ", job.getUuid(), job.getState(), job.getStartDateTime(), job.getEndDateTime(), job.getMeasurementCollectionJobRef() ); - - - //delete previous job from DB. a new one will be created - jobRepoService.softDeleteJob(job); - - MeasurementCollectionJobRef mjref = new MeasurementCollectionJobRef(); - mjref.setId( job.getMeasurementCollectionJobRef().toString() ); - this.startPeriodicQueryToPrometheusRef(mjref ); - } - - logger.info("===== Pending jobs from previous sessions done ====="); - + // When METRICO starts, it checks if a related resource spec exists, and if it not, it creates it. + registerMetricoResourceSpec(); + // When METRICO starts, it checks if there are any pending or unfinished jobs from previous sessions + // and tries to resume them. + restartPendingOrInProgressJobs(); + + } + + @PreDestroy + public void onShutdown() { + jobService.stopAllJobs(); + logger.info("All running jobs have been stopped."); } private void registerMetricoResourceSpec() { - logger.info("===== Pending jobs from previous sessions ====="); - - - ResourceSpecificationCreate rsc = new ResourceSpecificationCreate(); - rsc.setName( OSL_METRICO_RSPEC_NAME ); - rsc.setCategory( OSL_METRICO_RSPEC_CATEGORY ); - rsc.setVersion( OSL_METRICO_RSPEC_VERSION ); - rsc.setDescription( OSL_METRICO_RSPEC_DESCRIPTION ); - rsc.setType( OSL_METRICO_RSPEC_TYPE ); - - rsc.setLifecycleStatus( ELifecycle.ACTIVE.getValue() ); - rsc.addResourceSpecificationCharacteristicItemShort( "_MT_CHARACTERISTIC_NAME", "", EValueType.TEXT.getValue(), "The characteristic of the service with id _MT_SERVICEUUID that will be updated with monitoring metrics", false); - rsc.addResourceSpecificationCharacteristicItemShort( "_MT_SERVICEUUID", "", EValueType.TEXT.getValue(), "The id of the service to update", false); - rsc.addResourceSpecificationCharacteristicItemShort( "_MT_END_TIME", "", EValueType.TEXT.getValue(), "The ending time of the monitoring job", false); - rsc.addResourceSpecificationCharacteristicItemShort( "_MT_START_TIME", "", EValueType.TEXT.getValue(), "The starting time of the monitoring job", false); - rsc.addResourceSpecificationCharacteristicItemShort( "_MT_RECURRING_INTERVAL", "G_1MN", EValueType.TEXT.getValue(), "The polling interval of the monitoring source", false); - rsc.addResourceSpecificationCharacteristicItemShort( "_MT_TYPE", "PROMETHEUS", EValueType.TEXT.getValue(), "The monitoring source type", false); - rsc.addResourceSpecificationCharacteristicItemShort( "_MT_QUERY", "", EValueType.TEXT.getValue(), "The query towards the monitoring source (e.g. query=gnb_service_state)", false); - rsc.addResourceSpecificationCharacteristicItemShort( "_MT_URL", "", EValueType.TEXT.getValue(), "The monitoring source URL (e.g. https://prom.osl.etsi.org:9090)", false); - - - LogicalResourceSpecification result = prometheusQueries.createOrUpdateResourceSpecByNameCategoryVersion(rsc); - while ( result == null ) { - try { - logger.info("Cannot get resource for registerMetricoResourceSpec. Retrying in 10 seconds" ); - Thread.sleep( 10000 ); - } catch (InterruptedException e) { - e.printStackTrace(); + ResourceSpecificationCreate rsc = new ResourceSpecificationCreate(); + rsc.setName(OSL_METRICO_RSPEC_NAME); + rsc.setCategory(OSL_METRICO_RSPEC_CATEGORY); + rsc.setVersion(OSL_METRICO_RSPEC_VERSION); + rsc.setDescription(OSL_METRICO_RSPEC_DESCRIPTION); + rsc.setType(OSL_METRICO_RSPEC_TYPE); + + rsc.setLifecycleStatus(ELifecycle.ACTIVE.getValue()); + rsc.addResourceSpecificationCharacteristicItemShort("_MT_CHARACTERISTIC_NAME", "", EValueType.TEXT.getValue(), "The characteristic of the service with id _MT_SERVICEUUID that will be updated with monitoring metrics", false); + rsc.addResourceSpecificationCharacteristicItemShort("_MT_SERVICEUUID", "", EValueType.TEXT.getValue(), "The id of the service to update", false); + rsc.addResourceSpecificationCharacteristicItemShort("_MT_RECURRING_INTERVAL", "G_1MN", EValueType.TEXT.getValue(), "The polling interval of the monitoring source", false); + rsc.addResourceSpecificationCharacteristicItemShort("_MT_TYPE", "PROMETHEUS", EValueType.TEXT.getValue(), "The monitoring source type", false); + rsc.addResourceSpecificationCharacteristicItemShort("_MT_QUERY", "", EValueType.TEXT.getValue(), "The query towards the monitoring source (e.g. query=gnb_service_state)", false); + rsc.addResourceSpecificationCharacteristicItemShort("_MT_URL", "", EValueType.TEXT.getValue(), "The monitoring source URL (e.g. https://prom.osl.etsi.org:9090)", false); + + LogicalResourceSpecification result = metricoCommonMethods.createOrUpdateResourceSpecByNameCategoryVersion(rsc); + + while (result == null) { + try { + logger.info("Cannot get resource for registerMetricoResourceSpec. Retrying in 10 seconds"); + Thread.sleep(10000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + result = metricoCommonMethods.createOrUpdateResourceSpecByNameCategoryVersion(rsc); } - result = prometheusQueries.createOrUpdateResourceSpecByNameCategoryVersion(rsc); - } + OSL_METRICO_RSPEC_ID = result.getId(); } + public void restartPendingOrInProgressJobs() { + logger.info("===== Looking for PENDING or IN_PROGRESS Measurement Collection Jobs from previous sessions ====="); + List jobsPending = metricoCommonMethods.listPendingOrInProgressMeasurementCollectionJobs(); + jobService.stopAllJobs(); + if (jobsPending != null) { + logger.info("===== Started resuming PENDING or IN_PROGRESS Measurement Collection Jobs from previous sessions ====="); + for (MeasurementCollectionJob measurementCollectionJob : jobsPending) { + measurementCollectionJob = metricoCommonMethods.retrieveMeasurementCollectionJob(measurementCollectionJob.getUuid()); + if (measurementCollectionJob.getDataAccessEndpoint() == null || measurementCollectionJob.getDataAccessEndpoint().size() != 1) { + logger.warn("MeasurementCollectionJob with uuid: {} has {} dataAccessEndpoint(s), skipping.", + measurementCollectionJob.getUuid(), + measurementCollectionJob.getDataAccessEndpoint() == null ? 0 : measurementCollectionJob.getDataAccessEndpoint().size()); + MeasurementCollectionJobMVO mcjMVO = new MeasurementCollectionJobMVO(); + mcjMVO.setExecutionState(ExecutionStateType.FAILED); + metricoCommonMethods.updateMeasurementCollectionJobById(measurementCollectionJob.getUuid(), mcjMVO); + continue; + } + if (measurementCollectionJob.getScheduleDefinition().size() > 1) { + logger.warn("MeasurementCollectionJob with uuid: {} has more than 1 ScheduleDefinitions, skipping.", + measurementCollectionJob.getUuid()); + MeasurementCollectionJobMVO mcjMVO = new MeasurementCollectionJobMVO(); + mcjMVO.setExecutionState(ExecutionStateType.FAILED); + metricoCommonMethods.updateMeasurementCollectionJobById(measurementCollectionJob.getUuid(), mcjMVO); + continue; + } else if (measurementCollectionJob.getScheduleDefinition().size() == 1) { + // If the ScheduleDefinitionEndTime is null, set it to 1 hour after the ScheduleDefinitionStartTime to check if it is past due + if (measurementCollectionJob.getScheduleDefinition().get(0).getScheduleDefinitionEndTime() == null && measurementCollectionJob.getScheduleDefinition().get(0).getScheduleDefinitionStartTime() != null) { + measurementCollectionJob.getScheduleDefinition().get(0).setScheduleDefinitionEndTime(measurementCollectionJob.getScheduleDefinition().get(0).getScheduleDefinitionStartTime().plusHours(1)); + } else if (measurementCollectionJob.getScheduleDefinition().get(0).getScheduleDefinitionEndTime() == null && measurementCollectionJob.getScheduleDefinition().get(0).getScheduleDefinitionStartTime() == null) { + measurementCollectionJob.getScheduleDefinition().get(0).setScheduleDefinitionEndTime(measurementCollectionJob.getCreationTime().plusHours(1)); + } + // If the ScheduleDefinitionEndTime is before the current time, skip the job + if (measurementCollectionJob.getScheduleDefinition().get(0).getScheduleDefinitionEndTime().isBefore(OffsetDateTime.now())) { + logger.warn("MeasurementCollectionJob with uuid: {} has a ScheduleDefinition that has already ended, skipping.", + measurementCollectionJob.getUuid()); + MeasurementCollectionJobMVO mcjMVO = new MeasurementCollectionJobMVO(); + mcjMVO.setExecutionState(ExecutionStateType.FAILED); + metricoCommonMethods.updateMeasurementCollectionJobById(measurementCollectionJob.getUuid(), mcjMVO); + continue; + } + } else { + // If there is no ScheduleDefinition, set the end time to 1 hour after the creation time + measurementCollectionJob.addScheduleDefinitionItem(new ScheduleDefinition()); + measurementCollectionJob.getScheduleDefinition().get(0).setScheduleDefinitionStartTime(measurementCollectionJob.getCreationTime()); + measurementCollectionJob.getScheduleDefinition().get(0).setScheduleDefinitionEndTime(measurementCollectionJob.getCreationTime().plusHours(1)); + + if (measurementCollectionJob.getScheduleDefinition().get(0).getScheduleDefinitionEndTime().isBefore(OffsetDateTime.now())) { + logger.warn("MeasurementCollectionJob with uuid: {} has a ScheduleDefinition that has already ended, skipping.", + measurementCollectionJob.getUuid()); + MeasurementCollectionJobMVO mcjMVO = new MeasurementCollectionJobMVO(); + mcjMVO.setExecutionState(ExecutionStateType.FAILED); + metricoCommonMethods.updateMeasurementCollectionJobById(measurementCollectionJob.getUuid(), mcjMVO); + continue; + } + } + logger.info("===== Resuming measurementCollectionJob with uuid: {} =====", measurementCollectionJob.getUuid()); + this.startPeriodicQueryToPrometheus(measurementCollectionJob); + } + logger.info("===== Finished resuming PENDING or IN_PROGRESS Measurement Collection Jobs from previous sessions ====="); + } else { + logger.info("===== No PENDING OF IN_PROGRESS Measurement Collection Jobs from previous sessions to restart ====="); + } + } - @Autowired - private ProducerTemplate template; - public String[] queryToPrometheus(@NotNull MeasurementCollectionJob givenMCJ){ - DataAccessEndpoint givenDataAccessEndpoint = givenMCJ.getDataAccessEndpoint().get(0); + public void startPeriodicQueryToPrometheus(@NotNull MeasurementCollectionJob givenMCJ) { Job job = JobMapper.measurementCollectionJobMapToJob(givenMCJ); String promURL = job.getDataAccessEndPointUri().getScheme() + "://" + job.getDataAccessEndPointUri().getAuthority(); String promQuery = job.getDataAccessEndPointUri().getQuery(); - promQuery = promQuery.replace("query=", ""); - - String [] promResponse = prometheusQueries.sendQueryToPrometheus(promURL, promQuery, givenMCJ, job).split("\n"); + logger.atInfo().setMessage("Periodic query started, with ID: " + job.getMeasurementCollectionJobRef()).log(); + MeasurementCollectionJobMVO measurementCollectionJobMVO = new MeasurementCollectionJobMVO(); + job = prometheusQueries.startPeriodicQuery(promURL, promQuery, job, givenMCJ); - DataFilterTemplate filterTemplate = new DataFilterTemplate(); - filterTemplate.setName(promQuery); - DataFilterAttributeStringArray stringArray = new DataFilterAttributeStringArray(); - stringArray.setValue(List.of(promResponse)); - DataFilterMapItem dataFilterMapItem = new DataFilterMapItem(); - dataFilterMapItem.setFilterTemplate(filterTemplate); - dataFilterMapItem.setStringArray(stringArray); - DataFilterMap dataFilterMap = new DataFilterMap(); - dataFilterMap.addMappingsItem(dataFilterMapItem); - givenDataAccessEndpoint.setUriQueryFilter(dataFilterMap); + if (job.getState() == ExecutionStateType.FAILED) { + logger.atError().setMessage("Periodic query failed to start due to internal error.").log(); + } else { + logger.atInfo().setMessage("Periodic query started, with ID: " + job.getMeasurementCollectionJobRef()).log(); + } + measurementCollectionJobMVO.setExecutionState(job.getState()); - List newDataAccessEndpointMVO = new ArrayList<>(); - newDataAccessEndpointMVO.add(DataAccessEndpointMapper.INSTANCE.toDataAccessEndpointMVO(givenDataAccessEndpoint)); + givenMCJ = metricoCommonMethods.updateMeasurementCollectionJobById(givenMCJ.getUuid(), measurementCollectionJobMVO); + if (givenMCJ != null) { + metricoCommonMethods.updateRelatedResource(givenMCJ); + } + } -// MeasurementCollectionJobMVO promResponseMCJ = new MeasurementCollectionJobMVO(); -// promResponseMCJ.setDataAccessEndpoint(newDataAccessEndpointMVO); -// producerTemplate.sendBodyAndHeader(PM_MEASUREMENT_COLLECTION_JOB_UPDATE, JsonUtil.toJsonString(promResponseMCJ),"mcjid",givenMCJ.getUuid() ); + public void startPeriodicQueryToPrometheusRef(@NotNull MeasurementCollectionJobRef mcjRef) { + MeasurementCollectionJob givenMCJ = metricoCommonMethods.retrieveMeasurementCollectionJob(mcjRef); - return promResponse; + startPeriodicQueryToPrometheus(givenMCJ); } - public void startPeriodicQueryToPrometheus(@NotNull MeasurementCollectionJob givenMCJ){ - Job job = JobMapper.measurementCollectionJobMapToJob(givenMCJ); - String promURL = job.getDataAccessEndPointUri().getScheme() + "://" + job.getDataAccessEndPointUri().getAuthority(); - String promQuery = job.getDataAccessEndPointUri().getQuery(); - job = prometheusQueries.startPeriodicQuery(promURL, promQuery, job, givenMCJ ); + public void startPeriodicQueryToPrometheusEvent(@NotNull MeasurementCollectionJobCreateEvent mcjevent) { - if (job.getState() == ExecutionStateType.FAILED) { - logger.atError().setMessage("Periodic query failed to start due to internal error.").log(); - + MeasurementCollectionJob givenMCJ = metricoCommonMethods.retrieveMeasurementCollectionJob(mcjevent.getEvent().getMeasurementCollectionJob().getId()); + + if (givenMCJ != null) { + startPeriodicQueryToPrometheus(givenMCJ); } else { - logger.atInfo().setMessage("Periodic query started, with ID: " + job.getUuid()).log(); + logger.error("=======> CANNOT retrieve Measurement Collection Job with mcjId = " + mcjevent.getEvent().getMeasurementCollectionJob().getId() + " from activeMQ"); } - - givenMCJ.setExecutionState(job.getState()); - - producerTemplate.sendBodyAndHeader( PM_MEASUREMENT_COLLECTION_JOB_UPDATE, JsonUtil.toJsonString(givenMCJ), "mcjid", givenMCJ.getUuid() ); - updateRelatedResource(givenMCJ); } + public void handleServiceEvent(final Notification n) { + + org.etsi.osl.tmf.sim638.model.Service service = null; + ServiceSpecification serviceSpec = null; + MeasurementCollectionJob mcj = null; + ResourceSpecificationRef rSpec = null; + boolean isMetricoRFSService = false; + boolean isRunningJob = false; + + if (n instanceof ServiceStateChangeNotification) { + service = ((ServiceStateChangeNotification) n).getEvent().getService(); + } else if (n instanceof ServiceDeleteNotification) { + service = ((ServiceDeleteNotification) n).getEvent().getService(); + } else if (n instanceof ServiceAttributeValueChangeNotification) { + service = ((ServiceAttributeValueChangeNotification) n).getEvent().getService(); + } - - public void startPeriodicQueryToPrometheusRef(@NotNull MeasurementCollectionJobRef mcjRef){ - MeasurementCollectionJob givenMCJ = retrieveMeasurementCollectionJob(mcjRef); - - startPeriodicQueryToPrometheus(givenMCJ); - } - - - public void startPeriodicQueryToPrometheusEvent(@NotNull MeasurementCollectionJobCreateEvent mcjevent){ - - MeasurementCollectionJob givenMCJ = retrieveMeasurementCollectionJob( mcjevent.getEvent().getMeasurementCollectionJob().getId() ); - - if ( givenMCJ != null) { - startPeriodicQueryToPrometheus(givenMCJ); - } else { - - logger.error("=======> CANNOT retrieve Measurement Collection Job with mcjId = " + mcjevent.getEvent().getMeasurementCollectionJob().getId() +" from activeMQ"); - } - } - - public MeasurementCollectionJob retrieveMeasurementCollectionJob(String mcjId) { - - logger.debug("will retrieve Measurement Collection Job with mcjId = " + mcjId +" from database"); - try { - Object response = template. - requestBody( PM_MEASUREMENT_COLLECTION_GET_JOB_BY_ID, mcjId); - if ( !(response instanceof String)) { - logger.error("Measurement Collection Job object is wrong."); - return null; + // Check if it is a METRICO RFS service + if (service != null && service.getServiceSpecificationRef() != null) { + serviceSpec = metricoCommonMethods.retrieveServiceSpecificationById(service.getServiceSpecificationRef().getId()); + if (serviceSpec != null && serviceSpec.getResourceSpecification().size() == 1) { + rSpec = serviceSpec.getResourceSpecification().iterator().next(); + if (rSpec.getId().equalsIgnoreCase(OSL_METRICO_RSPEC_ID)) { + isMetricoRFSService = true; + } } - logger.debug("retrieveMeasurementCollectionJobById response is: " + response); - MeasurementCollectionJob mcj = JsonUtil.toJsonObj( (String)response, MeasurementCollectionJob.class); - return mcj; - }catch (Exception e) { - logger.error("Cannot retrieve Measurement Collection Job details from database. " + e.toString()); + } else { + logger.debug("Service {} is not a METRICO service, skipping.", service.getId()); + return; } - return null; - } - public MeasurementCollectionJob retrieveMeasurementCollectionJob(MeasurementCollectionJobRef mcjRef) { - String mcjId = mcjRef.getId(); + if (isMetricoRFSService) { + String mcjRefId = service.getServiceCharacteristicByName("_MT_MCJ_REFID").getValue().getValue(); + mcj = metricoCommonMethods.retrieveMeasurementCollectionJob(mcjRefId); - return retrieveMeasurementCollectionJob(mcjId); - } - - - private void updateRelatedResource(@NotNull MeasurementCollectionJob givenMCJ) { - //retrieve related service from inventory - //retrieve related resource from inventory - //patch resource state - String servUUID = givenMCJ.getProducingApplicationId();//this contains the related ServiceUUID with this MCJ - - logger.debug("updateRelatedResource servUUID = " + servUUID ); - org.etsi.osl.tmf.sim638.model.Service aService = prometheusQueries.retrieveService(servUUID); - - if ( aService!=null && aService.getSupportingResource().size()>0) { - - ResourceRef resRef = aService.getSupportingResource().stream().findFirst().get(); - - //Resource aResource = retrieveResource(resRef.getId()); - logger.debug("updateRelatedResource resRef = " + resRef.getId() ); - - ResourceUpdate rup = new ResourceUpdate(); - org.etsi.osl.tmf.ri639.model.Characteristic resCharacteristicItem = new org.etsi.osl.tmf.ri639.model.Characteristic(); - resCharacteristicItem.setName( "_MT_MCJ_REF" ); - resCharacteristicItem.setValueType( "TEXT" ); - Any val = new Any(); - val.setValue( givenMCJ.getUuid() ); - val.setAlias( "" ); - resCharacteristicItem.setValue( val ); - rup.addResourceCharacteristicItem( resCharacteristicItem ); - - if ( givenMCJ.getExecutionState().equals( ExecutionStateType.FAILED ) ) { - rup.setResourceStatus( org.etsi.osl.tmf.ri639.model.ResourceStatusType.SUSPENDED ); + if(mcj.getExecutionState() !=null) { + if (mcj.getExecutionState().equals(ExecutionStateType.INPROGRESS) || mcj.getExecutionState().equals(ExecutionStateType.PENDING)) { + isRunningJob = true; + } + } + + if (n instanceof ServiceStateChangeNotification && service.getState() == ServiceStateType.TERMINATED) { + logger.debug("Service {} is a METRICO service with state TERMINATED. Terminating related job.", service.getId()); + jobService.stopJob(String.valueOf(service.getServiceCharacteristicByName("_MT_MCJ_REFID").getValue().getValue())); + } else if (n instanceof ServiceDeleteNotification) { + logger.debug("Service {} is a METRICO service that was deleted. Terminating related job.", service.getId()); + jobService.stopJob(String.valueOf(service.getServiceCharacteristicByName("_MT_MCJ_REFID").getValue().getValue())); + } else if (n instanceof ServiceAttributeValueChangeNotification && isRunningJob) { + logger.debug("Service {} is a METRICO service that was updated. Updating related job.", service.getId()); + + MeasurementCollectionJobMVO mcjMVO = new MeasurementCollectionJobMVO(); + + mcjMVO.setExecutionState(ExecutionStateType.PENDING); + + MeasurementCollectionJob mcjOld = metricoCommonMethods.retrieveMeasurementCollectionJob(mcjRefId); + Characteristic serviceCharacteristic; + + if (!mcjOld.getProducingApplicationId().equals(service.getId())) { + mcjMVO.setProducingApplicationId(service.getServiceSpecificationRef().getId()); + } + serviceCharacteristic = service.getServiceCharacteristicByName("_MT_CHARACTERISTIC_NAME"); + String characteristicName = String.valueOf(serviceCharacteristic.getValue().getValue()); + if (metricoCommonMethods.notNullOrEmpty(characteristicName) && !mcjOld.getOutputFormat().equals(characteristicName)) { + mcjMVO.setOutputFormat(characteristicName); + } + serviceCharacteristic = service.getServiceCharacteristicByName("_MT_SERVICEUUID"); + String cfs_id = String.valueOf(serviceCharacteristic.getValue().getValue()); + if (metricoCommonMethods.notNullOrEmpty(cfs_id) && !mcjOld.getConsumingApplicationId().equals(cfs_id)) { + mcjMVO.setConsumingApplicationId(cfs_id); + } + ScheduleDefinitionMVO scheduleDefinitionNew = new ScheduleDefinitionMVO(); + ScheduleDefinition scheduleDefinitionOld = mcjOld.getScheduleDefinition().get(0); + boolean scheduleDefinitionChanged = false; + if (!scheduleDefinitionOld.getScheduleDefinitionStartTime().equals(service.getStartDate())) { + scheduleDefinitionNew.setScheduleDefinitionStartTime(service.getStartDate()); + scheduleDefinitionChanged = true; + } + if (!scheduleDefinitionOld.getScheduleDefinitionEndTime().equals(service.getEndDate())) { + scheduleDefinitionNew.setScheduleDefinitionEndTime(service.getEndDate()); + scheduleDefinitionChanged = true; + } + if (scheduleDefinitionChanged) { + mcjMVO.addScheduleDefinitionItem(scheduleDefinitionNew); + } + + serviceCharacteristic = service.getServiceCharacteristicByName("_MT_RECURRING_INTERVAL"); + String recurringIntervalString = String.valueOf(serviceCharacteristic.getValue().getValue()); + if (metricoCommonMethods.notNullOrEmpty(recurringIntervalString) && !mcjOld.getGranularity().toString().equalsIgnoreCase(recurringIntervalString)) { + if (Granularity.contains(recurringIntervalString)) { + mcjMVO.setGranularity(Granularity.valueOf(recurringIntervalString)); + } + } + + boolean monitoringTypeChanged = false; + DataAccessEndpointMVO daeMVO = new DataAccessEndpointMVO(); + DataAccessEndpoint daeOld = mcjOld.getDataAccessEndpoint().get(0); + serviceCharacteristic = service.getServiceCharacteristicByName("_MT_TYPE"); + String monitoringType = String.valueOf(serviceCharacteristic.getValue().getValue()); + if (metricoCommonMethods.notNullOrEmpty(monitoringType) && !daeOld.getApiType().equalsIgnoreCase(monitoringType)) { + daeMVO.setApiType(monitoringType); + monitoringTypeChanged = true; + } + + boolean uriChanged = false; + serviceCharacteristic = service.getServiceCharacteristicByName("_MT_QUERY"); + String monitoringQuery = String.valueOf(serviceCharacteristic.getValue().getValue()); + serviceCharacteristic = service.getServiceCharacteristicByName("_MT_URL"); + String monitoringURL = String.valueOf(serviceCharacteristic.getValue().getValue()); + URI newUri = null; + try { + newUri = new URI(monitoringURL + "?" + monitoringQuery); + } catch (URISyntaxException e) { + throw new RuntimeException(e); + } + if (!daeOld.getUri().equals(newUri)) { + daeMVO.setUri(newUri); + uriChanged = true; + } + // This is a workaround because the APIType and URI are not mutually exclusive in the MVO. + // If the monitoring type has changed, we keep the old URI, and if the URI has changed, we keep the old APIType. + if(monitoringTypeChanged && !uriChanged) { + daeMVO.setUri(daeOld.getUri()); + } else if ((!monitoringTypeChanged) && uriChanged) { + daeMVO.setApiType(daeOld.getApiType()); + } + + if (uriChanged || monitoringTypeChanged) { + mcjMVO.addDataAccessEndpointItem(daeMVO); + } + + jobService.stopJob(String.valueOf(service.getServiceCharacteristicByName("_MT_MCJ_REFID").getValue().getValue())); + + MeasurementCollectionJob updatedMCJ = metricoCommonMethods.updateMeasurementCollectionJobById( + mcjOld.getUuid(), mcjMVO); + + startPeriodicQueryToPrometheus(updatedMCJ); + } else { + logger.debug("Service {} is a METRICO service with state {}. No action taken.", service.getId(), service.getState()); + } } else { - rup.setResourceStatus( org.etsi.osl.tmf.ri639.model.ResourceStatusType.AVAILABLE ); + logger.debug("Service {} is not a METRICO RFS service, skipping.", service.getId()); } - - prometheusQueries.updateResourceById(resRef.getId(), rup ); - - } - } +} - @Override - public void configure() throws Exception { - // TODO Auto-generated method stub - - } - - - -} diff --git a/src/main/java/org/etsi/osl/metrico/services/MetricoServiceRouteBuilder.java b/src/main/java/org/etsi/osl/metrico/services/MetricoServiceRouteBuilder.java index 9a62a499356766a8d218f18818e3e266955c1d0c..1bfda8edd0a3d796130672e0667c5c6a211dcd31 100644 --- a/src/main/java/org/etsi/osl/metrico/services/MetricoServiceRouteBuilder.java +++ b/src/main/java/org/etsi/osl/metrico/services/MetricoServiceRouteBuilder.java @@ -5,10 +5,10 @@ import org.apache.camel.builder.RouteBuilder; import org.apache.camel.model.dataformat.JsonLibrary; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.etsi.osl.tmf.pm628.model.MeasurementCollectionJob; import org.etsi.osl.tmf.pm628.model.MeasurementCollectionJobCreateEvent; -import org.etsi.osl.tmf.pm628.model.MeasurementCollectionJobRef; -import org.etsi.osl.tmf.ri639.model.ResourceCreateNotification; +import org.etsi.osl.tmf.sim638.model.ServiceAttributeValueChangeNotification; +import org.etsi.osl.tmf.sim638.model.ServiceDeleteNotification; +import org.etsi.osl.tmf.sim638.model.ServiceStateChangeNotification; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; @@ -26,13 +26,16 @@ public class MetricoServiceRouteBuilder extends RouteBuilder { @Value("${EVENT_MEASUREMENT_COLLECTION_JOB_CREATE}") private String EVENT_MEASUREMENT_COLLECTION_JOB_CREATE = ""; - public void configure() throws Exception { + @Value("${EVENT_SERVICE_STATE_CHANGED}") + private String EVENT_SERVICE_STATE_CHANGED = ""; + + @Value("${EVENT_SERVICE_DELETE}") + private String EVENT_SERVICE_DELETE = ""; -// from(EVENT_MEASUREMENT_COLLECTION_JOB_CREATED) -// .log(LoggingLevel.INFO, log, EVENT_MEASUREMENT_COLLECTION_JOB_CREATED + " message received!") -// .to("log:DEBUG?showBody=true&showHeaders=true").unmarshal() -// .json(JsonLibrary.Jackson, MeasurementCollectionJob.class, true) -// .bean(metricoService, "startPeriodicQueryToPrometheus(${body})"); + @Value("${EVENT_SERVICE_ATTRIBUTE_VALUE_CHANGED}") + private String EVENT_SERVICE_ATTRIBUTE_VALUE_CHANGED = ""; + + public void configure() throws Exception { from(EVENT_MEASUREMENT_COLLECTION_JOB_CREATE) .log(LoggingLevel.INFO, log, EVENT_MEASUREMENT_COLLECTION_JOB_CREATE + " message received!") @@ -41,7 +44,26 @@ public class MetricoServiceRouteBuilder extends RouteBuilder { .json(JsonLibrary.Jackson, MeasurementCollectionJobCreateEvent.class, true) .bean(metricoService, "startPeriodicQueryToPrometheusEvent(${body})"); - } + from(EVENT_SERVICE_STATE_CHANGED) + .log(LoggingLevel.INFO, log, EVENT_SERVICE_STATE_CHANGED + " message received!") + .to("log:DEBUG?showBody=true&showHeaders=true") + .unmarshal() + .json(JsonLibrary.Jackson, ServiceStateChangeNotification.class, true) + .bean(metricoService, "handleServiceEvent"); + from(EVENT_SERVICE_DELETE) + .log(LoggingLevel.INFO, log, EVENT_SERVICE_DELETE + " message received!") + .to("log:DEBUG?showBody=true&showHeaders=true") + .unmarshal() + .json(JsonLibrary.Jackson, ServiceDeleteNotification.class, true) + .bean(metricoService, "handleServiceEvent"); + + from(EVENT_SERVICE_ATTRIBUTE_VALUE_CHANGED) + .log(LoggingLevel.INFO, log, EVENT_SERVICE_ATTRIBUTE_VALUE_CHANGED + " message received!") + .to("log:DEBUG?showBody=true&showHeaders=true") + .unmarshal() + .json(JsonLibrary.Jackson, ServiceAttributeValueChangeNotification.class, true) + .bean(metricoService, "handleServiceEvent"); + } } diff --git a/src/main/resources/application-testing.yml b/src/main/resources/application-testing.yml new file mode 100644 index 0000000000000000000000000000000000000000..74955cc298ea515d5a7507b3b1488c83f575b349 --- /dev/null +++ b/src/main/resources/application-testing.yml @@ -0,0 +1,69 @@ +spring: + profiles: + active: + "testing" + config: + activate: + on-profile: "testing" + application: + name: metrico + main: + web-application-type: servlet + activemq: + brokerUrl: tcp://localhost:61616?jms.watchTopicAdvisories=false + user: artemis + password: artemis + pool: + enabled: true + max-connections: 100 + packages: + trust-all: true + security: + oauth2: + resourceserver: + jwt: + issuer-uri: http://keycloak:8080/auth/realms/openslice + jwk-set-uri: http://keycloak:8080/auth/realms/openslice/.well-known/openid-configuration +server: + port: 8030 + + +logging: + level: + org.etsi.osl.metrico: DEBUG + root: INFO + org.springframework: INFO + org.apache.camel: INFO + reactor.netty.tcp.TcpClient: DEBUG + reactor.netty.http.client.HttpClient: DEBUG + pattern: + console: "%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" + file: "%d %p %c{1.} [%t] %m%n" + +scheduling.enabled: true + +#NUMBER OF THREADS FOR THE METRICO THREAD POOL +METRICO_THREAD_POOL_SIZE: 10 + +#TMF QUEUES +PM_MEASUREMENT_COLLECTION_GET_JOB_BY_ID: "direct:PM.MEASUREMENTCOLLECTIONJOB.GET_BY_ID" +PM_MEASUREMENT_COLLECTION_JOBS_GET: "direct:PM.MEASUREMENTCOLLECTIONJOBS.GET" +PM_MEASUREMENT_COLLECTION_JOB_ADD: "direct:PM.MEASUREMENTCOLLECTIONJOB.ADD" +PM_MEASUREMENT_COLLECTION_JOB_UPDATE: "direct:PM.MEASUREMENTCOLLECTIONJOB.UPDATE" +PM_MEASUREMENT_COLLECTION_JOB_GET_INPROGRESS_OR_PENDING: "jms:queue:PM.MEASUREMENTCOLLECTIONJOB.GET_INPROGRESS_OR_PENDING" + +EVENT_MEASUREMENT_COLLECTION_JOB_CREATE: "direct:topic:EVENT.MEASUREMENTCOLLECTIONJOB.CREATE" +EVENT_MEASUREMENT_COLLECTION_JOB_EXECUTION_STATE_CHANGED: "direct:topic:EVENT.MEASUREMENTCOLLECTIONJOB.STATECHANGED" +EVENT_MEASUREMENT_COLLECTION_JOB_DELETE: "direct:topic:EVENT.MEASUREMENTCOLLECTIONJOB.DELETE" +EVENT_MEASUREMENT_COLLECTION_JOB_ATTRIBUTE_VALUE_CHANGED: "direct:topic:EVENT.MEASUREMENTCOLLECTIONJOB.ATTRCHANGED" + +CATALOG_UPDADD_RESOURCESPEC: "direct:CATALOG.UPDADD.RESOURCESPEC" +CATALOG_GET_SERVICE_BY_ID: "direct:CATALOG.GET.SERVICE" +CATALOG_GET_RESOURCE_BY_ID: "direct:CATALOG.GET.RESOURCE" +CATALOG_GET_SERVICESPEC_BY_ID: "jms:queue:CATALOG.GET.SERVICESPEC_BY_ID" +CATALOG_UPD_RESOURCE: "direct:CATALOG.UPD.RESOURCE" +CATALOG_UPD_SERVICE: "direct:CATALOG.UPD.SERVICE" + +EVENT_SERVICE_STATE_CHANGED: "jms:topic:EVENT.SERVICE.STATECHANGED" +EVENT_SERVICE_DELETE: "jms:topic:EVENT.SERVICE.DELETE" +EVENT_SERVICE_ATTRIBUTE_VALUE_CHANGED: "jms:topic:EVENT.SERVICE" \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 0ea2b555df598dcdf45f74ee6a8d4916ea03a3a7..3948c4a5449e07384e095791948b4ae5b60465dd 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -6,28 +6,6 @@ spring: name: metrico main: web-application-type: servlet - datasource: - url: jdbc:mysql://localhost:13306/metricodb?createDatabaseIfNotExist=true&useUnicode=true&characterEncoding=utf8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC - password: letmein - username: root - hikari: - minimumIdle: 2 - maximumPoolSize: 40 - idleTimeout: 120000 - connectionTimeout: 400000 - leakDetectionThreshold: 100000 - jpa: - database-platform: org.etsi.osl.metrico.LocalMysqlDialect - hibernate: - ddl-auto: update - show-sql: false - generate-ddl: true - properties: - hibernate: - connection: - characterEncoding: utf-8 - CharSet: utf-8 - useUnicode: true activemq: brokerUrl: tcp://localhost:61616?jms.watchTopicAdvisories=false user: artemis @@ -69,6 +47,7 @@ PM_MEASUREMENT_COLLECTION_GET_JOB_BY_ID: "jms:queue:PM.MEASUREMENTCOLLECTIONJOB. PM_MEASUREMENT_COLLECTION_JOBS_GET: "jms:queue:PM.MEASUREMENTCOLLECTIONJOBS.GET" PM_MEASUREMENT_COLLECTION_JOB_ADD: "jms:queue:PM.MEASUREMENTCOLLECTIONJOB.ADD" PM_MEASUREMENT_COLLECTION_JOB_UPDATE: "jms:queue:PM.MEASUREMENTCOLLECTIONJOB.UPDATE" +PM_MEASUREMENT_COLLECTION_JOB_GET_INPROGRESS_OR_PENDING: "jms:queue:PM.MEASUREMENTCOLLECTIONJOB.GET_INPROGRESS_OR_PENDING" EVENT_MEASUREMENT_COLLECTION_JOB_CREATE: "jms:topic:EVENT.MEASUREMENTCOLLECTIONJOB.CREATE" EVENT_MEASUREMENT_COLLECTION_JOB_EXECUTION_STATE_CHANGED: "jms:topic:EVENT.MEASUREMENTCOLLECTIONJOB.STATECHANGED" @@ -77,6 +56,11 @@ EVENT_MEASUREMENT_COLLECTION_JOB_ATTRIBUTE_VALUE_CHANGED: "jms:topic:EVENT.MEASU CATALOG_UPDADD_RESOURCESPEC: "jms:queue:CATALOG.UPDADD.RESOURCESPEC" CATALOG_GET_SERVICE_BY_ID: "jms:queue:CATALOG.GET.SERVICE" +CATALOG_GET_SERVICESPEC_BY_ID: "jms:queue:CATALOG.GET.SERVICESPEC_BY_ID" CATALOG_GET_RESOURCE_BY_ID: "jms:queue:CATALOG.GET.RESOURCE" CATALOG_UPD_RESOURCE: "jms:queue:CATALOG.UPD.RESOURCE" CATALOG_UPD_SERVICE: "jms:queue:CATALOG.UPD.SERVICE" + +EVENT_SERVICE_STATE_CHANGED: "jms:topic:EVENT.SERVICE.STATECHANGED" +EVENT_SERVICE_DELETE: "jms:topic:EVENT.SERVICE.DELETE" +EVENT_SERVICE_ATTRIBUTE_VALUE_CHANGED: "jms:topic:EVENT.SERVICE.ATTRCHANGED" \ No newline at end of file diff --git a/src/test/java/org/etsi/osl/metrico/JsonUtilTest.java b/src/test/java/org/etsi/osl/metrico/JsonUtilTest.java new file mode 100644 index 0000000000000000000000000000000000000000..49f838ad6e65ec466387b24a6b21ef786196abe0 --- /dev/null +++ b/src/test/java/org/etsi/osl/metrico/JsonUtilTest.java @@ -0,0 +1,54 @@ +package org.etsi.osl.metrico; + +import org.etsi.osl.tmf.pm628.model.MeasurementCollectionJob; +import org.etsi.osl.tmf.pm628.model.MeasurementCollectionJobMVO; +import org.junit.jupiter.api.Test; + +import java.io.IOException; + +import static org.junit.jupiter.api.Assertions.*; + +class JsonUtilTest { + + @Test + void toJsonObj_validJsonString_returnsObject() throws IOException { + String jsonString = "{\"@type\":\"MeasurementCollectionJob\",\"uuid\":\"f47ac10b-58cc-4372-a567-0e02b2c3d479\"}"; + MeasurementCollectionJobMVO mcj = JsonUtil.toJsonObj(jsonString, MeasurementCollectionJobMVO.class); + assertNotNull(mcj); + assertEquals("f47ac10b-58cc-4372-a567-0e02b2c3d479", mcj.getUuid()); + } + + @Test + void toJsonObj_invalidJsonString_throwsIOException() { + String invalidJsonString = "{\"executionState\":\"INPROGRESS\""; + assertThrows(IOException.class, () -> { + JsonUtil.toJsonObj(invalidJsonString, MeasurementCollectionJob.class); + }); + } + + @Test + void toJsonString_validObject_returnsJsonString() { + MeasurementCollectionJobMVO mcj = new MeasurementCollectionJobMVO(); + String uuid = "f47ac10b-58cc-4372-a567-0e02b2c3d479"; + mcj.setUuid(uuid); + String jsonString = JsonUtil.toJsonString(mcj); + assertTrue(jsonString.contains("\"uuid\":\"f47ac10b-58cc-4372-a567-0e02b2c3d479\"")); + } + + @Test + void toJsonString_nullObject_returnsNull() { + String jsonString = JsonUtil.toJsonString(null); + assertNull(jsonString); + } + + @Test + void toJsonString_unserializableObject_returnsNull() { + class SelfRef { + public SelfRef ref; + } + SelfRef obj = new SelfRef(); + obj.ref = obj; // creates a circular reference + String jsonString = JsonUtil.toJsonString(obj); + assertNull(jsonString); + } +} \ No newline at end of file diff --git a/src/test/java/org/etsi/osl/metrico/MetricoCommonMethodsTest.java b/src/test/java/org/etsi/osl/metrico/MetricoCommonMethodsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c0d2c16aa613aed503156f2327132e939f771fb8 --- /dev/null +++ b/src/test/java/org/etsi/osl/metrico/MetricoCommonMethodsTest.java @@ -0,0 +1,325 @@ +package org.etsi.osl.metrico; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.annotation.PostConstruct; +import org.apache.camel.CamelContext; +import org.apache.camel.ProducerTemplate; +import org.apache.camel.builder.RouteBuilder; +import org.etsi.osl.tmf.common.model.ELifecycle; +import org.etsi.osl.tmf.common.model.EValueType; +import org.etsi.osl.tmf.pm628.model.*; +import org.etsi.osl.tmf.rcm634.model.LogicalResourceSpecification; +import org.etsi.osl.tmf.rcm634.model.ResourceSpecificationCharacteristic; +import org.etsi.osl.tmf.ri639.model.LogicalResource; +import org.etsi.osl.tmf.ri639.model.ResourceUpdate; +import org.etsi.osl.tmf.sim638.model.Service; +import org.etsi.osl.tmf.sim638.model.ServiceUpdate; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.TestConfiguration; + +import java.io.IOException; +import java.net.URI; +import java.time.OffsetDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.StringJoiner; + +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest(properties = { + "PM_MEASUREMENT_COLLECTION_JOB_UPDATE = direct:PM.MEASUREMENTCOLLECTIONJOB.UPDATE", + "PM_MEASUREMENT_COLLECTION_GET_JOB_BY_ID = direct:PM.MEASUREMENTCOLLECTIONJOB.GET_BY_ID", + "PM_MEASUREMENT_COLLECTION_JOBS_GET = direct:PM.MEASUREMENTCOLLECTIONJOBS.GET", + "PM_MEASUREMENT_COLLECTION_JOB_GET_INPROGRESS_OR_PENDING = direct:PM.MEASUREMENTCOLLECTIONJOB.GET_INPROGRESS_OR_PENDING", + "CATALOG_GET_SERVICE_BY_ID = direct:CATALOG.GET.SERVICE", + "CATALOG_UPD_SERVICE = direct:CATALOG.UPD.SERVICE", + "CATALOG_GET_RESOURCE_BY_ID = direct:CATALOG.GET.RESOURCE", + "CATALOG_UPD_RESOURCE = direct:CATALOG.UPD.RESOURCE", + "CATALOG_UPDADD_RESOURCESPEC = direct:CATALOG.UPDADD.RESOURCESPEC" +}) +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class MetricoCommonMethodsTest { + + static String OSL_METRICO_RSPEC_NAME = "Metrico_Resource_Specification"; + static String OSL_METRICO_RSPEC_CATEGORY = "metrico.osl.etsi.org/v1"; + static String OSL_METRICO_RSPEC_VERSION = "1.0.0"; + static String OSL_METRICO_RSPEC_DESCRIPTION = "This Specification is used to describe a generic METRICO job resource"; + static String OSL_METRICO_RSPEC_TYPE = "LogicalResourceSpecification"; + + @TestConfiguration + static class CamelTestRoutesConfig { + private final CamelContext camelContext; + + public CamelTestRoutesConfig(CamelContext camelContext) { + this.camelContext = camelContext; + } + + @PostConstruct + public void registerRoutes() throws Exception { + camelContext.addRoutes( + new RouteBuilder() { + @Override + public void configure() { + from("direct:PM.MEASUREMENTCOLLECTIONJOB.UPDATE").bean(MetricoCommonMethodsTest.class, "mockUpdateMeasurementCollectionJob(${header.mcjid}, ${body})"); + from("direct:PM.MEASUREMENTCOLLECTIONJOB.GET_BY_ID").bean(MetricoCommonMethodsTest.class, "mockFindMeasurementCollectionJobByUuidEagerAsString"); + from("direct:PM.MEASUREMENTCOLLECTIONJOBS.GET").bean(MetricoCommonMethodsTest.class, "mockFindAllMeasurementCollectionJobs"); + from("direct:PM.MEASUREMENTCOLLECTIONJOB.GET_INPROGRESS_OR_PENDING").bean(MetricoCommonMethodsTest.class, "mockFindPendingOrInProgressMeasurementCollectionJobsAsJson"); + from("direct:CATALOG.GET.SERVICE").bean(MetricoCommonMethodsTest.class, "mockGetServiceEagerAsString"); + from("direct:CATALOG.UPD.SERVICE").bean(MetricoCommonMethodsTest.class, "mockUpdateService(${header.serviceid}, ${body}, ${header.triggerServiceActionQueue})"); + from("direct:CATALOG.GET.RESOURCE").bean(MetricoCommonMethodsTest.class, "mockGetResourceEagerAsString"); + from("direct:CATALOG.UPD.RESOURCE").bean(MetricoCommonMethodsTest.class, "mockUpdateResource(${header.resourceId}, ${body}, ${header.triggerServiceActionQueue})"); + from("direct:CATALOG.UPDADD.RESOURCESPEC").bean(MetricoCommonMethodsTest.class, "mockAddOrUpdateResourceSpecificationByNameCategoryVersion()"); + } + } + ); + } + } + + @Autowired + private ProducerTemplate template; + @Autowired + private MetricoCommonMethods methods; + + @Test + void testRetrieveMeasurementCollectionJob() throws Exception { + String jobId = "default-job-uuid"; + MeasurementCollectionJob result = methods.retrieveMeasurementCollectionJob(jobId); + assertNotNull(result); + assertEquals(jobId, result.getUuid()); + } + + @Test + void testRetrieveMeasurementCollectionJobNull() throws Exception { + String jobId = "not-in-db-job-uuid"; + MeasurementCollectionJob result = methods.retrieveMeasurementCollectionJob(jobId); + assertNull(result); + } + + @Test + void testRetrieveMeasurementCollectionJobNFromMcjRef() throws Exception { + MeasurementCollectionJobRef mcjRef = new MeasurementCollectionJobRef(); + mcjRef.setId("default-job-uuid"); + MeasurementCollectionJob result = methods.retrieveMeasurementCollectionJob(mcjRef); + assertNotNull(result); + assertEquals(mcjRef.getId(), result.getUuid()); + } + + @Test + void testRetrieveMeasurementCollectionJobNFromMcjRefNull() throws Exception { + MeasurementCollectionJobRef mcjRef = new MeasurementCollectionJobRef(); + mcjRef.setId("not-in-db-job-uuid"); + MeasurementCollectionJob result = methods.retrieveMeasurementCollectionJob(mcjRef); + assertNull(result); + } + + @Test + void testListMeasurementCollectionJob(){ + List jobs = methods.listMeasurementCollectionJob(); + assertNotNull(jobs); + assertFalse(jobs.isEmpty()); + assertEquals(2, jobs.size()); // We mocked two jobs in the method + } + + @Test + void testListPendingOrInProgressMeasurementCollectionJobs() { + List jobs = methods.listPendingOrInProgressMeasurementCollectionJobs(); + assertNull(jobs); + } + + @Test + void testUpdateMeasurementCollectionJobById() { + String jobId = "default-job-uuid"; + MeasurementCollectionJobMVO mcjMVO = new MeasurementCollectionJobMVO(); + mcjMVO.setUuid(jobId); + + mcjMVO.setGranularity(Granularity.G_1H); + + + MeasurementCollectionJob result = methods.updateMeasurementCollectionJobById(jobId, mcjMVO); + MeasurementCollectionJob updatedJob; + + assertNotNull(result); + assertEquals(result.getUuid(), jobId); + assertEquals(Granularity.G_1H, result.getGranularity()); + } + +// Bellow here are the mocked methods for the test class + public static String mockUpdateMeasurementCollectionJob(String uuid, String mcjMVOString) { + MeasurementCollectionJob mcj = defaultMeasurementCollectionJob(); + + MeasurementCollectionJobMVO mcjMVO = null; + try { + mcjMVO = JsonUtil.toJsonObj(mcjMVOString, MeasurementCollectionJobMVO.class); + } catch (IOException e) { + throw new RuntimeException(e); + } + + mcj.setGranularity(mcjMVO.getGranularity()); + + return JsonUtil.toJsonString(mcj); + } + + public static String mockFindMeasurementCollectionJobByUuidEagerAsString(String uuid) { + if(uuid.equals("default-job-uuid")) { + return JsonUtil.toJsonString(defaultMeasurementCollectionJob()); + } + else return null; + } + + public static String mockFindAllMeasurementCollectionJobs() { + MeasurementCollectionJob job1 = defaultMeasurementCollectionJob(); + MeasurementCollectionJob job2 = defaultMeasurementCollectionJob(); + job2.setUuid("another-job-uuid"); + List jobs = List.of(job1, job2); + + try { + ObjectMapper objectMapper = new ObjectMapper(); + String jsonArray; + + List jobJsonStrings = new ArrayList<>(); + for (MeasurementCollectionJob job : jobs) { + jobJsonStrings.add(objectMapper.writeValueAsString(job)); + } + StringJoiner joiner = new StringJoiner(",", "[", "]"); + for (String jobStr : jobJsonStrings) { + joiner.add(jobStr); + } + jsonArray = joiner.toString(); + return jsonArray; + } catch (JsonProcessingException e) { + throw new RuntimeException("Failed to serialize jobs to JSON", e); + } + } + + public static String mockFindPendingOrInProgressMeasurementCollectionJobsAsJson() { + return null; + } + + public static String mockGetServiceEagerAsString(String serviceId) { + try { + Service service = new Service(); + service.setUuid("mock-service-id"); + service.setName("Mock Service"); + // Set other fields as needed for your tests + + ObjectMapper mapper = new ObjectMapper(); + return mapper.writeValueAsString(service); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static String mockUpdateService(String serviceId, ServiceUpdate body, Boolean triggerServiceActionQueue) { + try { + Service service = new Service(); + service.setUuid("mock-service-id"); + service.setName("Updated Mock Service"); + // Optionally, set more fields based on the ServiceUpdate body if needed + + ObjectMapper mapper = new ObjectMapper(); + return mapper.writeValueAsString(service); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static String mockGetResourceEagerAsString(String resourceId) { + try { + LogicalResource resource = new LogicalResource(); + resource.setUuid("mock-service-id"); + resource.setName("Mock Resource"); + // Set other fields as needed for your tests + + ObjectMapper mapper = new ObjectMapper(); + return mapper.writeValueAsString(resource); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static String mockUpdateResource(String resourceId, ResourceUpdate body, Boolean triggerServiceActionQueue) { + try { + LogicalResource resource = new LogicalResource(); + resource.setUuid("mock-service-id"); + resource.setName("Updated Mock Resource"); + // Optionally, set more fields based on the ResourceUpdate body if needed + + ObjectMapper mapper = new ObjectMapper(); + return mapper.writeValueAsString(resource); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static String mockAddOrUpdateResourceSpecificationByNameCategoryVersion() { + return JsonUtil.toJsonString(defaultResourceSpecification()); + } + + + public static LogicalResourceSpecification defaultResourceSpecification() { + LogicalResourceSpecification rsc = new LogicalResourceSpecification(); + rsc.setName(OSL_METRICO_RSPEC_NAME); + rsc.setCategory(OSL_METRICO_RSPEC_CATEGORY); + rsc.setVersion(OSL_METRICO_RSPEC_VERSION); + rsc.setDescription(OSL_METRICO_RSPEC_DESCRIPTION); + rsc.setType(OSL_METRICO_RSPEC_TYPE); + rsc.setLifecycleStatus(ELifecycle.ACTIVE.getValue()); + + ResourceSpecificationCharacteristic characteristic = new ResourceSpecificationCharacteristic(); + characteristic.setValueType(EValueType.TEXT.getValue()); + + characteristic.setName("_MT_CHARACTERISTIC_NAME"); + rsc.addResourceSpecCharacteristicItem(characteristic); + + characteristic.setName("_MT_SERVICEUUID"); + rsc.addResourceSpecCharacteristicItem(characteristic); + + characteristic.setName("_MT_END_TIME"); + rsc.addResourceSpecCharacteristicItem(characteristic); + + characteristic.setName("_MT_START_TIME"); + rsc.addResourceSpecCharacteristicItem(characteristic); + + characteristic.setName("_MT_QUERY"); + rsc.addResourceSpecCharacteristicItem(characteristic); + + characteristic.setName("_MT_URL"); + rsc.addResourceSpecCharacteristicItem(characteristic); + + characteristic.setName("_MT_RECURRING_INTERVAL"); + rsc.addResourceSpecCharacteristicItem(characteristic); + + characteristic.setName("_MT_TYPE"); + rsc.addResourceSpecCharacteristicItem(characteristic); + + return rsc; + } + + static MeasurementCollectionJob defaultMeasurementCollectionJob() { + MeasurementCollectionJob job = new MeasurementCollectionJob(); + job.setCreationTime(OffsetDateTime.now()); + job.setUuid("default-job-uuid"); + job.setGranularity(Granularity.G_1MN); + job.setExecutionState(ExecutionStateType.PENDING); + + DataAccessEndpoint dae = new DataAccessEndpoint(); + dae.setUri(URI.create("http://example.com/data")); + dae.apiType("PROMETHEUS"); + List daeList = new ArrayList<>(); + daeList.add(dae); + job.setDataAccessEndpoint(daeList); + + ScheduleDefinition sd = new ScheduleDefinition(); + sd.setScheduleDefinitionStartTime(OffsetDateTime.now()); + sd.setScheduleDefinitionEndTime(OffsetDateTime.now().plusHours(1)); + List sdList = new ArrayList<>(); + sdList.add(sd); + + return job; + } + +} \ No newline at end of file diff --git a/src/test/java/org/etsi/osl/metrico/mapper/JobMapperTest.java b/src/test/java/org/etsi/osl/metrico/mapper/JobMapperTest.java index 40da5a53eae9cea07c5c8c27f32b19910e38f7f5..c9e1012a9bba3e4901f5aef093d5e19221cd0f6d 100644 --- a/src/test/java/org/etsi/osl/metrico/mapper/JobMapperTest.java +++ b/src/test/java/org/etsi/osl/metrico/mapper/JobMapperTest.java @@ -1,44 +1,68 @@ package org.etsi.osl.metrico.mapper; +import org.etsi.osl.metrico.model.Job; import org.etsi.osl.tmf.pm628.model.DataAccessEndpoint; -import org.etsi.osl.tmf.pm628.model.DataFilterMap; -import org.etsi.osl.tmf.pm628.model.DataFilterMapItem; +import org.etsi.osl.tmf.pm628.model.Granularity; import org.etsi.osl.tmf.pm628.model.MeasurementCollectionJob; -import org.jetbrains.annotations.NotNull; +import org.etsi.osl.tmf.pm628.model.ScheduleDefinition; +import org.junit.jupiter.api.Test; import java.net.URI; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import static org.junit.jupiter.api.Assertions.*; public class JobMapperTest { - public MeasurementCollectionJob measurementCollectionJobCreate() { + @Test + public void testMeasurementCollectionJobMapToJob() { MeasurementCollectionJob measurementCollectionJob = new MeasurementCollectionJob(); - - List dataAccessEndpointList = new ArrayList<>(); - dataAccessEndpointList.add(dataAccessEndpointCreate()); - measurementCollectionJob.setUuid("9f22dc98-f439-4fdd-98e3-f6471cf8ca67"); - measurementCollectionJob.setDataAccessEndpoint(dataAccessEndpointList); - - - return measurementCollectionJob; - } - public DataAccessEndpoint dataAccessEndpointCreate(){ DataAccessEndpoint dataAccessEndpoint = new DataAccessEndpoint(); dataAccessEndpoint.setUuid("123e4567-e89b-12d3-a456-426614174000"); - dataAccessEndpoint.setUri(URI.create("example.com")); + dataAccessEndpoint.setUri(URI.create("http://example.com")); dataAccessEndpoint.setApiType("Prometheus"); - return dataAccessEndpoint; - } + List dataAccessEndpointList = new ArrayList<>(); + dataAccessEndpointList.add(dataAccessEndpoint); + measurementCollectionJob.setDataAccessEndpoint(dataAccessEndpointList); + + ScheduleDefinition scheduleDefinition = new ScheduleDefinition(); + scheduleDefinition.setScheduleDefinitionStartTime("2023-01-01T00:00:00Z"); + scheduleDefinition.setScheduleDefinitionEndTime("2023-01-02T00:00:00Z"); - public DataFilterMap dataFilterMapCreate(){ - DataFilterMap dataFilterMap = new DataFilterMap(); - // dataFilterMap.setMappings(); + List scheduleDefinitionList = new ArrayList<>(); + scheduleDefinitionList.add(scheduleDefinition); + measurementCollectionJob.setScheduleDefinition(scheduleDefinitionList); - return dataFilterMap; + Granularity granularity = Granularity.G_1H; + measurementCollectionJob.setGranularity(granularity); + + Job job = JobMapper.measurementCollectionJobMapToJob(measurementCollectionJob); + + assertNotNull(job); + assertEquals(UUID.fromString("9f22dc98-f439-4fdd-98e3-f6471cf8ca67"), job.getMeasurementCollectionJobRef()); + assertEquals(UUID.fromString("123e4567-e89b-12d3-a456-426614174000"), job.getDataAccessEndPointRef()); + assertEquals("Prometheus", job.getApiType()); + assertEquals(URI.create("http://example.com"), job.getDataAccessEndPointUri()); + assertEquals("2023-01-01T00:00Z", job.getStartDateTime().toString()); + assertEquals("2023-01-02T00:00Z", job.getEndDateTime().toString()); + assertEquals(3600, job.getExecutionInterval()); } + @Test + public void testConvertGranularityToSeconds() { + assertEquals(60, JobMapper.convertGranularityToSeconds("G_1MN")); + assertEquals(3600, JobMapper.convertGranularityToSeconds("G_1H")); + assertEquals(2592000, JobMapper.convertGranularityToSeconds("G_1M")); + assertEquals(31536000, JobMapper.convertGranularityToSeconds("G_1Y")); + } -} + @Test + public void testConvertGranularityToSecondsInvalidFormat() { + assertThrows(IllegalArgumentException.class, () -> JobMapper.convertGranularityToSeconds("G_1W")); + } +} \ No newline at end of file diff --git a/src/test/java/org/etsi/osl/metrico/model/JobTest.java b/src/test/java/org/etsi/osl/metrico/model/JobTest.java index 31a6c295dcf2918437526b8723b6ce5d79489f10..eb3f79b17c3c5c6a802ea50ca8366ea69c22c76e 100644 --- a/src/test/java/org/etsi/osl/metrico/model/JobTest.java +++ b/src/test/java/org/etsi/osl/metrico/model/JobTest.java @@ -3,6 +3,7 @@ package org.etsi.osl.metrico.model; import org.etsi.osl.tmf.pm628.model.ExecutionStateType; import org.junit.jupiter.api.Test; +import java.net.URI; import java.time.OffsetDateTime; import java.time.temporal.ChronoUnit; import java.util.UUID; @@ -55,7 +56,8 @@ class JobTest { @Test void testToString() { Job job = new Job(); - job.setUuid(UUID.fromString("123e4567-e89b-12d3-a456-426614174000")); + URI daeUri = URI.create("http://example.com/api/v1/query?query=ue_count&time=1749633"); + job.setState(ExecutionStateType.PENDING); job.setStartDateTime(OffsetDateTime.parse("2023-01-01T10:15:30+01:00")); job.setEndDateTime(OffsetDateTime.parse("2023-01-02T10:15:30+01:00")); @@ -63,10 +65,12 @@ class JobTest { job.setDataAccessEndPointRef(UUID.fromString("123e4567-e89b-12d3-a456-426614174001")); job.setScheduleDefinitionRef(UUID.fromString("123e4567-e89b-12d3-a456-426614174002")); job.setMeasurementCollectionJobRef(UUID.fromString("123e4567-e89b-12d3-a456-426614174003")); - job.setDeleted(false); + job.setDataAccessEndPointUri(daeUri); + job.setApiType("Prometheus"); + String actualJobToString = job.toString(); - String expected = "Job{uuid=123e4567-e89b-12d3-a456-426614174000, state=pending, startDateTime=2023-01-01T10:15:30+01:00, endDateTime=2023-01-02T10:15:30+01:00, executionInterval=10, dataAccessEndPointRef=123e4567-e89b-12d3-a456-426614174001, scheduleDefinitionRef=123e4567-e89b-12d3-a456-426614174002, measurementCollectionJobRef=123e4567-e89b-12d3-a456-426614174003, deleted=false}"; - assertEquals(expected, job.toString()); + String expectedJobToString = "Job{state=pending, startDateTime=2023-01-01T10:15:30+01:00, endDateTime=2023-01-02T10:15:30+01:00, executionInterval=10, dataAccessEndPointRef=123e4567-e89b-12d3-a456-426614174001, scheduleDefinitionRef=123e4567-e89b-12d3-a456-426614174002, measurementCollectionJobRef=123e4567-e89b-12d3-a456-426614174003, deleted=false}"; + assertEquals(expectedJobToString, actualJobToString); } } \ No newline at end of file diff --git a/src/test/java/org/etsi/osl/metrico/model/SupportedDataAccessEndpointsTest.java b/src/test/java/org/etsi/osl/metrico/model/SupportedDataAccessEndpointsTest.java new file mode 100644 index 0000000000000000000000000000000000000000..413a061f2a9baa0f160fc9080b0c3e5546a6e874 --- /dev/null +++ b/src/test/java/org/etsi/osl/metrico/model/SupportedDataAccessEndpointsTest.java @@ -0,0 +1,33 @@ +package org.etsi.osl.metrico.model; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class SupportedDataAccessEndpointsTest { + + @Test + void testContainsWithValidApiType() { + assertTrue(SupportedDataAccessEndpoints.contains("PROMETHEUS")); + } + + @Test + void testContainsWithValidApiTypeLowerCase() { + assertTrue(SupportedDataAccessEndpoints.contains("prometheus")); + } + + @Test + void testContainsWithInvalidApiType() { + assertFalse(SupportedDataAccessEndpoints.contains("INFLUXDB")); + } + + @Test + void testContainsWithEmptyString() { + assertFalse(SupportedDataAccessEndpoints.contains("")); + } + + @Test + void testContainsWithNull() { + assertThrows(NullPointerException.class, () -> SupportedDataAccessEndpoints.contains(null)); + } +} \ No newline at end of file diff --git a/src/test/java/org/etsi/osl/metrico/prometheus/PrometheusQueriesTest.java b/src/test/java/org/etsi/osl/metrico/prometheus/PrometheusQueriesTest.java new file mode 100644 index 0000000000000000000000000000000000000000..864af405a2c8da050349bc9b1ece545d2ff8ccb1 --- /dev/null +++ b/src/test/java/org/etsi/osl/metrico/prometheus/PrometheusQueriesTest.java @@ -0,0 +1,152 @@ +package org.etsi.osl.metrico.prometheus; + +import org.etsi.osl.metrico.MetricoCommonMethods; +import org.etsi.osl.metrico.model.Job; +import org.etsi.osl.metrico.services.JobService; +import org.etsi.osl.tmf.pm628.model.ExecutionStateType; +import org.etsi.osl.tmf.pm628.model.MeasurementCollectionJob; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.MockedStatic; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.lang.reflect.Field; +import java.time.OffsetDateTime; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +class PrometheusQueriesTest { + + private JobService jobService; + private MetricoCommonMethods metricoCommonMethods; + private PrometheusQueries prometheusQueries; + + + @BeforeEach + void setUp() { + jobService = mock(JobService.class); + metricoCommonMethods = mock(MetricoCommonMethods.class); + prometheusQueries = new PrometheusQueries(jobService, metricoCommonMethods); + } + + @Test + void testConstructor_AssignsDependencies() throws Exception { + PrometheusQueries queries = new PrometheusQueries(jobService, metricoCommonMethods); + + Field jobServiceField = PrometheusQueries.class.getDeclaredField("jobService"); + jobServiceField.setAccessible(true); + assertSame(jobService, jobServiceField.get(queries)); + + Field metricoCommonMethodsField = PrometheusQueries.class.getDeclaredField("metricoCommonMethods"); + metricoCommonMethodsField.setAccessible(true); + assertSame(metricoCommonMethods, metricoCommonMethodsField.get(queries)); + } + + @Test + void testStartPeriodicQuery_SetsDefaultsAndSchedulesJob() { + Job job = new Job(); + job.setExecutionInterval(null); + + MeasurementCollectionJob mcj = new MeasurementCollectionJob(); + when(jobService.startJob(any(Runnable.class), any(Job.class))).thenAnswer(invocation -> { + Job j = invocation.getArgument(1); + j.setState(ExecutionStateType.INPROGRESS); + return j; + }); + + Job result = prometheusQueries.startPeriodicQuery("http://localhost:9090", "query=up", job, mcj); + + assertNotNull(result.getExecutionInterval()); + assertEquals(ExecutionStateType.INPROGRESS, result.getState()); + } + + @Test + void testStartPeriodicQuery_FailedJobIsStopped() { + Job job = new Job(); + MeasurementCollectionJob mcj = new MeasurementCollectionJob(); + + when(jobService.startJob(any(Runnable.class), any(Job.class))).thenAnswer(invocation -> { + Job j = invocation.getArgument(1); + j.setState(ExecutionStateType.FAILED); + return j; + }); + + Job result = prometheusQueries.startPeriodicQuery("http://localhost:9090", "query=up", job, mcj); + + assertEquals(ExecutionStateType.FAILED, result.getState()); + verify(jobService).stopJob(any(Job.class)); + } + + @Test + void testSendQueryToPrometheus_HandlesWebClientError() { + // This test checks that even if WebClient fails, a response string is returned and updateService is called. + MeasurementCollectionJob mcj = new MeasurementCollectionJob(); + mcj.setConsumingApplicationId("service-uuid"); + mcj.setOutputFormat("output"); + + Job job = new Job(); + String response = prometheusQueries.sendQueryToPrometheus("http://invalid-url", "query=up", mcj, job); + + assertTrue(response.contains("status")); + verify(metricoCommonMethods).updateService(eq("service-uuid"), any(), eq(true)); + } + + @Test + void testSendQueryToPrometheus_WhenWebClientThrowsException_LogsErrorAndReturnsStatus() { + PrometheusQueries pq = new PrometheusQueries(jobService, metricoCommonMethods) { + @Override + public String sendQueryToPrometheus(String prometheusUrl, String query, MeasurementCollectionJob mcj, Job job) { + // Simulate exception in WebClient block + try { + throw new RuntimeException("Simulated error"); + } catch (Exception e) { + Logger logger = LoggerFactory.getLogger(PrometheusQueriesTest.class);; + logger.error(" error on web client request"); + String response = "{\"status\":\"" + e.getLocalizedMessage() + "\""; + // Simulate updateService call as in original method + metricoCommonMethods.updateService(mcj.getConsumingApplicationId(), null, true); + return response; + } + } + }; + + MeasurementCollectionJob mcj = new MeasurementCollectionJob(); + mcj.setConsumingApplicationId("service-uuid"); + mcj.setOutputFormat("output"); + Job job = new Job(); + + String response = pq.sendQueryToPrometheus("http://localhost:9090", "query=up", mcj, job); + + assertTrue(response.contains("Simulated error")); + verify(metricoCommonMethods).updateService(eq("service-uuid"), any(), eq(true)); + } + + @Test + void testStartPeriodicQuery_SchedulesStopJobWhenEndDateTimePresent() { + Job job = new Job(); + job.setExecutionInterval(100); + job.setEndDateTime(OffsetDateTime.now().plusSeconds(61)); + MeasurementCollectionJob mcj = new MeasurementCollectionJob(); + + ScheduledExecutorService scheduler = mock(ScheduledExecutorService.class); + + try (MockedStatic jobServiceStatic = mockStatic(JobService.class)) { + jobServiceStatic.when(JobService::getScheduler).thenReturn(scheduler); + + when(jobService.startJob(any(Runnable.class), any(Job.class))).thenAnswer(invocation -> { + Job j = invocation.getArgument(1); + j.setState(ExecutionStateType.INPROGRESS); + return j; + }); + + prometheusQueries.startPeriodicQuery("http://localhost:9090", "query=up", job, mcj); + + verify(scheduler).schedule(any(Runnable.class), eq(60L), eq(TimeUnit.SECONDS)); + } + } + +} \ No newline at end of file diff --git a/src/test/java/org/etsi/osl/metrico/services/JobServiceTest.java b/src/test/java/org/etsi/osl/metrico/services/JobServiceTest.java index ed1f285bb862d39c96741b340bc3df42676afa93..904a25d61f539a98bfddc009eb9b6027e7cc25d1 100644 --- a/src/test/java/org/etsi/osl/metrico/services/JobServiceTest.java +++ b/src/test/java/org/etsi/osl/metrico/services/JobServiceTest.java @@ -1,106 +1,136 @@ package org.etsi.osl.metrico.services; +import org.etsi.osl.metrico.MetricoCommonMethods; import org.etsi.osl.metrico.model.Job; -import org.etsi.osl.metrico.reposervices.JobRepoService; import org.etsi.osl.tmf.pm628.model.ExecutionStateType; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.slf4j.Logger; import java.time.OffsetDateTime; import java.util.UUID; -import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeUnit; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.mockito.ArgumentMatchers.any; +import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; class JobServiceTest { - @Mock - private JobRepoService jobRepoService; - - @Mock - private ScheduledExecutorService scheduler; - - @Mock - private Logger logger; - + private MetricoCommonMethods metricoCommonMethods; private JobService jobService; @BeforeEach void setUp() { - MockitoAnnotations.openMocks(this); - jobService = new JobService(jobRepoService); + metricoCommonMethods = mock(MetricoCommonMethods.class); + jobService = new JobService(metricoCommonMethods); } @Test - void testStartJob_Success() { - // Initialize the job with specific parameters - OffsetDateTime startDateTime = OffsetDateTime.now().plusSeconds(5); - OffsetDateTime endDateTime = startDateTime.plusMinutes(10); - Integer executionInterval = 5; - Runnable task = () -> {}; - Job expectedJob = new Job(startDateTime, endDateTime, executionInterval); - // Assert the initial state is PENDING - assertEquals(expectedJob.getState(), ExecutionStateType.PENDING); - - // Set the UUID and state of the expected job after it has been saved to the db - - expectedJob.setState(ExecutionStateType.INPROGRESS); - - // Mock jobRepoService.createAndSaveJob() to return the expected Job - when(jobRepoService.createAndSaveJob(expectedJob)).thenReturn(expectedJob); - -// // Mock scheduler.scheduleAtFixedRate() to not throw an exception -// ScheduledFuture mockFuture = mock(ScheduledFuture.class); -// when(scheduler.scheduleAtFixedRate(any(Runnable.class), eq(5L), eq(5L), eq(TimeUnit.SECONDS))) -// .thenReturn(mockFuture); - -// // Call jobService.startJob() with valid parameters -// Job resultJob = jobService.startJob(task, startDateTime, endDateTime, executionInterval); -// -// // Verify job state is INPROGRESS, and job is added to the jobs map -// assertEquals(ExecutionStateType.INPROGRESS, resultJob.getState()); -// assertNotNull(JobService.getJobs().get(resultJob.getUuid())); -// assertEquals(expectedJob, JobService.getJobs().get(resultJob.getUuid())); + void startJob_withValidDates_shouldStartJob() { + Job job = new Job(); + job.setStartDateTime(OffsetDateTime.now().plusSeconds(1)); + job.setEndDateTime(OffsetDateTime.now().plusHours(1)); + job.setExecutionInterval(10); + job.setMeasurementCollectionJobRef(UUID.fromString("123e4567-e89b-12d3-a456-426614174002")); + + Runnable task = mock(Runnable.class); + + Job result = jobService.startJob(task, job); + + assertEquals(ExecutionStateType.INPROGRESS, result.getState()); + verify(metricoCommonMethods).updateMeasurementCollectionJobById(eq("123e4567-e89b-12d3-a456-426614174002"), any()); + assertTrue(jobService.getRunningJobs().containsKey("123e4567-e89b-12d3-a456-426614174002")); } + @Test - void testStartJob_NullPointerException() { - // Mock jobRepoService.createAndSaveJob() to throw NullPointerException - // Call jobService.startJob() with valid parameters - // Verify job state is FAILED + void startJob_withEndDateBeforeNow_shouldFailJob() { + Job job = new Job(); + job.setStartDateTime(OffsetDateTime.now().minusHours(2)); + job.setEndDateTime(OffsetDateTime.now().minusHours(1)); + job.setExecutionInterval(10); + job.setMeasurementCollectionJobRef(UUID.fromString("123e4567-e89b-12d3-a456-426614174002")); + + Runnable task = mock(Runnable.class); + + Job result = jobService.startJob(task, job); + + assertEquals(ExecutionStateType.FAILED, result.getState()); + verify(metricoCommonMethods).updateMeasurementCollectionJobById(eq("123e4567-e89b-12d3-a456-426614174002"), any()); + assertFalse(jobService.getRunningJobs().containsKey("123e4567-e89b-12d3-a456-426614174002")); } @Test - void testStartJob_RejectedExecutionException() { - // Mock scheduler.scheduleAtFixedRate() to throw RejectedExecutionException - // Call jobService.startJob() with valid parameters - // Verify job state is FAILED + void stopJob_shouldCancelFutureAndSetCancelled() { + Job job = new Job(); + job.setMeasurementCollectionJobRef(UUID.fromString("123e4567-e89b-12d3-a456-426614174002")); + job.setState(ExecutionStateType.INPROGRESS); + + ScheduledFuture future = mock(ScheduledFuture.class); + when(future.cancel(true)).thenReturn(true); + job.setFuture(future); + + jobService.getRunningJobs().put("123e4567-e89b-12d3-a456-426614174002", job); + + jobService.stopJob(job); + + assertEquals(ExecutionStateType.CANCELLED, job.getState()); + assertFalse(jobService.getRunningJobs().containsKey("123e4567-e89b-12d3-a456-426614174002")); + verify(metricoCommonMethods).updateMeasurementCollectionJobById(eq("123e4567-e89b-12d3-a456-426614174002"), any()); } @Test - void testStopJob_InProgress() { - // Add a job to the jobs map with state INPROGRESS - // Call JobService.stopJob() with the job's UUID - // Verify job state is CANCELLED + void stopJob_alreadyCancelled_shouldJustRemove() { + Job job = new Job(); + job.setMeasurementCollectionJobRef(UUID.fromString("123e4567-e89b-12d3-a456-426614174002")); + job.setState(ExecutionStateType.CANCELLED); + + jobService.getRunningJobs().put("123e4567-e89b-12d3-a456-426614174002", job); + + jobService.stopJob(job); + + assertFalse(jobService.getRunningJobs().containsKey("123e4567-e89b-12d3-a456-426614174002")); } @Test - void testStopJob_AlreadyCompleted() { - // Add a job to the jobs map with state COMPLETED - // Call JobService.stopJob() with the job's UUID - // Verify job state remains COMPLETED + void stopJob_byUuid_shouldCallStopJob() { + Job job = new Job(); + job.setMeasurementCollectionJobRef(UUID.fromString("123e4567-e89b-12d3-a456-426614174002")); + job.setState(ExecutionStateType.INPROGRESS); + + ScheduledFuture future = mock(ScheduledFuture.class); + when(future.cancel(true)).thenReturn(true); + job.setFuture(future); + + jobService.getRunningJobs().put("123e4567-e89b-12d3-a456-426614174002", job); + + jobService.stopJob("123e4567-e89b-12d3-a456-426614174002"); + + assertEquals(ExecutionStateType.CANCELLED, job.getState()); + assertFalse(jobService.getRunningJobs().containsKey("123e4567-e89b-12d3-a456-426614174002")); } @Test - void testStopJob_DoesNotExist() { - // Call JobService.stopJob() with a non-existent job UUID - // Verify appropriate warning is logged + void stopAllJobs_shouldStopAndClearAll() { + Job job1 = new Job(); + job1.setMeasurementCollectionJobRef(UUID.fromString("123e4567-e89b-12d3-a456-426614174002")); + job1.setState(ExecutionStateType.INPROGRESS); + ScheduledFuture future1 = mock(ScheduledFuture.class); + when(future1.cancel(true)).thenReturn(true); + job1.setFuture(future1); + + Job job2 = new Job(); + job2.setMeasurementCollectionJobRef(UUID.fromString("123e4567-e89b-12d3-a456-426614174007")); + job2.setState(ExecutionStateType.INPROGRESS); + ScheduledFuture future2 = mock(ScheduledFuture.class); + when(future2.cancel(true)).thenReturn(true); + job2.setFuture(future2); + + jobService.getRunningJobs().put("123e4567-e89b-12d3-a456-426614174002", job1); + jobService.getRunningJobs().put("123e4567-e89b-12d3-a456-426614174007", job2); + + jobService.stopAllJobs(); + + assertTrue(jobService.getRunningJobs().isEmpty()); + assertEquals(ExecutionStateType.CANCELLED, job1.getState()); + assertEquals(ExecutionStateType.CANCELLED, job2.getState()); } } \ No newline at end of file diff --git a/src/test/java/org/etsi/osl/metrico/services/MetricoServiceRouteBuilderTest.java b/src/test/java/org/etsi/osl/metrico/services/MetricoServiceRouteBuilderTest.java new file mode 100644 index 0000000000000000000000000000000000000000..b72b6e1ff042add68bba0d4784767e083e6ec0a4 --- /dev/null +++ b/src/test/java/org/etsi/osl/metrico/services/MetricoServiceRouteBuilderTest.java @@ -0,0 +1,45 @@ +package org.etsi.osl.metrico.services; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.camel.ProducerTemplate; +import org.apache.camel.test.spring.junit5.CamelSpringBootTest; +import org.etsi.osl.metrico.MetricoCommonMethods; +import org.etsi.osl.tmf.pm628.model.MeasurementCollectionJobCreateEvent; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.TestPropertySource; + +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.verify; + +@CamelSpringBootTest +@SpringBootTest +@TestPropertySource(properties = { + "EVENT_MEASUREMENT_COLLECTION_JOB_CREATE=direct:eventMeasurementCollectionJobCreate" +}) +class MetricoServiceRouteBuilderTest { + + @Autowired + private ProducerTemplate producerTemplate; + + @MockBean + private MetricoService metricoService; + + @MockBean + private MetricoCommonMethods metricoCommonMethods; + + @Test + void testRouteCallsMetricoService() throws Exception { + ObjectMapper objectMapper = new ObjectMapper(); + MeasurementCollectionJobCreateEvent event = new MeasurementCollectionJobCreateEvent(); + String eventJson = objectMapper.writeValueAsString(event); + + producerTemplate.sendBody("direct:eventMeasurementCollectionJobCreate", eventJson); + + ArgumentCaptor captor = ArgumentCaptor.forClass(MeasurementCollectionJobCreateEvent.class); + verify(metricoService, timeout(1000)).startPeriodicQueryToPrometheusEvent(captor.capture()); + } +} \ No newline at end of file diff --git a/src/test/java/org/etsi/osl/metrico/services/MetricoServiceTest.java b/src/test/java/org/etsi/osl/metrico/services/MetricoServiceTest.java index 23940b6c1256d01c0580dd8c6ec8ad2a35fb4e11..b74229859f2c7d3a748b6fc78b01bd895c8bef91 100644 --- a/src/test/java/org/etsi/osl/metrico/services/MetricoServiceTest.java +++ b/src/test/java/org/etsi/osl/metrico/services/MetricoServiceTest.java @@ -1,60 +1,283 @@ package org.etsi.osl.metrico.services; -import org.etsi.osl.tmf.pm628.model.DataAccessEndpoint; -import org.etsi.osl.tmf.pm628.model.Granularity; -import org.etsi.osl.tmf.pm628.model.MeasurementCollectionJob; +import org.etsi.osl.metrico.MetricoCommonMethods; +import org.etsi.osl.metrico.model.Job; +import org.etsi.osl.metrico.prometheus.PrometheusQueries; +import org.etsi.osl.tmf.pm628.model.*; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.junit.jupiter.SpringExtension; - -import java.util.*; import java.net.URI; -import java.net.URISyntaxException; +import java.time.OffsetDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; -@SpringBootTest -@ExtendWith(SpringExtension.class) -public class MetricoServiceTest { +class MetricoServiceTest { - @Autowired + private MetricoCommonMethods metricoCommonMethods; + private PrometheusQueries prometheusQueries; + private JobService jobService; private MetricoService metricoService; - private MeasurementCollectionJob mcj; + private MeasurementCollectionJob validMCJ() { + MeasurementCollectionJob mcj = new MeasurementCollectionJob(); + mcj.setUuid(UUID.randomUUID().toString()); + + DataAccessEndpoint dae = new DataAccessEndpoint(); + dae.setUuid(UUID.randomUUID().toString()); + dae.setApiType("Prometheus"); // must be supported + dae.setUri(URI.create("http://localhost:9090/api/v1/query?query=up")); + mcj.setDataAccessEndpoint(List.of(dae)); + + ScheduleDefinition schedule = new ScheduleDefinition(); + schedule.setScheduleDefinitionStartTime(OffsetDateTime.now().plusSeconds(1)); + schedule.setScheduleDefinitionEndTime(OffsetDateTime.now().plusHours(1)); + mcj.setScheduleDefinition(List.of(schedule)); + mcj.setGranularity(Granularity.G_30SEC); + + return mcj; + } @BeforeEach - public void setUp() throws URISyntaxException { - mcj = new MeasurementCollectionJob(); - mcj.setUuid("123e4567-e89b-12d3-a456-426614174000"); + void setUp() { + metricoCommonMethods = mock(MetricoCommonMethods.class); + prometheusQueries = mock(PrometheusQueries.class); + jobService = mock(JobService.class); + metricoService = new MetricoService(prometheusQueries, metricoCommonMethods, jobService); + } - mcj.granularity(Granularity.G_10SEC); + @Test + void testOnShutdownStopsAllJobs() { + metricoService.onShutdown(); + verify(jobService).stopAllJobs(); + } - DataAccessEndpoint dae = new DataAccessEndpoint(); - dae.setApiType("PROMETHEUS"); - dae.setUri(new URI("http://")); - dae.setUuid("123e4567-e89b-12d3-a456-426614174011"); - List daeList = new ArrayList<>(); - daeList.add(dae); - mcj.setDataAccessEndpoint(daeList); - - //job.setDataAccessEndPointUri(new URI("http://")); - - } - -// @Test -// public void testQueryToPrometheus() { -// String[] result = metricoService.queryToPrometheus(mcj); -// System.out.println(Arrays.toString(result)); -// -// //assertEquals("OK", result); -// } -// -// @Test -// public void testStartPeriodicQueryToPrometheus() throws InterruptedException { -// metricoService.startPeriodicQueryToPrometheus(mcj); -// Thread.sleep(60000); -// } + @Test + void testRestartPendingOrInProgressJobs_withJobs() { + ArrayList jobs = new ArrayList<>(); + MeasurementCollectionJob mcj1 = validMCJ(); + mcj1.setExecutionState(ExecutionStateType.INPROGRESS); + jobs.add(mcj1); + + when(metricoCommonMethods.listPendingOrInProgressMeasurementCollectionJobs()) + .thenReturn(jobs); + when(metricoCommonMethods.retrieveMeasurementCollectionJob(mcj1.getUuid())) + .thenReturn(mcj1); + when(prometheusQueries.startPeriodicQuery(anyString(), anyString(), any(Job.class), any(MeasurementCollectionJob.class))) + .thenAnswer(invocation -> { + Job job = invocation.getArgument(2); + job.setState(ExecutionStateType.INPROGRESS); + return job; + }); + + metricoService.restartPendingOrInProgressJobs(); + + verify(jobService).stopAllJobs(); + verify(metricoCommonMethods).retrieveMeasurementCollectionJob(mcj1.getUuid()); + } + + @Test + void testRestartPendingOrInProgressJobs_withNullList() { + when(metricoCommonMethods.listPendingOrInProgressMeasurementCollectionJobs()) + .thenReturn(null); + + metricoService.restartPendingOrInProgressJobs(); + + verify(jobService).stopAllJobs(); + } + + @Test + void testStartPeriodicQueryToPrometheus_callsPrometheusQueriesAndUpdatesJob() { + MeasurementCollectionJob mcj = validMCJ(); + + Job job = new Job(); + job.setDataAccessEndPointUri(mcj.getDataAccessEndpoint().get(0).getUri()); + job.setMeasurementCollectionJobRef(UUID.fromString(mcj.getUuid())); + job.setState(org.etsi.osl.tmf.pm628.model.ExecutionStateType.INPROGRESS); + + when(prometheusQueries.startPeriodicQuery(anyString(), anyString(), any(Job.class), eq(mcj))) + .thenReturn(job); + when(metricoCommonMethods.updateMeasurementCollectionJobById(eq(mcj.getUuid()), any())) + .thenReturn(mcj); + + metricoService.startPeriodicQueryToPrometheus(mcj); + + verify(prometheusQueries).startPeriodicQuery(anyString(), anyString(), any(Job.class), eq(mcj)); + verify(metricoCommonMethods).updateMeasurementCollectionJobById(eq(mcj.getUuid()), any()); + verify(metricoCommonMethods).updateRelatedResource(mcj); + } + + @Test + void testStartPeriodicQueryToPrometheusRef_delegatesToStartPeriodicQueryToPrometheus() { + MeasurementCollectionJobRef mcjRef = new MeasurementCollectionJobRef(); + mcjRef.setId("123e4567-e89b-12d3-a456-426614174002"); + MeasurementCollectionJob mcj = validMCJ(); + mcj.setUuid("123e4567-e89b-12d3-a456-426614174002"); + + when(prometheusQueries.startPeriodicQuery(anyString(), anyString(), any(Job.class), any(MeasurementCollectionJob.class))) + .thenAnswer(invocation -> { + Job job = invocation.getArgument(2); + job.setState(ExecutionStateType.INPROGRESS); + return job; + }); + when(metricoCommonMethods.retrieveMeasurementCollectionJob(mcjRef)).thenReturn(mcj); + + metricoService.startPeriodicQueryToPrometheusRef(mcjRef); + + verify(metricoCommonMethods).retrieveMeasurementCollectionJob(mcjRef); + } + + @Test + void testStartPeriodicQueryToPrometheusEvent_withValidJob() { + MeasurementCollectionJobCreateEvent event = new MeasurementCollectionJobCreateEvent(); + MeasurementCollectionJobCreateEventPayload payload = new MeasurementCollectionJobCreateEventPayload(); + MeasurementCollectionJobRef mcjRef = new MeasurementCollectionJobRef(); + mcjRef.setId("123e4567-e89b-12d3-a456-426614174002"); + MeasurementCollectionJob mcj = validMCJ(); + mcj.setUuid("123e4567-e89b-12d3-a456-426614174002"); + payload.setMeasurementCollectionJob(mcjRef); + event.setEvent(payload); + + when(prometheusQueries.startPeriodicQuery(anyString(), anyString(), any(Job.class), any(MeasurementCollectionJob.class))) + .thenAnswer(invocation -> { + Job job = invocation.getArgument(2); + job.setState(ExecutionStateType.INPROGRESS); + return job; + }); + when(metricoCommonMethods.retrieveMeasurementCollectionJob("123e4567-e89b-12d3-a456-426614174002")).thenReturn(mcj); + + metricoService.startPeriodicQueryToPrometheusEvent(event); + + verify(metricoCommonMethods).retrieveMeasurementCollectionJob("123e4567-e89b-12d3-a456-426614174002"); + } + + @Test + void testStartPeriodicQueryToPrometheusEvent_withNullJob() { + MeasurementCollectionJobCreateEvent event = new MeasurementCollectionJobCreateEvent(); + MeasurementCollectionJobCreateEventPayload payload = new MeasurementCollectionJobCreateEventPayload(); + MeasurementCollectionJobRef mcjRef = new MeasurementCollectionJobRef(); + mcjRef.setId("123e4567-e89b-12d3-a456-426614174002"); + payload.setMeasurementCollectionJob(mcjRef); + event.setEvent(payload); + + when(metricoCommonMethods.retrieveMeasurementCollectionJob("123e4567-e89b-12d3-a456-426614174002")).thenReturn(null); + + metricoService.startPeriodicQueryToPrometheusEvent(event); + + verify(metricoCommonMethods).retrieveMeasurementCollectionJob("123e4567-e89b-12d3-a456-426614174002"); + } + + + @Test + void testRestartPendingOrInProgressJobs_skipsJobWithNoDataAccessEndpoint() { + MeasurementCollectionJob mcj = validMCJ(); + mcj.setDataAccessEndpoint(null); + + ArrayList mcjList = new ArrayList<>(); + mcjList.add(mcj); + + when(metricoCommonMethods.listPendingOrInProgressMeasurementCollectionJobs()) + .thenReturn(mcjList); + when(metricoCommonMethods.retrieveMeasurementCollectionJob(mcj.getUuid())) + .thenReturn(mcj); + + metricoService.restartPendingOrInProgressJobs(); + + verify(metricoCommonMethods).updateMeasurementCollectionJobById(eq(mcj.getUuid()), any(MeasurementCollectionJobMVO.class)); + verify(jobService).stopAllJobs(); + } + + @Test + void testRestartPendingOrInProgressJobs_skipsJobWithMultipleDataAccessEndpoints() { + MeasurementCollectionJob mcj = validMCJ(); + DataAccessEndpoint dae2 = new DataAccessEndpoint(); + dae2.setUuid(UUID.randomUUID().toString()); + dae2.setApiType("Prometheus"); + dae2.setUri(URI.create("http://localhost:9091/api/v1/query?query=down")); + List endpoints = new ArrayList<>(mcj.getDataAccessEndpoint()); + endpoints.add(dae2); + mcj.setDataAccessEndpoint(endpoints); + + ArrayList mcjList = new ArrayList<>(); + mcjList.add(mcj); + + when(metricoCommonMethods.listPendingOrInProgressMeasurementCollectionJobs()) + .thenReturn(mcjList); + when(metricoCommonMethods.retrieveMeasurementCollectionJob(mcj.getUuid())) + .thenReturn(mcj); + + metricoService.restartPendingOrInProgressJobs(); + + verify(metricoCommonMethods).updateMeasurementCollectionJobById(eq(mcj.getUuid()), any(MeasurementCollectionJobMVO.class)); + verify(jobService).stopAllJobs(); + } + + @Test + void testRestartPendingOrInProgressJobs_skipsJobWithMultipleScheduleDefinitions() { + MeasurementCollectionJob mcj = validMCJ(); + ScheduleDefinition schedule2 = new ScheduleDefinition(); + schedule2.setScheduleDefinitionStartTime(OffsetDateTime.now().plusSeconds(2)); + schedule2.setScheduleDefinitionEndTime(OffsetDateTime.now().plusHours(2)); + List schedules = new ArrayList<>(mcj.getScheduleDefinition()); + schedules.add(schedule2); + mcj.setScheduleDefinition(schedules); + + ArrayList mcjList = new ArrayList<>(); + mcjList.add(mcj); + + when(metricoCommonMethods.listPendingOrInProgressMeasurementCollectionJobs()) + .thenReturn(mcjList); + when(metricoCommonMethods.retrieveMeasurementCollectionJob(mcj.getUuid())) + .thenReturn(mcj); + + metricoService.restartPendingOrInProgressJobs(); + + verify(metricoCommonMethods).updateMeasurementCollectionJobById(eq(mcj.getUuid()), any(MeasurementCollectionJobMVO.class)); + verify(jobService).stopAllJobs(); + } + + @Test + void testRestartPendingOrInProgressJobs_skipsJobWithEndedScheduleDefinition() { + MeasurementCollectionJob mcj = validMCJ(); + OffsetDateTime start = OffsetDateTime.now().minusHours(2); + OffsetDateTime end = OffsetDateTime.now().minusHours(1); + mcj.getScheduleDefinition().get(0).setScheduleDefinitionStartTime(start); + mcj.getScheduleDefinition().get(0).setScheduleDefinitionEndTime(end); + + ArrayList mcjList = new ArrayList<>(); + mcjList.add(mcj); + + when(metricoCommonMethods.listPendingOrInProgressMeasurementCollectionJobs()) + .thenReturn(mcjList); + when(metricoCommonMethods.retrieveMeasurementCollectionJob(mcj.getUuid())) + .thenReturn(mcj); + + metricoService.restartPendingOrInProgressJobs(); + + verify(metricoCommonMethods).updateMeasurementCollectionJobById(eq(mcj.getUuid()), any(MeasurementCollectionJobMVO.class)); + verify(jobService).stopAllJobs(); + } + + @Test + void testRestartPendingOrInProgressJobs_jobWithNoScheduleDefinition_addsAndSkipsIfEnded() { + MeasurementCollectionJob mcj = validMCJ(); + mcj.setScheduleDefinition(new ArrayList<>()); // No schedule definitions + mcj.setCreationTime(OffsetDateTime.now().minusHours(2)); + ArrayList mcjList = new ArrayList<>(); + mcjList.add(mcj); + + when(metricoCommonMethods.listPendingOrInProgressMeasurementCollectionJobs()) + .thenReturn(mcjList); + when(metricoCommonMethods.retrieveMeasurementCollectionJob(mcj.getUuid())) + .thenReturn(mcj); + + metricoService.restartPendingOrInProgressJobs(); + + verify(metricoCommonMethods).updateMeasurementCollectionJobById(eq(mcj.getUuid()), any(MeasurementCollectionJobMVO.class)); + verify(jobService).stopAllJobs(); + } } \ No newline at end of file diff --git a/src/test/resources/application-testing.yml b/src/test/resources/application-testing.yml new file mode 100644 index 0000000000000000000000000000000000000000..eab305100e3179d2a51e5238d27a17aacc95493c --- /dev/null +++ b/src/test/resources/application-testing.yml @@ -0,0 +1,63 @@ +spring: + profiles: + active: + "testing" + config: + activate: + on-profile: "testing" + application: + name: metrico + main: + web-application-type: servlet + activemq: + brokerUrl: tcp://localhost:61616?jms.watchTopicAdvisories=false + user: artemis + password: artemis + pool: + enabled: true + max-connections: 100 + packages: + trust-all: true + security: + oauth2: + resourceserver: + jwt: + issuer-uri: http://keycloak:8080/auth/realms/openslice + jwk-set-uri: http://keycloak:8080/auth/realms/openslice/.well-known/openid-configuration +server: + port: 8030 + + +logging: + level: + org.etsi.osl.metrico: DEBUG + root: INFO + org.springframework: INFO + org.apache.camel: INFO + reactor.netty.tcp.TcpClient: DEBUG + reactor.netty.http.client.HttpClient: DEBUG + pattern: + console: "%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" + file: "%d %p %c{1.} [%t] %m%n" + +scheduling.enabled: true + +#NUMBER OF THREADS FOR THE METRICO THREAD POOL +METRICO_THREAD_POOL_SIZE: 10 + +#TMF QUEUES +PM_MEASUREMENT_COLLECTION_GET_JOB_BY_ID: "direct:PM.MEASUREMENTCOLLECTIONJOB.GET_BY_ID" +PM_MEASUREMENT_COLLECTION_JOBS_GET: "direct:PM.MEASUREMENTCOLLECTIONJOBS.GET" +PM_MEASUREMENT_COLLECTION_JOB_ADD: "direct:PM.MEASUREMENTCOLLECTIONJOB.ADD" +PM_MEASUREMENT_COLLECTION_JOB_UPDATE: "direct:PM.MEASUREMENTCOLLECTIONJOB.UPDATE" + +EVENT_MEASUREMENT_COLLECTION_JOB_CREATE: "direct:topic:EVENT.MEASUREMENTCOLLECTIONJOB.CREATE" +EVENT_MEASUREMENT_COLLECTION_JOB_EXECUTION_STATE_CHANGED: "direct:topic:EVENT.MEASUREMENTCOLLECTIONJOB.STATECHANGED" +EVENT_MEASUREMENT_COLLECTION_JOB_DELETE: "direct:topic:EVENT.MEASUREMENTCOLLECTIONJOB.DELETE" +EVENT_MEASUREMENT_COLLECTION_JOB_ATTRIBUTE_VALUE_CHANGED: "direct:topic:EVENT.MEASUREMENTCOLLECTIONJOB.ATTRCHANGED" + +CATALOG_UPDADD_RESOURCESPEC: "direct:CATALOG.UPDADD.RESOURCESPEC" +CATALOG_GET_SERVICE_BY_ID: "direct:CATALOG.GET.SERVICE" +CATALOG_GET_RESOURCE_BY_ID: "direct:CATALOG.GET.RESOURCE" +CATALOG_UPD_RESOURCE: "direct:CATALOG.UPD.RESOURCE" +CATALOG_UPD_SERVICE: "direct:CATALOG.UPD.SERVICE" diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml deleted file mode 100644 index e8714e1d756e5e9a9305c36d685bb909cfca8668..0000000000000000000000000000000000000000 --- a/src/test/resources/application.yml +++ /dev/null @@ -1,17 +0,0 @@ -spring: - datasource: - url: jdbc:h2:mem:testdb - driverClassName: org.h2.Driver - username: sa - password: password - jpa: - database-platform: org.hibernate.dialect.H2Dialect - - -#NUMBER OF THREADS FOR THE METRICO THREAD POOL -METRICO_THREAD_POOL_SIZE: 10 - -CATALOG_GET_SERVICE_BY_ID: "jms:queue:CATALOG.GET.SERVICE" -CATALOG_GET_RESOURCE_BY_ID: "jms:queue:CATALOG.GET.RESOURCE" -CATALOG_UPD_RESOURCE: "jms:queue:CATALOG.UPD.RESOURCE" -CATALOG_UPD_SERVICE: "jms:queue:CATALOG.UPD.SERVICE" \ No newline at end of file