diff options
Diffstat (limited to 'cps-ncmp-service/src/main')
11 files changed, 335 insertions, 309 deletions
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/OpenTelemetryConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/OpenTelemetryConfig.java new file mode 100644 index 0000000000..bcbacbd421 --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/OpenTelemetryConfig.java @@ -0,0 +1,111 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2024 Nordix Foundation + * ================================================================================ + * 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.api.impl.config; + +import io.micrometer.observation.ObservationPredicate; +import io.micrometer.observation.ObservationRegistry; +import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter; +import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; +import io.opentelemetry.sdk.extension.trace.jaeger.sampler.JaegerRemoteSampler; +import io.opentelemetry.sdk.trace.samplers.Sampler; +import java.time.Duration; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.actuate.autoconfigure.observation.ObservationRegistryCustomizer; +import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.server.observation.ServerRequestObservationContext; +import org.springframework.util.AntPathMatcher; +import org.springframework.util.PathMatcher; + +@Configuration +public class OpenTelemetryConfig { + + public static final int JAEGER_REMOTE_SAMPLER_POLLING_INTERVAL_IN_SECOND = 30; + + @Value("${spring.application.name:cps-application}") + private String serviceId; + + @Value("${cps.tracing.exporter.endpoint:http://onap-otel-collector:4317}") + private String tracingExporterEndpointUrl; + + @Value("${cps.tracing.sampler.jaeger_remote.endpoint:http://onap-otel-collector:14250}") + private String jaegerRemoteSamplerUrl; + + /** + * OTLP Exporter with Grpc exporter protocol. + */ + @Bean + @ConditionalOnExpression( + "${cps.tracing.enabled} && 'grpc'.equals('${cps.tracing.exporter.protocol}')") + public OtlpGrpcSpanExporter createOtlpExporterGrpc() { + return OtlpGrpcSpanExporter.builder().setEndpoint(tracingExporterEndpointUrl).build(); + } + + /** + * OTLP Exporter with HTTP exporter protocol. + */ + @Bean + @ConditionalOnExpression( + "${cps.tracing.enabled} && 'http'.equals('${cps.tracing.exporter.protocol}')") + public OtlpHttpSpanExporter createOtlpExporterHttp() { + return OtlpHttpSpanExporter.builder().setEndpoint(tracingExporterEndpointUrl).build(); + } + + /** + * Jaeger Remote Sampler. + */ + @Bean + @ConditionalOnProperty("cps.tracing.enabled") + public JaegerRemoteSampler createJaegerRemoteSampler() { + return JaegerRemoteSampler.builder() + .setEndpoint(jaegerRemoteSamplerUrl) + .setPollingInterval(Duration.ofSeconds(JAEGER_REMOTE_SAMPLER_POLLING_INTERVAL_IN_SECOND)) + .setInitialSampler(Sampler.alwaysOff()) + .setServiceName(serviceId) + .build(); + } + + /** + * Excluding /actuator/** endpoints. + */ + @Bean + @ConditionalOnProperty("cps.tracing.enabled") + ObservationRegistryCustomizer<ObservationRegistry> skipActuatorEndpointsFromObservation() { + final PathMatcher pathMatcher = new AntPathMatcher("/"); + return registry -> + registry.observationConfig().observationPredicate(observationPredicate(pathMatcher)); + } + + /** + * Excluding /actuator/** endpoints. + */ + static ObservationPredicate observationPredicate(final PathMatcher pathMatcher) { + return (name, context) -> { + if (context instanceof ServerRequestObservationContext observationContext) { + return !pathMatcher.match("/actuator/**", observationContext.getCarrier().getRequestURI()); + } else { + return true; + } + }; + } +}
\ No newline at end of file diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/kafka/KafkaConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/kafka/KafkaConfig.java index 167df5a98d..cf6f1c5b17 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/kafka/KafkaConfig.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/config/kafka/KafkaConfig.java @@ -21,10 +21,14 @@ package org.onap.cps.ncmp.api.impl.config.kafka; import io.cloudevents.CloudEvent; +import io.opentelemetry.instrumentation.kafkaclients.v2_6.TracingConsumerInterceptor; +import io.opentelemetry.instrumentation.kafkaclients.v2_6.TracingProducerInterceptor; import java.time.Duration; import java.util.Map; import lombok.RequiredArgsConstructor; +import org.apache.kafka.clients.consumer.ConsumerConfig; import org.apache.kafka.clients.producer.ProducerConfig; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.kafka.KafkaProperties; import org.springframework.boot.ssl.SslBundles; import org.springframework.context.annotation.Bean; @@ -52,6 +56,9 @@ public class KafkaConfig<T> { private final KafkaProperties kafkaProperties; + @Value("${cps.tracing.enabled:false}") + private boolean tracingEnabled; + private static final SslBundles NO_SSL = null; /** @@ -64,6 +71,10 @@ public class KafkaConfig<T> { public ProducerFactory<String, T> legacyEventProducerFactory() { final Map<String, Object> producerConfigProperties = kafkaProperties.buildProducerProperties(NO_SSL); producerConfigProperties.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, JsonSerializer.class); + if (tracingEnabled) { + producerConfigProperties.put( + ProducerConfig.INTERCEPTOR_CLASSES_CONFIG, TracingProducerInterceptor.class.getName()); + } return new DefaultKafkaProducerFactory<>(producerConfigProperties); } @@ -77,6 +88,10 @@ public class KafkaConfig<T> { public ConsumerFactory<String, T> legacyEventConsumerFactory() { final Map<String, Object> consumerConfigProperties = kafkaProperties.buildConsumerProperties(NO_SSL); consumerConfigProperties.put("spring.deserializer.value.delegate.class", JsonDeserializer.class); + if (tracingEnabled) { + consumerConfigProperties.put( + ConsumerConfig.INTERCEPTOR_CLASSES_CONFIG, TracingConsumerInterceptor.class.getName()); + } return new DefaultKafkaConsumerFactory<>(consumerConfigProperties); } @@ -90,6 +105,9 @@ public class KafkaConfig<T> { public KafkaTemplate<String, T> legacyEventKafkaTemplate() { final KafkaTemplate<String, T> kafkaTemplate = new KafkaTemplate<>(legacyEventProducerFactory()); kafkaTemplate.setConsumerFactory(legacyEventConsumerFactory()); + if (tracingEnabled) { + kafkaTemplate.setObservationEnabled(true); + } return kafkaTemplate; } @@ -104,6 +122,9 @@ public class KafkaConfig<T> { new ConcurrentKafkaListenerContainerFactory<>(); containerFactory.setConsumerFactory(legacyEventConsumerFactory()); containerFactory.getContainerProperties().setAuthExceptionRetryInterval(Duration.ofSeconds(10)); + if (tracingEnabled) { + containerFactory.getContainerProperties().setObservationEnabled(true); + } return containerFactory; } @@ -116,6 +137,10 @@ public class KafkaConfig<T> { @Bean public ProducerFactory<String, CloudEvent> cloudEventProducerFactory() { final Map<String, Object> producerConfigProperties = kafkaProperties.buildProducerProperties(NO_SSL); + if (tracingEnabled) { + producerConfigProperties.put( + ProducerConfig.INTERCEPTOR_CLASSES_CONFIG, TracingProducerInterceptor.class.getName()); + } return new DefaultKafkaProducerFactory<>(producerConfigProperties); } @@ -128,6 +153,10 @@ public class KafkaConfig<T> { @Bean public ConsumerFactory<String, CloudEvent> cloudEventConsumerFactory() { final Map<String, Object> consumerConfigProperties = kafkaProperties.buildConsumerProperties(NO_SSL); + if (tracingEnabled) { + consumerConfigProperties.put( + ConsumerConfig.INTERCEPTOR_CLASSES_CONFIG, TracingConsumerInterceptor.class.getName()); + } return new DefaultKafkaConsumerFactory<>(consumerConfigProperties); } @@ -142,6 +171,9 @@ public class KafkaConfig<T> { final KafkaTemplate<String, CloudEvent> kafkaTemplate = new KafkaTemplate<>(cloudEventProducerFactory()); kafkaTemplate.setConsumerFactory(cloudEventConsumerFactory()); + if (tracingEnabled) { + kafkaTemplate.setObservationEnabled(true); + } return kafkaTemplate; } @@ -157,6 +189,9 @@ public class KafkaConfig<T> { new ConcurrentKafkaListenerContainerFactory<>(); containerFactory.setConsumerFactory(cloudEventConsumerFactory()); containerFactory.getContainerProperties().setAuthExceptionRetryInterval(Duration.ofSeconds(10)); + if (tracingEnabled) { + containerFactory.getContainerProperties().setObservationEnabled(true); + } return containerFactory; } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/consumer/CmNotificationSubscriptionNcmpInEventConsumer.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/consumer/CmNotificationSubscriptionNcmpInEventConsumer.java index 2c544b7b6a..fb3388c117 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/consumer/CmNotificationSubscriptionNcmpInEventConsumer.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/consumer/CmNotificationSubscriptionNcmpInEventConsumer.java @@ -23,11 +23,13 @@ package org.onap.cps.ncmp.api.impl.events.cmsubscription.consumer; import static org.onap.cps.ncmp.api.impl.events.mapper.CloudEventMapper.toTargetEvent; import io.cloudevents.CloudEvent; +import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.kafka.clients.consumer.ConsumerRecord; import org.onap.cps.ncmp.api.impl.events.cmsubscription.service.CmNotificationSubscriptionHandlerService; import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.client_to_ncmp.CmNotificationSubscriptionNcmpInEvent; +import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.client_to_ncmp.Predicate; import org.springframework.kafka.annotation.KafkaListener; import org.springframework.stereotype.Component; @@ -53,10 +55,16 @@ public class CmNotificationSubscriptionNcmpInEventConsumer { cmNotificationSubscriptionNcmpInEvent.getData().getSubscriptionId()); final String subscriptionId = cmNotificationSubscriptionNcmpInEvent.getData().getSubscriptionId(); + final List<Predicate> predicates = cmNotificationSubscriptionNcmpInEvent.getData().getPredicates(); if ("subscriptionCreateRequest".equals(cloudEvent.getType())) { - log.info("Subscription for source {} with subscription id {} ...", cloudEvent.getSource(), subscriptionId); - cmNotificationSubscriptionHandlerService.processSubscriptionCreateRequest( - cmNotificationSubscriptionNcmpInEvent); + log.info("Subscription create request for source {} with subscription id {} ...", + cloudEvent.getSource(), subscriptionId); + cmNotificationSubscriptionHandlerService.processSubscriptionCreateRequest(subscriptionId, predicates); + } + if ("subscriptionDeleteRequest".equals(cloudEvent.getType())) { + log.info("Subscription delete request for source {} with subscription id {} ...", + cloudEvent.getSource(), subscriptionId); + cmNotificationSubscriptionHandlerService.processSubscriptionDeleteRequest(subscriptionId, predicates); } } }
\ No newline at end of file diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/mapper/CmNotificationSubscriptionDmiInEventMapper.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/mapper/CmNotificationSubscriptionDmiInEventMapper.java index 489401f26e..7610687480 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/mapper/CmNotificationSubscriptionDmiInEventMapper.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/mapper/CmNotificationSubscriptionDmiInEventMapper.java @@ -29,8 +29,8 @@ import java.util.Set; import lombok.RequiredArgsConstructor; import org.onap.cps.ncmp.api.impl.events.cmsubscription.model.DmiCmNotificationSubscriptionPredicate; import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; +import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.ncmp_to_dmi.CmHandle; import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.ncmp_to_dmi.CmNotificationSubscriptionDmiInEvent; -import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.ncmp_to_dmi.Cmhandle; import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.ncmp_to_dmi.Data; import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.ncmp_to_dmi.Predicate; import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.ncmp_to_dmi.ScopeFilter; @@ -54,7 +54,7 @@ public class CmNotificationSubscriptionDmiInEventMapper { new CmNotificationSubscriptionDmiInEvent(); final Data cmSubscriptionData = new Data(); cmSubscriptionData.setPredicates(mapToDmiInEventPredicates(dmiCmNotificationSubscriptionPredicates)); - cmSubscriptionData.setCmhandles(mapToCmSubscriptionCmhandleWithPrivateProperties( + cmSubscriptionData.setCmHandles(mapToCmSubscriptionCmhandleWithPrivateProperties( extractUniqueCmHandleIds(dmiCmNotificationSubscriptionPredicates))); cmNotificationSubscriptionDmiInEvent.setData(cmSubscriptionData); return cmNotificationSubscriptionDmiInEvent; @@ -81,12 +81,12 @@ public class CmNotificationSubscriptionDmiInEventMapper { } - private List<Cmhandle> mapToCmSubscriptionCmhandleWithPrivateProperties(final Set<String> cmHandleIds) { + private List<CmHandle> mapToCmSubscriptionCmhandleWithPrivateProperties(final Set<String> cmHandleIds) { - final List<Cmhandle> cmSubscriptionCmHandles = new ArrayList<>(); + final List<CmHandle> cmSubscriptionCmHandles = new ArrayList<>(); inventoryPersistence.getYangModelCmHandles(cmHandleIds).forEach(yangModelCmHandle -> { - final Cmhandle cmhandle = new Cmhandle(); + final CmHandle cmhandle = new CmHandle(); final Map<String, String> cmhandleDmiProperties = new LinkedHashMap<>(); yangModelCmHandle.getDmiProperties() .forEach(dmiProperty -> cmhandleDmiProperties.put(dmiProperty.getName(), dmiProperty.getValue())); diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionHandlerService.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionHandlerService.java index 536693ee4e..1c52ffa798 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionHandlerService.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionHandlerService.java @@ -20,16 +20,25 @@ package org.onap.cps.ncmp.api.impl.events.cmsubscription.service; -import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.client_to_ncmp.CmNotificationSubscriptionNcmpInEvent; +import java.util.List; +import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.client_to_ncmp.Predicate; public interface CmNotificationSubscriptionHandlerService { /** - * Process cm notification subscription request. + * Process cm notification subscription create request. * - * @param cmNotificationSubscriptionNcmpInEvent CM Notification Subscription event + * @param subscriptionId subscription id + * @param predicates subscription predicates */ - void processSubscriptionCreateRequest( - final CmNotificationSubscriptionNcmpInEvent cmNotificationSubscriptionNcmpInEvent); + void processSubscriptionCreateRequest(final String subscriptionId, final List<Predicate> predicates); -} + /** + * Process cm notification subscription delete request. + * + * @param subscriptionId subscription id + * @param predicates subscription predicates + */ + void processSubscriptionDeleteRequest(final String subscriptionId, final List<Predicate> predicates); + +}
\ No newline at end of file diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionHandlerServiceImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionHandlerServiceImpl.java index 128c6751ce..08e3c95529 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionHandlerServiceImpl.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/events/cmsubscription/service/CmNotificationSubscriptionHandlerServiceImpl.java @@ -33,7 +33,6 @@ import org.onap.cps.ncmp.api.impl.events.cmsubscription.DmiCmNotificationSubscri import org.onap.cps.ncmp.api.impl.events.cmsubscription.model.CmNotificationSubscriptionStatus; import org.onap.cps.ncmp.api.impl.events.cmsubscription.model.DmiCmNotificationSubscriptionDetails; import org.onap.cps.ncmp.api.impl.events.cmsubscription.model.DmiCmNotificationSubscriptionPredicate; -import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.client_to_ncmp.CmNotificationSubscriptionNcmpInEvent; import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.client_to_ncmp.Predicate; import org.onap.cps.ncmp.events.cmnotificationsubscription_merge1_0_0.ncmp_to_dmi.CmNotificationSubscriptionDmiInEvent; import org.onap.cps.ncmp.events.cmsubscription_merge1_0_0.ncmp_to_client.CmNotificationSubscriptionNcmpOutEvent; @@ -50,27 +49,32 @@ public class CmNotificationSubscriptionHandlerServiceImpl implements CmNotificat private final DmiCmNotificationSubscriptionCacheHandler dmiCmNotificationSubscriptionCacheHandler; @Override - public void processSubscriptionCreateRequest( - final CmNotificationSubscriptionNcmpInEvent cmNotificationSubscriptionNcmpInEvent) { - final String subscriptionId = cmNotificationSubscriptionNcmpInEvent.getData().getSubscriptionId(); - final List<Predicate> predicates = cmNotificationSubscriptionNcmpInEvent.getData().getPredicates(); - + public void processSubscriptionCreateRequest(final String subscriptionId, final List<Predicate> predicates) { if (cmNotificationSubscriptionPersistenceService.isUniqueSubscriptionId(subscriptionId)) { dmiCmNotificationSubscriptionCacheHandler.add(subscriptionId, predicates); handleCmNotificationSubscriptionDelta(subscriptionId); - scheduleCmNotificationSubscriptionNcmpOutEventResponse(subscriptionId); + scheduleCmNotificationSubscriptionNcmpOutEventResponse(subscriptionId, + "subscriptionCreateResponse"); } else { rejectAndPublishCmNotificationSubscriptionCreateRequest(subscriptionId, predicates); } } - private void scheduleCmNotificationSubscriptionNcmpOutEventResponse(final String subscriptionId) { + @Override + public void processSubscriptionDeleteRequest(final String subscriptionId, final List<Predicate> predicates) { + dmiCmNotificationSubscriptionCacheHandler.add(subscriptionId, predicates); + sendSubscriptionDeleteRequestToDmi(subscriptionId); + scheduleCmNotificationSubscriptionNcmpOutEventResponse(subscriptionId, "subscriptionDeleteResponse"); + } + + private void scheduleCmNotificationSubscriptionNcmpOutEventResponse(final String subscriptionId, + final String eventType) { cmNotificationSubscriptionEventsHandler.publishCmNotificationSubscriptionNcmpOutEvent(subscriptionId, - "subscriptionCreateResponse", null, true); + eventType, null, true); } private void rejectAndPublishCmNotificationSubscriptionCreateRequest(final String subscriptionId, - final List<Predicate> predicates) { + final List<Predicate> predicates) { final Set<String> subscriptionTargetFilters = predicates.stream().flatMap(predicate -> predicate.getTargetFilter().stream()) .collect(Collectors.toSet()); @@ -99,8 +103,9 @@ public class CmNotificationSubscriptionHandlerServiceImpl implements CmNotificat } private void publishCmNotificationSubscriptionDmiInEventPerDmi(final String subscriptionId, - final String dmiPluginName, - final List<DmiCmNotificationSubscriptionPredicate> dmiCmNotificationSubscriptionPredicates) { + final String dmiPluginName, + final List<DmiCmNotificationSubscriptionPredicate> + dmiCmNotificationSubscriptionPredicates) { final CmNotificationSubscriptionDmiInEvent cmNotificationSubscriptionDmiInEvent = cmNotificationSubscriptionMappersHandler.toCmNotificationSubscriptionDmiInEvent( dmiCmNotificationSubscriptionPredicates); @@ -109,9 +114,21 @@ public class CmNotificationSubscriptionHandlerServiceImpl implements CmNotificat } private void acceptAndPublishCmNotificationSubscriptionNcmpOutEventPerDmi(final String subscriptionId, - final String dmiPluginName) { + final String dmiPluginName) { dmiCmNotificationSubscriptionCacheHandler.updateDmiCmNotificationSubscriptionStatusPerDmi(subscriptionId, dmiPluginName, CmNotificationSubscriptionStatus.ACCEPTED); dmiCmNotificationSubscriptionCacheHandler.persistIntoDatabasePerDmi(subscriptionId, dmiPluginName); } -} + + private void sendSubscriptionDeleteRequestToDmi(final String subscriptionId) { + final Map<String, DmiCmNotificationSubscriptionDetails> dmiCmNotificationSubscriptionDetailsMap = + dmiCmNotificationSubscriptionCacheHandler.get(subscriptionId); + dmiCmNotificationSubscriptionDetailsMap.forEach((dmiPluginName, dmiCmNotificationSubscriptionDetails) -> { + final CmNotificationSubscriptionDmiInEvent cmNotificationSubscriptionDmiInEvent = + cmNotificationSubscriptionMappersHandler.toCmNotificationSubscriptionDmiInEvent( + dmiCmNotificationSubscriptionDetails.getDmiCmNotificationSubscriptionPredicates()); + cmNotificationSubscriptionEventsHandler.publishCmNotificationSubscriptionDmiInEvent(subscriptionId, + dmiPluginName, "subscriptionDeleteRequest", cmNotificationSubscriptionDmiInEvent); + }); + } +}
\ No newline at end of file diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java index 49894dedbd..6370879094 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiDataOperations.java @@ -30,6 +30,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.onap.cps.ncmp.api.NcmpResponseStatus; import org.onap.cps.ncmp.api.impl.client.DmiRestClient; @@ -45,7 +46,7 @@ import org.onap.cps.ncmp.api.models.DataOperationRequest; import org.onap.cps.spi.exceptions.CpsException; import org.onap.cps.utils.JsonObjectMapper; import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.util.UriComponentsBuilder; @@ -53,17 +54,15 @@ import org.springframework.web.util.UriComponentsBuilder; /** * Operations class for DMI data. */ -@Component +@RequiredArgsConstructor +@Service @Slf4j -public class DmiDataOperations extends DmiOperations { +public class DmiDataOperations { - public DmiDataOperations(final InventoryPersistence inventoryPersistence, - final JsonObjectMapper jsonObjectMapper, - final DmiProperties dmiProperties, - final DmiRestClient dmiRestClient, - final DmiServiceUrlBuilder dmiServiceUrlBuilder) { - super(inventoryPersistence, jsonObjectMapper, dmiProperties, dmiRestClient, dmiServiceUrlBuilder); - } + private final InventoryPersistence inventoryPersistence; + private final JsonObjectMapper jsonObjectMapper; + private final DmiProperties dmiProperties; + private final DmiRestClient dmiRestClient; /** * This method fetches the resource data from operational data store for given cm handle @@ -89,39 +88,33 @@ public class DmiDataOperations extends DmiOperations { validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState); final String jsonRequestBody = getDmiRequestBody(READ, requestId, null, null, yangModelCmHandle); - final MultiValueMap<String, String> uriQueryParamsMap = getUriQueryParamsMap( - cmResourceAddress.resourceIdentifier(), optionsParamInQuery, topicParamInQuery); - final Map<String, Object> uriVariableParamsMap = getUriVariableParamsMap(cmResourceAddress.datastoreName(), - yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA), cmResourceAddress.cmHandleId()); - final String dmiResourceDataUrl = getDmiRequestUrl(uriQueryParamsMap, uriVariableParamsMap); - - return dmiRestClient.postOperationWithJsonData(dmiResourceDataUrl, jsonRequestBody, READ, authorization); + final String dmiUrl = getDmiResourceDataUrl(cmResourceAddress.datastoreName(), + yangModelCmHandle, + cmResourceAddress.resourceIdentifier(), + optionsParamInQuery, + topicParamInQuery); + return dmiRestClient.postOperationWithJsonData(dmiUrl, jsonRequestBody, READ, authorization); } /** * This method fetches all the resource data from operational data store for given cm handle * identifier using dmi client. * - * @param dataStoreName data store name + * @param datastoreName data store name * @param cmHandleId network resource identifier * @param requestId requestId for async responses * @return {@code ResponseEntity} response entity */ - public ResponseEntity<Object> getResourceDataFromDmi(final String dataStoreName, + public ResponseEntity<Object> getResourceDataFromDmi(final String datastoreName, final String cmHandleId, final String requestId) { final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmHandleId); - final String jsonRequestBody = getDmiRequestBody(READ, requestId, null, null, - yangModelCmHandle); - - final MultiValueMap<String, String> uriQueryParamsMap = getUriQueryParamsMap("/", null, null); - final Map<String, Object> uriVariableParamsMap = getUriVariableParamsMap(dataStoreName, - yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA), cmHandleId); - final String dmiResourceDataUrl = getDmiRequestUrl(uriQueryParamsMap, uriVariableParamsMap); - final CmHandleState cmHandleState = yangModelCmHandle.getCompositeState().getCmHandleState(); validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState); - return dmiRestClient.postOperationWithJsonData(dmiResourceDataUrl, jsonRequestBody, READ, null); + + final String jsonRequestBody = getDmiRequestBody(READ, requestId, null, null, yangModelCmHandle); + final String dmiUrl = getDmiResourceDataUrl(datastoreName, yangModelCmHandle, "/", null, null); + return dmiRestClient.postOperationWithJsonData(dmiUrl, jsonRequestBody, READ, null); } /** @@ -142,13 +135,13 @@ public class DmiDataOperations extends DmiOperations { = getDistinctCmHandleIdsFromDataOperationRequest(dataOperationRequest); final Collection<YangModelCmHandle> yangModelCmHandles - = inventoryPersistence.getYangModelCmHandles(cmHandlesIds); + = inventoryPersistence.getYangModelCmHandles(cmHandlesIds); final Map<String, List<DmiDataOperation>> operationsOutPerDmiServiceName = ResourceDataOperationRequestUtils.processPerDefinitionInDataOperationsRequest(topicParamInQuery, requestId, dataOperationRequest, yangModelCmHandles); - buildDataOperationRequestUrlAndSendToDmiService(topicParamInQuery, requestId, operationsOutPerDmiServiceName, + buildDataOperationRequestUrlAndSendToDmiService(requestId, topicParamInQuery, operationsOutPerDmiServiceName, authorization); } @@ -171,16 +164,13 @@ public class DmiDataOperations extends DmiOperations { final String dataType, final String authorization) { final YangModelCmHandle yangModelCmHandle = getYangModelCmHandle(cmHandleId); - final String jsonRequestBody = getDmiRequestBody(operationType, null, requestData, dataType, - yangModelCmHandle); - - final MultiValueMap<String, String> uriQueryParamsMap = getUriQueryParamsMap(resourceId, null, null); - final Map<String, Object> uriVariableParamsMap = getUriVariableParamsMap(PASSTHROUGH_RUNNING.getDatastoreName(), - yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA), cmHandleId); - final String dmiUrl = getDmiRequestUrl(uriQueryParamsMap, uriVariableParamsMap); - final CmHandleState cmHandleState = yangModelCmHandle.getCompositeState().getCmHandleState(); validateIfCmHandleStateReady(yangModelCmHandle, cmHandleState); + + final String jsonRequestBody = getDmiRequestBody(operationType, null, requestData, dataType, + yangModelCmHandle); + final String dmiUrl = getDmiResourceDataUrl(PASSTHROUGH_RUNNING.getDatastoreName(), + yangModelCmHandle, resourceId, null, null); return dmiRestClient.postOperationWithJsonData(dmiUrl, jsonRequestBody, operationType, authorization); } @@ -204,31 +194,22 @@ public class DmiDataOperations extends DmiOperations { return jsonObjectMapper.asJsonString(dmiRequestBody); } - private String getDmiRequestUrl(final MultiValueMap<String, String> uriQueryParamsMap, - final Map<String, Object> uriVariableParamsMap) { - return dmiServiceUrlBuilder.getDmiDatastoreUrl(uriQueryParamsMap, uriVariableParamsMap); - } - - private MultiValueMap<String, String> getUriQueryParamsMap(final String resourceId, - final String optionsParamInQuery, - final String topicParamInQuery) { - return dmiServiceUrlBuilder.populateQueryParams(resourceId, optionsParamInQuery, - topicParamInQuery); - } - - private Map<String, Object> getUriVariableParamsMap(final String dataStoreName, - final String dmiServiceName, - final String cmHandleId) { - return dmiServiceUrlBuilder.populateUriVariables(dataStoreName, dmiServiceName, cmHandleId); - } - - private String getDmiServiceDataOperationRequestUrl(final String dmiServiceName, - final String topicParamInQuery, - final String requestId) { - final MultiValueMap<String, String> dataOperationRequestQueryParams = dmiServiceUrlBuilder - .getDataOperationRequestQueryParams(topicParamInQuery, requestId); - return dmiServiceUrlBuilder.getDataOperationRequestUrl(dataOperationRequestQueryParams, - dmiServiceUrlBuilder.populateDataOperationRequestUriVariables(dmiServiceName)); + private String getDmiResourceDataUrl(final String datastoreName, + final YangModelCmHandle yangModelCmHandle, + final String resourceIdentifier, + final String optionsParamInQuery, + final String topicParamInQuery) { + final String dmiServiceName = yangModelCmHandle.resolveDmiServiceName(RequiredDmiService.DATA); + return DmiServiceUrlBuilder.newInstance() + .pathSegment("ch") + .variablePathSegment("cmHandleId", yangModelCmHandle.getId()) + .pathSegment("data") + .pathSegment("ds") + .variablePathSegment("datastore", datastoreName) + .queryParameter("resourceIdentifier", resourceIdentifier) + .queryParameter("options", optionsParamInQuery) + .queryParameter("topic", topicParamInQuery) + .build(dmiServiceName, dmiProperties.getDmiBasePath()); } private void validateIfCmHandleStateReady(final YangModelCmHandle yangModelCmHandle, @@ -247,32 +228,32 @@ public class DmiDataOperations extends DmiOperations { dataOperationDefinition.getCmHandleIds().stream()).collect(Collectors.toSet()); } - private void buildDataOperationRequestUrlAndSendToDmiService(final String topicParamInQuery, - final String requestId, + private void buildDataOperationRequestUrlAndSendToDmiService(final String requestId, + final String topicParamInQuery, final Map<String, List<DmiDataOperation>> groupsOutPerDmiServiceName, final String authorization) { groupsOutPerDmiServiceName.forEach((dmiServiceName, dmiDataOperationRequestBodies) -> { - final String dmiDataOperationResourceUrl = - getDmiServiceDataOperationRequestUrl(dmiServiceName, topicParamInQuery, requestId); - sendDataOperationRequestToDmiService(dmiDataOperationResourceUrl, dmiDataOperationRequestBodies, - authorization); + final String dmiUrl = DmiServiceUrlBuilder.newInstance() + .pathSegment("data") + .queryParameter("requestId", requestId) + .queryParameter("topic", topicParamInQuery) + .build(dmiServiceName, dmiProperties.getDmiBasePath()); + sendDataOperationRequestToDmiService(dmiUrl, dmiDataOperationRequestBodies, authorization); }); } - private void sendDataOperationRequestToDmiService(final String dataOperationResourceUrl, + private void sendDataOperationRequestToDmiService(final String dmiUrl, final List<DmiDataOperation> dmiDataOperationRequestBodies, final String authorization) { final DmiDataOperationRequest dmiDataOperationRequest = DmiDataOperationRequest.builder() .operations(dmiDataOperationRequestBodies).build(); - final String dmiDataOperationRequestAsJsonString = - jsonObjectMapper.asJsonString(dmiDataOperationRequest); + final String dmiDataOperationRequestAsJsonString = jsonObjectMapper.asJsonString(dmiDataOperationRequest); try { - dmiRestClient.postOperationWithJsonData(dataOperationResourceUrl, dmiDataOperationRequestAsJsonString, READ, - authorization); + dmiRestClient.postOperationWithJsonData(dmiUrl, dmiDataOperationRequestAsJsonString, READ, authorization); } catch (final DmiClientRequestException e) { - handleTaskCompletionException(e, dataOperationResourceUrl, dmiDataOperationRequestBodies); + handleTaskCompletionException(e, dmiUrl, dmiDataOperationRequestBodies); } } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java index d54dcb8deb..78d27b54b6 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiModelOperations.java @@ -33,34 +33,27 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import lombok.RequiredArgsConstructor; import org.onap.cps.ncmp.api.impl.client.DmiRestClient; import org.onap.cps.ncmp.api.impl.config.DmiProperties; -import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder; import org.onap.cps.ncmp.api.impl.yangmodels.YangModelCmHandle; import org.onap.cps.ncmp.api.models.YangResource; import org.onap.cps.spi.model.ModuleReference; import org.onap.cps.utils.JsonObjectMapper; import org.springframework.http.ResponseEntity; -import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; /** * Operations class for DMI Model. */ -@Component -public class DmiModelOperations extends DmiOperations { +@RequiredArgsConstructor +@Service +public class DmiModelOperations { - /** - * Constructor for {@code DmiOperations}. This method also manipulates url properties. - * - * @param dmiRestClient {@code DmiRestClient} - */ - public DmiModelOperations(final InventoryPersistence inventoryPersistence, - final JsonObjectMapper jsonObjectMapper, - final DmiProperties dmiProperties, - final DmiRestClient dmiRestClient, final DmiServiceUrlBuilder dmiServiceUrlBuilder) { - super(inventoryPersistence, jsonObjectMapper, dmiProperties, dmiRestClient, dmiServiceUrlBuilder); - } + private final JsonObjectMapper jsonObjectMapper; + private final DmiProperties dmiProperties; + private final DmiRestClient dmiRestClient; /** * Retrieves module references. @@ -113,9 +106,12 @@ public class DmiModelOperations extends DmiOperations { final String jsonRequestBody, final String cmHandle, final String resourceName) { - final String dmiResourceDataUrl = getDmiResourceUrl(dmiServiceName, cmHandle, resourceName); - return dmiRestClient.postOperationWithJsonData(dmiResourceDataUrl, jsonRequestBody, - OperationType.READ, null); + final String dmiUrl = DmiServiceUrlBuilder.newInstance() + .pathSegment("ch") + .variablePathSegment("cmHandleId", cmHandle) + .variablePathSegment("resourceName", resourceName) + .build(dmiServiceName, dmiProperties.getDmiBasePath()); + return dmiRestClient.postOperationWithJsonData(dmiUrl, jsonRequestBody, OperationType.READ, null); } private static String getRequestBodyToFetchYangResources(final Collection<ModuleReference> newModuleReferences, diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperations.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperations.java deleted file mode 100644 index c195ab3096..0000000000 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/DmiOperations.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * ============LICENSE_START======================================================= - * Copyright (C) 2021-2024 Nordix Foundation - * Modifications Copyright (C) 2022 Bell Canada - * ================================================================================ - * 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. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - -package org.onap.cps.ncmp.api.impl.operations; - -import lombok.RequiredArgsConstructor; -import org.onap.cps.ncmp.api.impl.client.DmiRestClient; -import org.onap.cps.ncmp.api.impl.config.DmiProperties; -import org.onap.cps.ncmp.api.impl.inventory.InventoryPersistence; -import org.onap.cps.ncmp.api.impl.utils.DmiServiceUrlBuilder; -import org.onap.cps.utils.JsonObjectMapper; -import org.springframework.stereotype.Service; - -@RequiredArgsConstructor -@Service -public class DmiOperations { - - protected final InventoryPersistence inventoryPersistence; - protected final JsonObjectMapper jsonObjectMapper; - protected final DmiProperties dmiProperties; - protected final DmiRestClient dmiRestClient; - protected final DmiServiceUrlBuilder dmiServiceUrlBuilder; - - String getDmiResourceUrl(final String dmiServiceName, final String cmHandle, final String resourceName) { - return dmiServiceUrlBuilder.getResourceDataBasePathUriBuilder() - .pathSegment("{resourceName}") - .buildAndExpand(dmiServiceName, dmiProperties.getDmiBasePath(), cmHandle, resourceName).toUriString(); - } -} diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/OperationType.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/OperationType.java index fa00d1a15e..e863228ed5 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/OperationType.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/operations/OperationType.java @@ -21,9 +21,7 @@ package org.onap.cps.ncmp.api.impl.operations; import com.fasterxml.jackson.annotation.JsonValue; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; +import java.util.Locale; import lombok.Getter; import org.onap.cps.ncmp.api.impl.exception.InvalidOperationException; @@ -48,13 +46,6 @@ public enum OperationType { return String.valueOf(operationName); } - private static final Map<String, OperationType> operationNameToOperationEnum = new HashMap<>(); - - static { - Arrays.stream(OperationType.values()).forEach( - operationType -> operationNameToOperationEnum.put(operationType.getOperationName(), operationType)); - } - /** * From operation name get operation enum type. * @@ -62,10 +53,10 @@ public enum OperationType { * @return the operation enum type */ public static OperationType fromOperationName(final String operationName) { - final OperationType operationType = operationNameToOperationEnum.get(operationName); - if (null == operationType) { + try { + return OperationType.valueOf(operationName.toUpperCase(Locale.ENGLISH)); + } catch (final IllegalArgumentException e) { throw new InvalidOperationException(operationName + " is an invalid operation name"); } - return operationType; } } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilder.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilder.java index 15f1effdd6..aeeeb6430f 100644 --- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilder.java +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/utils/DmiServiceUrlBuilder.java @@ -20,167 +20,92 @@ package org.onap.cps.ncmp.api.impl.utils; -import java.net.URLEncoder; -import java.nio.charset.StandardCharsets; import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; -import lombok.RequiredArgsConstructor; +import lombok.NoArgsConstructor; import org.apache.logging.log4j.util.Strings; -import org.apache.logging.log4j.util.TriConsumer; -import org.onap.cps.ncmp.api.impl.config.DmiProperties; -import org.onap.cps.spi.utils.CpsValidator; -import org.springframework.stereotype.Component; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; import org.springframework.web.util.UriComponentsBuilder; -@Component -@RequiredArgsConstructor +@NoArgsConstructor public class DmiServiceUrlBuilder { - private final DmiProperties dmiProperties; - private final CpsValidator cpsValidator; - /** - * This method creates the dmi service url. - * - * @param queryParams query param map as key,value pair - * @param uriVariables uri param map as key (placeholder),value pair - * @return {@code String} dmi service url as string - */ - public String getDmiDatastoreUrl(final MultiValueMap<String, String> queryParams, - final Map<String, Object> uriVariables) { - return getUriComponentsBuilder(getResourceDataBasePathUriBuilder(), queryParams, uriVariables) - .buildAndExpand().toUriString(); - } + private static final String FIXED_PATH_SEGMENT = null; - /** - * This method builds data operation request url. - * - * @param dataoperationRequestQueryParams query param map as key, value pair - * @param dataoperationRequestUriVariables uri param map as key (placeholder), value pair - * @return {@code String} data operation request url as string - */ - public String getDataOperationRequestUrl(final MultiValueMap<String, String> dataoperationRequestQueryParams, - final Map<String, Object> dataoperationRequestUriVariables) { - return getDataOperationResourceDataBasePathUriBuilder() - .queryParams(dataoperationRequestQueryParams) - .uriVariables(dataoperationRequestUriVariables) - .buildAndExpand().toUriString(); - } + final UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.newInstance(); + final Map<String, Object> pathSegments = new LinkedHashMap<>(); - /** - * This method creates the dmi service url builder object with path variables. - * - * @return {@code UriComponentsBuilder} dmi service url builder object - */ - public UriComponentsBuilder getResourceDataBasePathUriBuilder() { - return UriComponentsBuilder.newInstance() - .path("{dmiServiceName}") - .pathSegment("{dmiBasePath}") - .pathSegment("v1") - .pathSegment("ch") - .pathSegment("{cmHandleId}"); + public static DmiServiceUrlBuilder newInstance() { + return new DmiServiceUrlBuilder(); } /** - * This method creates the dmi service url builder object with path variables for data operation request. + * Add a fixed pathSegment to the URI. * - * @return {@code UriComponentsBuilder} dmi service url builder object + * @param pathSegment the path segment + * @return this builder */ - public UriComponentsBuilder getDataOperationResourceDataBasePathUriBuilder() { - return UriComponentsBuilder.newInstance() - .path("{dmiServiceName}") - .pathSegment("{dmiBasePath}") - .pathSegment("v1") - .pathSegment("data"); + public DmiServiceUrlBuilder pathSegment(final String pathSegment) { + pathSegments.put(pathSegment, FIXED_PATH_SEGMENT); + return this; } /** - * This method populates uri variables. + * Add a variable pathSegment to the URI. + * Do NOT add { } braces. the builder will take care of that * - * @param dataStoreName data store name - * @param dmiServiceName dmi service name - * @param cmHandleId cm handle id for dmi registration - * @return {@code String} dmi service url as string + * @param pathSegment the name of the variable path segment (with { and } + * @param value the value to be insert in teh URI for the given variable path segment + * @return this builder */ - public Map<String, Object> populateUriVariables(final String dataStoreName, - final String dmiServiceName, - final String cmHandleId) { - cpsValidator.validateNameCharacters(cmHandleId); - final Map<String, Object> uriVariables = new HashMap<>(); - final String dmiBasePath = dmiProperties.getDmiBasePath(); - uriVariables.put("dmiServiceName", dmiServiceName); - uriVariables.put("dmiBasePath", dmiBasePath); - uriVariables.put("cmHandleId", cmHandleId); - uriVariables.put("dataStore", dataStoreName); - return uriVariables; + public DmiServiceUrlBuilder variablePathSegment(final String pathSegment, final Object value) { + pathSegments.put(pathSegment, value); + return this; } /** - * This method populates uri variables for data operation request. + * Add a query parameter to the URI. + * Do NOT encode as the builder wil take care of encoding * - * @param dmiServiceName dmi service name - * @return {@code Map<String, Object>} uri variables as map - */ - public Map<String, Object> populateDataOperationRequestUriVariables(final String dmiServiceName) { - final Map<String, Object> uriVariables = new HashMap<>(); - final String dmiBasePath = dmiProperties.getDmiBasePath(); - uriVariables.put("dmiServiceName", dmiServiceName); - uriVariables.put("dmiBasePath", dmiBasePath); - return uriVariables; - } - - /** - * This method is used to populate map from query params. + * @param name the name of the variable + * @param value the value of the variable (only Strings are supported). * - * @param resourceId unique id of response for valid topic - * @param optionsParamInQuery options as provided by client - * @param topicParamInQuery topic as provided by client - * @return all valid query params as map + * @return this builder */ - public MultiValueMap<String, String> populateQueryParams(final String resourceId, - final String optionsParamInQuery, - final String topicParamInQuery) { - final MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>(); - getQueryParamConsumer().accept("resourceIdentifier", resourceId, queryParams); - getQueryParamConsumer().accept("options", optionsParamInQuery, queryParams); - if (Strings.isNotEmpty(topicParamInQuery)) { - getQueryParamConsumer().accept("topic", topicParamInQuery, queryParams); + public DmiServiceUrlBuilder queryParameter(final String name, final String value) { + if (Strings.isNotBlank(value)) { + uriComponentsBuilder.queryParam(name, value); } - return queryParams; + return this; } /** - * This method is used to populate map from query params for data operation request. + * Build the URI as a correctly percentage-encoded String. * - * @param topicParamInQuery topic into url param - * @param requestId unique id of response for valid topic - * @return all valid query params as map + * @param dmiServiceName the name of the dmi service + * @param dmiBasePath the base path of the dmi service + * + * @return URI as a string */ - public MultiValueMap<String, String> getDataOperationRequestQueryParams(final String topicParamInQuery, - final String requestId) { - final MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>(); - getQueryParamConsumer().accept("topic", topicParamInQuery, queryParams); - getQueryParamConsumer().accept("requestId", requestId, queryParams); - return queryParams; - } + public String build(final String dmiServiceName, final String dmiBasePath) { + uriComponentsBuilder + .path("{dmiServiceName}") + .pathSegment("{dmiBasePath}") + .pathSegment("v1"); - private TriConsumer<String, String, MultiValueMap<String, String>> getQueryParamConsumer() { - return (paramName, paramValue, paramMap) -> { - if (Strings.isNotEmpty(paramValue)) { - paramMap.add(paramName, URLEncoder.encode(paramValue, StandardCharsets.UTF_8)); + final Map<String, Object> uriVariables = new HashMap<>(); + uriVariables.put("dmiServiceName", dmiServiceName); + uriVariables.put("dmiBasePath", dmiBasePath); + + pathSegments.forEach((pathSegment, variablePathValue) -> { + if (variablePathValue == FIXED_PATH_SEGMENT) { + uriComponentsBuilder.pathSegment(pathSegment); + } else { + uriComponentsBuilder.pathSegment("{" + pathSegment + "}"); + uriVariables.put(pathSegment, variablePathValue); } - }; + }); + return uriComponentsBuilder.buildAndExpand(uriVariables).encode().toUriString(); } - private UriComponentsBuilder getUriComponentsBuilder(final UriComponentsBuilder uriComponentsBuilder, - final MultiValueMap<String, String> queryParams, - final Map<String, Object> uriVariables) { - return uriComponentsBuilder - .pathSegment("data") - .pathSegment("ds") - .pathSegment("{dataStore}") - .queryParams(queryParams) - .uriVariables(uriVariables); - } } |