diff options
author | JoeOLeary <joseph.o.leary@est.tech> | 2019-02-15 13:46:01 +0000 |
---|---|---|
committer | JoeOLeary <joseph.o.leary@est.tech> | 2019-02-15 13:46:01 +0000 |
commit | 924ab47c83837fae7c70713cab51665b8fc858a6 (patch) | |
tree | d26b3fcf654603bdf27992399a76c7f879fffcc6 /src/main | |
parent | 85d315a40fa48255e1104a0c2d6c5ad984952c9c (diff) |
Add Mapping
Change-Id: I417b7fe9d0e588c6c38dc23eb55e43a85e277e81
Issue-ID: DCAEGEN2-1216
Signed-off-by: JoeOLeary <joseph.o.leary@est.tech>
Diffstat (limited to 'src/main')
8 files changed, 302 insertions, 7 deletions
diff --git a/src/main/java/org/onap/dcaegen2/services/pmmapper/App.java b/src/main/java/org/onap/dcaegen2/services/pmmapper/App.java index 3c075ba..67d4875 100644 --- a/src/main/java/org/onap/dcaegen2/services/pmmapper/App.java +++ b/src/main/java/org/onap/dcaegen2/services/pmmapper/App.java @@ -31,19 +31,29 @@ import org.onap.dcaegen2.services.pmmapper.exceptions.CBSServerError; import org.onap.dcaegen2.services.pmmapper.exceptions.EnvironmentConfigException; import org.onap.dcaegen2.services.pmmapper.exceptions.MapperConfigException; import org.onap.dcaegen2.services.pmmapper.exceptions.TooManyTriesException; +import org.onap.dcaegen2.services.pmmapper.mapping.Mapper; import org.onap.dcaegen2.services.pmmapper.model.MapperConfig; import org.onap.dcaegen2.services.pmmapper.healthcheck.HealthCheckHandler; +import org.onap.logging.ref.slf4j.ONAPLogAdapter; +import org.slf4j.LoggerFactory; +import org.slf4j.MDC; -import java.net.MalformedURLException; -import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; public class App { + private static final ONAPLogAdapter logger = new ONAPLogAdapter(LoggerFactory.getLogger(App.class)); + private static Path mappingTemplate = Paths.get("/opt/app/pm-mapper/etc/mapping.ftl"); - public static void main(String[] args) throws MalformedURLException, InterruptedException, TooManyTriesException, CBSConfigException, EnvironmentConfigException, CBSServerError, MapperConfigException { + public static void main(String[] args) throws InterruptedException, TooManyTriesException, CBSConfigException, EnvironmentConfigException, CBSServerError, MapperConfigException { HealthCheckHandler healthCheckHandler = new HealthCheckHandler(); + Mapper mapper = new Mapper(mappingTemplate); DataRouterSubscriber dataRouterSubscriber = new DataRouterSubscriber(event -> { event.getHttpServerExchange().unDispatch(); event.getHttpServerExchange().getResponseSender().send(StatusCodes.OK_STRING); + MDC.setContextMap(event.getMdc()); + String ves = mapper.map(event); + logger.unwrap().info("Mapped Event: {}", ves); }); MapperConfig mapperConfig = new ConfigHandler().getMapperConfig(); dataRouterSubscriber.start(mapperConfig); diff --git a/src/main/java/org/onap/dcaegen2/services/pmmapper/datarouter/DataRouterSubscriber.java b/src/main/java/org/onap/dcaegen2/services/pmmapper/datarouter/DataRouterSubscriber.java index e262d42..fc623bd 100644 --- a/src/main/java/org/onap/dcaegen2/services/pmmapper/datarouter/DataRouterSubscriber.java +++ b/src/main/java/org/onap/dcaegen2/services/pmmapper/datarouter/DataRouterSubscriber.java @@ -42,6 +42,7 @@ import org.onap.dcaegen2.services.pmmapper.utils.RequiredFieldDeserializer; import org.onap.logging.ref.slf4j.ONAPLogAdapter; import org.onap.logging.ref.slf4j.ONAPLogConstants; import org.slf4j.LoggerFactory; +import org.slf4j.MDC; import java.io.IOException; import java.io.OutputStream; @@ -49,6 +50,7 @@ import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.nio.charset.StandardCharsets; import java.time.Instant; +import java.util.Map; import java.util.Optional; import java.util.Random; import java.util.UUID; @@ -174,11 +176,11 @@ public class DataRouterSubscriber implements HttpHandler { .get(METADATA_HEADER)) .map((HeaderValues headerValues) -> headerValues.get(0)) .orElseThrow(() -> new NoMetadataException("Metadata Not found")); - + Map<String,String> mdc = MDC.getCopyOfContextMap(); EventMetadata metadata = metadataBuilder.fromJson(metadataAsString, EventMetadata.class); httpServerExchange.getRequestReceiver() .receiveFullString((callbackExchange, body) -> { - httpServerExchange.dispatch(() -> eventReceiver.receive(new Event(callbackExchange, body, metadata))); + httpServerExchange.dispatch(() -> eventReceiver.receive(new Event(callbackExchange, body, metadata, mdc))); }); } catch (NoMetadataException exception) { logger.unwrap().info("Bad Request: no metadata found under '{}' header.", METADATA_HEADER, exception); diff --git a/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/MappingException.java b/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/MappingException.java new file mode 100644 index 0000000..16af18b --- /dev/null +++ b/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/MappingException.java @@ -0,0 +1,28 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 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.dcaegen2.services.pmmapper.exceptions; + +public class MappingException extends RuntimeException{ + public MappingException(String message, Throwable cause) { + super(message, cause); + } + +} diff --git a/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/XMLParseException.java b/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/XMLParseException.java new file mode 100644 index 0000000..c2bfa01 --- /dev/null +++ b/src/main/java/org/onap/dcaegen2/services/pmmapper/exceptions/XMLParseException.java @@ -0,0 +1,27 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 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.dcaegen2.services.pmmapper.exceptions; + +public class XMLParseException extends RuntimeException{ + public XMLParseException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/src/main/java/org/onap/dcaegen2/services/pmmapper/mapping/Mapper.java b/src/main/java/org/onap/dcaegen2/services/pmmapper/mapping/Mapper.java new file mode 100644 index 0000000..0ad26e3 --- /dev/null +++ b/src/main/java/org/onap/dcaegen2/services/pmmapper/mapping/Mapper.java @@ -0,0 +1,93 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2019 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.dcaegen2.services.pmmapper.mapping; + +import freemarker.ext.dom.NodeModel; +import freemarker.template.Configuration; +import freemarker.template.Template; +import freemarker.template.TemplateException; +import lombok.NonNull; +import org.onap.dcaegen2.services.pmmapper.exceptions.MappingException; +import org.onap.dcaegen2.services.pmmapper.exceptions.XMLParseException; +import org.onap.dcaegen2.services.pmmapper.model.Event; +import org.onap.logging.ref.slf4j.ONAPLogAdapter; +import org.slf4j.LoggerFactory; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +import javax.xml.parsers.ParserConfigurationException; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.StringReader; +import java.io.StringWriter; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class Mapper { + private static final ONAPLogAdapter logger = new ONAPLogAdapter(LoggerFactory.getLogger(Mapper.class)); + private Template mappingTemplate; + + public Mapper(@NonNull Path pathToTemplate) { + logger.unwrap().trace("Constructing Mapper from {}", pathToTemplate); + Configuration configuration = new Configuration(Configuration.VERSION_2_3_28); + configuration.setTagSyntax(Configuration.ANGLE_BRACKET_TAG_SYNTAX); + try { + InputStreamReader templateInputStreamReader = new InputStreamReader(Files.newInputStream(pathToTemplate)); + mappingTemplate = new Template("pm", templateInputStreamReader, configuration, StandardCharsets.UTF_8.name()); + } catch (IOException exception) { + logger.unwrap().error("Failed to read template from location {}", pathToTemplate, exception); + throw new IllegalArgumentException("Failed to read template from path", exception); + } + } + + public String map(@NonNull Event event) { + logger.unwrap().info("Mapping event"); + NodeModel pmNodeModel; + try { + pmNodeModel = NodeModel.parse(new InputSource(new StringReader(event.getBody()))); + } catch (IOException | SAXException | ParserConfigurationException exception) { + logger.unwrap().error("Failed to parse input as XML", exception); + throw new XMLParseException("Failed to parse input as XML", exception); + } + Map<String, Object> mappingData = new HashMap<>(); + mappingData.put("xml", pmNodeModel); + mappingData.put("metadata", event.getMetadata()); + mappingData.put("eventId", makeEventId()); + StringWriter mappedOutputWriter = new StringWriter(); + try { + mappingTemplate.process(mappingData, mappedOutputWriter); + } catch (IOException | TemplateException exception) { + logger.unwrap().error("Failed to map XML", exception); + throw new MappingException("Mapping failure", exception); + } + logger.unwrap().info("Data mapped successfully"); + return mappedOutputWriter.toString(); + } + + private String makeEventId(){ + return UUID.randomUUID().toString(); + } + +} diff --git a/src/main/java/org/onap/dcaegen2/services/pmmapper/model/Event.java b/src/main/java/org/onap/dcaegen2/services/pmmapper/model/Event.java index a08dcfb..c2cacaa 100644 --- a/src/main/java/org/onap/dcaegen2/services/pmmapper/model/Event.java +++ b/src/main/java/org/onap/dcaegen2/services/pmmapper/model/Event.java @@ -23,6 +23,8 @@ import io.undertow.server.HttpServerExchange; import lombok.Data; import lombok.NonNull; +import java.util.Map; + /** * Class used to pass around relevant inbound event data. */ @@ -34,4 +36,6 @@ public class Event { private String body; @NonNull private EventMetadata metadata; + @NonNull + private Map<String, String> mdc; } diff --git a/src/main/resources/Dockerfile b/src/main/resources/Dockerfile index e48427c..9291567 100644 --- a/src/main/resources/Dockerfile +++ b/src/main/resources/Dockerfile @@ -18,6 +18,9 @@ # ============LICENSE_END========================================================= # FROM openjdk:8-jre -ENTRYPOINT ["/usr/bin/java", "-jar", "/opt/pm-mapper.jar"] +ENTRYPOINT ["/usr/bin/java", "-jar", "/opt/app/pm-mapper/pm-mapper.jar"] ARG JAR -ADD target/${JAR} /opt/pm-mapper.jar +WORKDIR /opt/app/pm-mapper +ADD target/${JAR} /opt/app/pm-mapper/pm-mapper.jar +ADD target/classes/mapping.ftl /opt/app/pm-mapper/etc/mapping.ftl + diff --git a/src/main/resources/mapping.ftl b/src/main/resources/mapping.ftl new file mode 100644 index 0000000..0b35c54 --- /dev/null +++ b/src/main/resources/mapping.ftl @@ -0,0 +1,128 @@ +<#ftl ns_prefixes={"D":"http://www.3gpp.org/ftp/specs/archive/32_series/32.435#measCollec"}> +<#-- + ============LICENSE_START======================================================= + Copyright (C) 2019 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========================================================= + --> +<#assign fileHeader = xml.measCollecFile.fileHeader> +<#assign fileFooter = xml.measCollecFile.fileFooter> +<#assign measData = xml.measCollecFile.measData> +<#setting datetime_format="iso"> +{ + "event": { + "commonEventHeader": <@commonEventHeader/> + <#if measData?has_content>, + "perf3gppFields": <@perf3gppFields/> + </#if> + } +} + + +<#macro commonEventHeader> +{ + "domain": "perf3gpp", + "eventId": "${eventId}", + "sequence": 0, + "eventName": "perf3gpp_${metadata.productName}-${metadata.vendorName}_pmMeasResult", + "sourceName": "${metadata.sourceName}", + "reportingEntityName": "", + "priority": "Normal", + "startEpochMicrosec": ${fileHeader.measCollec.@beginTime?datetime?long?c}, + "lastEpochMicrosec": ${fileFooter.measCollec.@endTime?datetime?long?c}, + "version": "4.0", + "vesEventListenerVersion": "7.1", + "timeZoneOffset": "${metadata.timeZoneOffset}" +} +</#macro> + + +<#macro measTypes measInfo> +{ + "sMeasTypesList":[ + <#if measInfo.measType?has_content> + <#list measInfo.measType as measType> + "${measType}"<#sep>,</#sep> + </#list> + <#else> + <#list measInfo.measTypes?split(" ") as measType> + "${measType}"<#sep>,</#sep> + </#list> + </#if> + ] +} +</#macro> + + +<#macro measValuesList measInfo> +[ + { + "measObjInstId": "${measInfo.measValue.@measObjLdn[0]!}", + "suspectFlag": "${measInfo.measValue.suspect[0]! "false"}", + "measResults": [ + <#if measInfo.measValue.r?has_content> + <#list measInfo.measValue.r as r> + { + "p": ${r.@p}, + "sValue": "${r}" + }<#sep>,</#sep> + </#list> + <#else> + <#list measInfo.measValue.measResults?split(" ") as r> + { + "p":${r?index+1}, + "sValue": "${r}" + }<#sep>,</#sep> + </#list> + </#if> + ] + } +] +</#macro> + + +<#macro measInfoList> +[ +<#list measData.measInfo as measInfo> + { + "measInfoId": { + "sMeasInfoId": "${measInfo.@measInfoId[0]!}" + }, + "measTypes": <@measTypes measInfo/>, + "measValuesList": <@measValuesList measInfo/> + }<#sep>,</#sep> +</#list> +] +</#macro> + + +<#macro measDataCollection> +{ + "granularityPeriod": ${measData.measInfo.granPeriod.@endTime[0]!?datetime?long?c}, + "measuredEntityUserName": "${measData.managedElement.@userLabel[0]!}", + "measuredEntityDn": "${measData.managedElement.@localDn}", + "measuredEntitySoftwareVersion": "${measData.managedElement.@swVersion}", + "measInfoList": <@measInfoList/> +} +</#macro> + + +<#macro perf3gppFields> +{ + "perf3gppFieldsVersion": "1.0", + "measDataCollection": <@measDataCollection/> +} +</#macro> |