From 9ed5663b79a772246026545cbedc2cc4bd5039e4 Mon Sep 17 00:00:00 2001 From: ck-c8y Date: Thu, 16 Jan 2025 09:21:57 +0100 Subject: [PATCH] consolidate methods splitTopicExcludingSeparator --- .../java/dynamic/mapping/model/Mapping.java | 50 +++++++++---------- .../inbound/BaseProcessorInbound.java | 2 +- .../outbound/BaseProcessorOutbound.java | 2 +- .../base-processor-inbound.service.ts | 4 +- .../base-processor-outbound.service.ts | 6 +-- dynamic-mapping-ui/src/mapping/shared/util.ts | 45 +++++++++-------- .../mapping-stepper.component.ts | 14 +++--- 7 files changed, 61 insertions(+), 62 deletions(-) diff --git a/dynamic-mapping-service/src/main/java/dynamic/mapping/model/Mapping.java b/dynamic-mapping-service/src/main/java/dynamic/mapping/model/Mapping.java index 36f5c757..51f86d2a 100644 --- a/dynamic-mapping-service/src/main/java/dynamic/mapping/model/Mapping.java +++ b/dynamic-mapping-service/src/main/java/dynamic/mapping/model/Mapping.java @@ -250,37 +250,35 @@ public static List splitTopicIncludingSeparatorAsList(String topic) { Arrays.asList(Mapping.splitTopicIncludingSeparatorAsArray(topic))); } - public static String[] splitTopicExcludingSeparatorAsArray(String topic) { - topic = topic.trim().replaceAll("(\\/{1,}$)|(^\\/{1,})", ""); - return topic.split("\\/"); - } - - public static String[] splitTopicExcludingSeparatorIncludingLeagingSlashAsArray(String topic) { - String topix = topic.trim().replaceAll("\\/{1,}$", ""); // Remove trailing slashes only - if (topix.startsWith("//")) { // If multiple leading slashes - topix = "/" + topix.replaceAll("^/+", ""); // Replace with single slash - } + public static String[] splitTopicExcludingSeparatorAsArray(String topic, boolean cutOffLeadingSlash) { + String topix = topic.trim(); - // Special handling for the first slash - if (topix.startsWith("/")) { - String[] parts = topix.substring(1).split("\\/"); - String[] result = new String[parts.length + 1]; - result[0] = "/"; - System.arraycopy(parts, 0, result, 1, parts.length); - return result; + if (cutOffLeadingSlash) { + // Original behavior: remove both leading and trailing slashes + topix = topix.replaceAll("(\\/{1,}$)|(^\\/{1,})", ""); + return topix.split("\\/"); + } else { + // New behavior: keep leading slash, remove only trailing slashes + topix = topix.replaceAll("\\/{1,}$", ""); + if (topix.startsWith("//")) { + topix = "/" + topix.replaceAll("^/+", ""); + } + + if (topix.startsWith("/")) { + String[] parts = topix.substring(1).split("\\/"); + String[] result = new String[parts.length + 1]; + result[0] = "/"; + System.arraycopy(parts, 0, result, 1, parts.length); + return result; + } + + return topix.split("\\/"); } - - return topix.split("\\/"); - } - - public static List splitTopicExcludingSeparatorAsList(String topic) { - return new ArrayList( - Arrays.asList(Mapping.splitTopicExcludingSeparatorAsArray(topic))); } - public static List splitTopicExcludingSeparatorIncludingLeagingSlashAsList(String topic) { + public static List splitTopicExcludingSeparatorAsList(String topic, boolean cutOffLeadingSlash) { return new ArrayList( - Arrays.asList(Mapping.splitTopicExcludingSeparatorIncludingLeagingSlashAsArray(topic))); + Arrays.asList(Mapping.splitTopicExcludingSeparatorAsArray(topic, cutOffLeadingSlash))); } /* diff --git a/dynamic-mapping-service/src/main/java/dynamic/mapping/processor/inbound/BaseProcessorInbound.java b/dynamic-mapping-service/src/main/java/dynamic/mapping/processor/inbound/BaseProcessorInbound.java index 74aa9d35..93cd3c03 100644 --- a/dynamic-mapping-service/src/main/java/dynamic/mapping/processor/inbound/BaseProcessorInbound.java +++ b/dynamic-mapping-service/src/main/java/dynamic/mapping/processor/inbound/BaseProcessorInbound.java @@ -88,7 +88,7 @@ public void enrichPayload(ProcessingContext context) { String tenant = context.getTenant(); Object payloadObject = context.getPayload(); - List splitTopicAsList = Mapping.splitTopicExcludingSeparatorIncludingLeagingSlashAsList(context.getTopic()); + List splitTopicAsList = Mapping.splitTopicExcludingSeparatorAsList(context.getTopic(), false); if (payloadObject instanceof Map) { ((Map) payloadObject).put(Mapping.TOKEN_TOPIC_LEVEL, splitTopicAsList); if (context.isSupportsMessageContext() && context.getKey() != null) { diff --git a/dynamic-mapping-service/src/main/java/dynamic/mapping/processor/outbound/BaseProcessorOutbound.java b/dynamic-mapping-service/src/main/java/dynamic/mapping/processor/outbound/BaseProcessorOutbound.java index 880541a7..3ae60491 100644 --- a/dynamic-mapping-service/src/main/java/dynamic/mapping/processor/outbound/BaseProcessorOutbound.java +++ b/dynamic-mapping-service/src/main/java/dynamic/mapping/processor/outbound/BaseProcessorOutbound.java @@ -123,7 +123,7 @@ public ProcessingContext substituteInTargetAndSend(ProcessingContext conte * step 0 patch payload with dummy property _TOPIC_LEVEL_ in case the content * is required in the payload for a substitution */ - List splitTopicExAsList = Mapping.splitTopicExcludingSeparatorIncludingLeagingSlashAsList(context.getTopic()); + List splitTopicExAsList = Mapping.splitTopicExcludingSeparatorAsList(context.getTopic(), false); payloadTarget.put("$", Mapping.TOKEN_TOPIC_LEVEL, splitTopicExAsList); if (mapping.supportsMessageContext) { Map cod = new HashMap() { diff --git a/dynamic-mapping-ui/src/mapping/core/processor/base-processor-inbound.service.ts b/dynamic-mapping-ui/src/mapping/core/processor/base-processor-inbound.service.ts index 6cf7a227..efa314f4 100644 --- a/dynamic-mapping-ui/src/mapping/core/processor/base-processor-inbound.service.ts +++ b/dynamic-mapping-ui/src/mapping/core/processor/base-processor-inbound.service.ts @@ -31,7 +31,7 @@ import { RepairStrategy, getPathTargetForDeviceIdentifiers, transformGenericPath2C8YPath } from '../../../shared'; -import { splitTopicExcludingSeparatorIncludingLeagingSlash } from '../../shared/util'; +import { splitTopicExcludingSeparator } from '../../shared/util'; import { C8YAgent } from '../c8y-agent.service'; import { IDENTITY, @@ -65,7 +65,7 @@ export abstract class BaseProcessorInbound { enrichPayload(context: ProcessingContext): void { const { payload } = context; - const topicLevels = splitTopicExcludingSeparatorIncludingLeagingSlash(context.topic); + const topicLevels = splitTopicExcludingSeparator(context.topic, false); payload[TOKEN_TOPIC_LEVEL] = topicLevels; } diff --git a/dynamic-mapping-ui/src/mapping/core/processor/base-processor-outbound.service.ts b/dynamic-mapping-ui/src/mapping/core/processor/base-processor-outbound.service.ts index 819608e8..2dc7aba6 100644 --- a/dynamic-mapping-ui/src/mapping/core/processor/base-processor-outbound.service.ts +++ b/dynamic-mapping-ui/src/mapping/core/processor/base-processor-outbound.service.ts @@ -24,7 +24,7 @@ import * as _ from 'lodash'; import { API, Mapping, MappingType, RepairStrategy } from '../../../shared'; import { TOKEN_TOPIC_LEVEL, - splitTopicExcludingSeparatorIncludingLeagingSlash, + splitTopicExcludingSeparator, splitTopicIncludingSeparator } from '../../shared/util'; import { C8YAgent } from '../c8y-agent.service'; @@ -72,8 +72,8 @@ export abstract class BaseProcessorOutbound { * step 0 patch payload with dummy property _TOPIC_LEVEL_ in case the content * is required in the payload for a substitution */ - const splitTopicExAsList: string[] = splitTopicExcludingSeparatorIncludingLeagingSlash( - context.topic + const splitTopicExAsList: string[] = splitTopicExcludingSeparator( + context.topic, false ); payloadTarget[TOKEN_TOPIC_LEVEL] = splitTopicExAsList; const deviceSource: string = 'undefined'; diff --git a/dynamic-mapping-ui/src/mapping/shared/util.ts b/dynamic-mapping-ui/src/mapping/shared/util.ts index 2b284c87..4d993bd1 100644 --- a/dynamic-mapping-ui/src/mapping/shared/util.ts +++ b/dynamic-mapping-ui/src/mapping/shared/util.ts @@ -34,26 +34,27 @@ export const TOKEN_CONTEXT_DATA = '_CONTEXT_DATA_'; export const CONTEXT_DATA_KEY_NAME = 'key'; export const TIME = 'time'; -export function splitTopicExcludingSeparator(topic: string): string[] { - let topix = topic; - topix = topix.trim().replace(/(\/{1,}$)|(^\/{1,})/g, ''); - return topix.split(/\//g); -} - -export function splitTopicExcludingSeparatorIncludingLeagingSlash(topic: string): string[] { - let topix = topic; - topix = topix.trim().replace(/(\/{1,}$)/g, ''); // Remove trailing slashes - if (topix.startsWith('//')) { // If there are multiple leading slashes - topix = '/' + topix.replace(/^\/+/, ''); // Replace with single slash - } +export function splitTopicExcludingSeparator(topic: string, cutOffLeadingSlash: boolean): string[] { + let topix = topic.trim(); - // Special handling for the first slash - if (topix.startsWith('/')) { - const parts = topix.substring(1).split(/\//g); - return ['/'].concat(parts); + if (cutOffLeadingSlash) { + // Original behavior: remove both leading and trailing slashes + topix = topix.replace(/(\/{1,}$)|(^\/{1,})/g, ''); + return topix.split(/\//g); + } else { + // New behavior: keep leading slash, remove only trailing slashes + topix = topix.replace(/\/{1,}$/g, ''); + if (topix.startsWith('//')) { + topix = '/' + topix.replace(/^\/+/, ''); + } + + if (topix.startsWith('/')) { + const parts = topix.substring(1).split(/\//g); + return ['/'].concat(parts); + } + + return topix.split(/\//g); } - - return topix.split(/\//g); } export function splitTopicIncludingSeparator(topic: string): string[] { @@ -204,9 +205,9 @@ export function checkTopicsInboundAreValid(control: AbstractControl) { }; } - const splitTT: string[] = splitTopicExcludingSeparator(mappingTopic.value); + const splitTT: string[] = splitTopicExcludingSeparator(mappingTopic.value, false); const splitTTS: string[] = splitTopicExcludingSeparator( - mappingTopicSample.value + mappingTopicSample.value, false ); if (splitTT.length != splitTTS.length) { errors = { @@ -322,9 +323,9 @@ export function checkTopicsOutboundAreValid(control: AbstractControl) { }; } - const splitPT: string[] = splitTopicExcludingSeparator(publishTopic.value); + const splitPT: string[] = splitTopicExcludingSeparator(publishTopic.value, false); const splitTTS: string[] = splitTopicExcludingSeparator( - publishTopicSample.value + publishTopicSample.value, false ); if (splitPT.length != splitTTS.length) { errors = { diff --git a/dynamic-mapping-ui/src/mapping/stepper-mapping/mapping-stepper.component.ts b/dynamic-mapping-ui/src/mapping/stepper-mapping/mapping-stepper.component.ts index b7fb4e59..d1ebee9c 100644 --- a/dynamic-mapping-ui/src/mapping/stepper-mapping/mapping-stepper.component.ts +++ b/dynamic-mapping-ui/src/mapping/stepper-mapping/mapping-stepper.component.ts @@ -66,7 +66,7 @@ import { expandExternalTemplate, isTypeOf, reduceSourceTemplate, - splitTopicExcludingSeparatorIncludingLeagingSlash + splitTopicExcludingSeparator } from '../shared/util'; import { EditSubstitutionComponent } from '../substitution/edit/edit-substitution-modal.component'; import { SubstitutionRendererComponent } from '../substitution/substitution-grid.component'; @@ -566,8 +566,8 @@ export class MappingStepperComponent implements OnInit, OnDestroy { this.mapping ); } else { - const levels: string[] = splitTopicExcludingSeparatorIncludingLeagingSlash( - this.mapping.mappingTopicSample + const levels: string[] = splitTopicExcludingSeparator( + this.mapping.mappingTopicSample, false ); this.targetTemplate = expandExternalTemplate( JSON.parse(getExternalTemplate(this.mapping)), @@ -694,10 +694,10 @@ export class MappingStepperComponent implements OnInit, OnDestroy { } private expandTemplates() { - const levels: string[] = splitTopicExcludingSeparatorIncludingLeagingSlash( + const levels: string[] = splitTopicExcludingSeparator( this.mapping.direction == Direction.INBOUND ? this.mapping.mappingTopicSample - : this.mapping.publishTopicSample + : this.mapping.publishTopicSample, false ); if ( @@ -772,7 +772,7 @@ export class MappingStepperComponent implements OnInit, OnDestroy { this.sourceTemplate = expandExternalTemplate( this.sourceTemplate, this.mapping, - splitTopicExcludingSeparatorIncludingLeagingSlash(this.mapping.mappingTopicSample) + splitTopicExcludingSeparator(this.mapping.mappingTopicSample, false) ); } else { this.sourceTemplate = expandC8YTemplate( @@ -800,7 +800,7 @@ export class MappingStepperComponent implements OnInit, OnDestroy { this.sourceTemplate = expandExternalTemplate( this.sourceTemplate, this.mapping, - splitTopicExcludingSeparatorIncludingLeagingSlash(this.mapping.mappingTopicSample) + splitTopicExcludingSeparator(this.mapping.mappingTopicSample, false) ); } else { this.sourceTemplate = expandC8YTemplate(