- Introduced new models for DataJobReadRequest and ReadProperties.
- Introduced new ReadRequestExaminer class with a method to split dataNodeSelector on newline and OR.
Issue-ID: CPS-3189
Change-Id: I0265599dc467ba78f1db57b225fbc9993e40f6b5
Signed-off-by: egernug <gerard.nugent@est.tech>
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2024-2025 OpenInfra Foundation Europe. All rights reserved.
+ * Copyright (C) 2024-2026 OpenInfra Foundation Europe. All rights reserved.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
/**
* process read data job operations.
*
- * @param authorization the authorization header from the REST request
- * @param dataJobId unique identifier of the job within the request
- * @param dataJobMetadata data job request headers
* @param dataJobReadRequest read data job request
*/
- void readDataJob(String authorization,
- String dataJobId,
- DataJobMetadata dataJobMetadata,
- DataJobReadRequest dataJobReadRequest);
+ void readDataJob(DataJobReadRequest dataJobReadRequest);
/**
* process write data job operations.
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2024 Nordix Foundation
+ * Copyright (C) 2024-2026 OpenInfra Foundation Europe. All rights reserved.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
package org.onap.cps.ncmp.api.datajobs.models;
-import java.util.List;
+import java.util.Map;
/**
- * Describes the read data job operation to be forwarded to dmi.
+ * Represents a read data job request to be forwarded to a DMI plugin.
+ * Contains metadata and configuration for executing read operations on network elements.
*
- * @param data List of read operations to be executed.
+ * @param name the name of the data job
+ * @param jobId the unique identifier for the data job
+ * @param description a description of the data job purpose
+ * @param readProperties the read operation properties including targets and data specifications
+ * @param customProperties additional custom properties for the data job
*/
-public record DataJobReadRequest(List<ReadOperation> data) {}
+public record DataJobReadRequest(String name, String jobId, String description,
+ ReadProperties readProperties,
+ Map<String, String> customProperties) {}
+++ /dev/null
-/*
- * ============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.datajobs.models;
-
-import java.util.List;
-
-/**
- * Holds information of read data job operation.
- * based on <a href="https://www.etsi.org/deliver/etsi_ts/128500_128599/128532/16.04.00_60/ts_128532v160400p.pdf">ETSI TS 128 532 V16.4.0 (2020-08)</a>
- *
- * @param path Identifier of a managed object (MO) on a network element. Defines the resource on which operation
- * is executed. Url Encoded Fully Distinguished Name (FDN).
- * @param op Describes the operation to execute. The value can only be "read".
- * @param operationId Unique identifier of the operation within the request.
- * @param attributes Specifies the attributes of the resources that are returned.
- * @param fields Specifies the attribute fields of the resources that are returned. This should be used if an
- * attribute is a struct and only a subset of its fields should be returned.
- * @param filter This filters the managed Objects.
- * @param scopeType This selects MOs depending on relationships with Base Managed Object.
- * e.g. "BASE_ONLY", "BASE_ALL", "BASE_NTH_LEVEL" etc.
- * @param scopeLevel Defines the level for objects to be returned for certain scopeTypes. The base level is zero.
- */
-public record ReadOperation(String path, String op, String operationId, List<String> attributes, List<String> fields,
- String filter, String scopeType, int scopeLevel) {
-}
--- /dev/null
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2026 OpenInfra Foundation Europe. All rights reserved.
+ * ================================================================================
+ * 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.datajobs.models;
+
+/**
+ * Represents the properties for a read data job operation.
+ * Defines what data to read and how to format the results.
+ *
+ * @param dataNodeSelector the selector expression to identify target data nodes
+ * @param resultsType the format type for the results (e.g., JSON, XML)
+ */
+public record ReadProperties(String dataNodeSelector, String resultsType) {
+}
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2024-2025 OpenInfra Foundation Europe. All rights reserved.
+ * Copyright (C) 2024-2026 OpenInfra Foundation Europe. All rights reserved.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
import org.onap.cps.ncmp.api.datajobs.models.DmiWriteOperation;
import org.onap.cps.ncmp.api.datajobs.models.ProducerKey;
import org.onap.cps.ncmp.api.datajobs.models.SubJobWriteResponse;
+import org.onap.cps.ncmp.impl.utils.JexParser;
import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.stereotype.Service;
private final JsonObjectMapper jsonObjectMapper;
@Override
- public void readDataJob(final String authorization,
- final String dataJobId,
- final DataJobMetadata dataJobMetadata,
- final DataJobReadRequest dataJobReadRequest) {
- logJobIdAndSize(dataJobId, dataJobReadRequest.data().size());
- log.info("Destination: {}", dataJobMetadata.destination());
- log.info("authorization: {}", authorization);
+ public void readDataJob(final DataJobReadRequest dataJobReadRequest) {
+ log.info("DataJobId: {}", dataJobReadRequest.jobId());
+ final List<String> selectors =
+ JexParser.toXpaths(dataJobReadRequest.readProperties().dataNodeSelector());
+ log.info("DataJobId: {} - Total selectors: {}", dataJobReadRequest.jobId(), selectors.size());
}
@Override
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
+ * Copyright (C) 2025-2026 OpenInfra Foundation Europe. All rights reserved.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
private static final Pattern XPATH_SEGMENT_PATTERN = Pattern.compile("^([^]]*)\\[id=\\\"([^\\\"]*)\\\"]");
private static final String JEX_COMMENT_PREFIX = "&&";
- private static final String LINE_SEPARATOR_REGEX = "\\R";
+ private static final String LINE_OR_LOGICAL_OR_REGEX = "\\R|\\bOR\\b";
private static final String LINE_JOINER_DELIMITER = "\n";
private static final String SEGMENT_SEPARATOR = "/";
if (jsonExpressionsAsString == null) {
return Collections.emptyList();
}
- final String[] lines = jsonExpressionsAsString.split(LINE_SEPARATOR_REGEX);
+ final String[] lines = jsonExpressionsAsString.split(LINE_OR_LOGICAL_OR_REGEX);
return Arrays.stream(lines)
.map(String::trim)
+ .filter(xpath -> !xpath.isEmpty())
.filter(xpath -> !xpath.startsWith(JEX_COMMENT_PREFIX))
.distinct()
.toList();
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2024-2025 OpenInfra Foundation Europe. All rights reserved.
+ * Copyright (C) 2024-2026 OpenInfra Foundation Europe. All rights reserved.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
import org.onap.cps.ncmp.api.datajobs.models.DataJobMetadata
import org.onap.cps.ncmp.api.datajobs.models.DataJobReadRequest
import org.onap.cps.ncmp.api.datajobs.models.DataJobWriteRequest
-import org.onap.cps.ncmp.api.datajobs.models.ReadOperation
+import org.onap.cps.ncmp.api.datajobs.models.ReadProperties
import org.onap.cps.ncmp.api.datajobs.models.WriteOperation
import org.onap.cps.utils.JsonObjectMapper
import org.slf4j.LoggerFactory
class DataJobServiceImplSpec extends Specification {
- def mockWriteRequestExaminer = Mock(WriteRequestExaminer)
def mockDmiSubJobRequestHandler = Mock(DmiSubJobRequestHandler)
+ def mockWriteRequestExaminer = Mock(WriteRequestExaminer)
def mockJsonObjectMapper = Mock(JsonObjectMapper)
def objectUnderTest = new DataJobServiceImpl(mockDmiSubJobRequestHandler, mockWriteRequestExaminer, mockJsonObjectMapper)
((Logger) LoggerFactory.getLogger(DataJobServiceImpl.class)).detachAndStopAllAppenders()
}
- def 'Read data job request.'() {
- when: 'read data job request is processed'
- def readOperation = new ReadOperation('', '', '', [], [], '', '', 1)
- objectUnderTest.readDataJob(authorization, 'my-job-id', myDataJobMetadata, new DataJobReadRequest([readOperation]))
- then: 'the data job id is correctly logged'
- def loggingEvent = logger.list[0]
- assert loggingEvent.level == Level.INFO
- assert loggingEvent.formattedMessage.contains('Data Job ID: my-job-id')
+ def 'Read data job request'() {
+ given: 'a read data job request with two selectors'
+ def dataJobReadRequest = new DataJobReadRequest('job-name', 'job-id', 'description',
+ new ReadProperties('selector1\nselector2', 'some-type'), [:])
+ when: 'the read data job request is processed'
+ objectUnderTest.readDataJob(dataJobReadRequest)
+ then: 'the total number of selectors is logged'
+ with(logger.list.find { it.formattedMessage.contains('Total selectors') }) {
+ assert it.formattedMessage.contains('Total selectors: 2')
+ }
}
def 'Write data-job request and verify logging when info enabled.'() {
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2025 OpenInfra Foundation Europe. All rights reserved.
+ * Copyright (C) 2025-2026 OpenInfra Foundation Europe. All rights reserved.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the 'License');
* you may not use this file except in compliance with the License.
class JexParserSpec extends Specification {
- def 'Parsing multi-line json expressions with #scenario.'() {
+ def 'Parsing json expressions with #scenario.'() {
when: 'the parser gets a (multi-line) json expressions'
def result = JexParser.toXpaths(jsonExpressions)
then: 'the expected xpaths are returned'
'preceding commented line' | '&&ignore this\n/SubNetwork[id="SN1"]'
}
- def 'Parsing multi-line json expressions with multiple xpaths.'() {
- given: 'multi-line json expressions'
- def jsonExpressions = '/SubNetwork[id="SN1"]\n/ManagedElement[id="ME1"]'
+ def 'Parsing json expressions with multiple xpaths using #scenario'() {
when: 'convert it to xpaths'
def result = JexParser.toXpaths(jsonExpressions)
then: 'the expected xpaths are returned'
assert result == ['/SubNetwork[id="SN1"]','/ManagedElement[id="ME1"]']
+ where: 'following expressions are used'
+ scenario | jsonExpressions
+ 'newline delimiter' | '/SubNetwork[id="SN1"]\n/ManagedElement[id="ME1"]'
+ 'OR delimiter' | '/SubNetwork[id="SN1"] OR /ManagedElement[id="ME1"]'
+ 'mixed delimiters' | '/SubNetwork[id="SN1"] OR\n/ManagedElement[id="ME1"]'
+ 'reverse mixed delimiters' | '/SubNetwork[id="SN1"]\nOR/ManagedElement[id="ME1"]'
+ 'OR delimiter with extra spacing'| '/SubNetwork[id="SN1"] OR /ManagedElement[id="ME1"]'
}
def 'Extracts xpaths from json expressions, ignored expressions: #scenario.'() {