summaryrefslogtreecommitdiffstats
path: root/cps-ri/src/main
diff options
context:
space:
mode:
authorniamhcore <niamh.core@est.tech>2021-02-11 14:49:11 +0000
committerniamhcore <niamh.core@est.tech>2021-02-19 10:22:59 +0000
commit760e597acc7854a736363a0136343b5a77462cfb (patch)
treebe65c9cd513bfe306ac1352c9bf9b2a230e7844d /cps-ri/src/main
parent55c4135bff02800659ddc4d2de15222ba229ac51 (diff)
Persistence layer - Query Datanodes using cpsPath that contains contains a leaf name and a leaf value
Issue-ID: CPS-231 Signed-off-by: niamhcore <niamh.core@est.tech> Change-Id: I9bd483a4b76e233ab6c64b3ef8aacb593e4e9da0
Diffstat (limited to 'cps-ri/src/main')
-rw-r--r--cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java15
-rw-r--r--cps-ri/src/main/java/org/onap/cps/spi/query/CpsPathQuery.java76
-rwxr-xr-xcps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepository.java9
3 files changed, 100 insertions, 0 deletions
diff --git a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java
index fd4e768cab..2d9588e8f3 100644
--- a/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java
+++ b/cps-ri/src/main/java/org/onap/cps/spi/impl/CpsDataPersistenceServiceImpl.java
@@ -21,6 +21,7 @@
package org.onap.cps.spi.impl;
import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS;
+import static org.onap.cps.spi.FetchDescendantsOption.OMIT_DESCENDANTS;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
@@ -38,6 +39,7 @@ import org.onap.cps.spi.entities.DataspaceEntity;
import org.onap.cps.spi.entities.FragmentEntity;
import org.onap.cps.spi.model.DataNode;
import org.onap.cps.spi.model.DataNodeBuilder;
+import org.onap.cps.spi.query.CpsPathQuery;
import org.onap.cps.spi.repository.AnchorRepository;
import org.onap.cps.spi.repository.DataspaceRepository;
import org.onap.cps.spi.repository.FragmentRepository;
@@ -124,6 +126,19 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService
return fragmentRepository.getByDataspaceAndAnchorAndXpath(dataspaceEntity, anchorEntity, xpath);
}
+ @Override
+ public List<DataNode> queryDataNodes(final String dataspaceName, final String anchorName, final String cpsPath) {
+ final DataspaceEntity dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
+ final AnchorEntity anchorEntity = anchorRepository.getByDataspaceAndName(dataspaceEntity, anchorName);
+ final CpsPathQuery cpsPathQuery = CpsPathQuery.createFrom(cpsPath);
+ final List<FragmentEntity> fragmentEntities = fragmentRepository
+ .getByAnchorAndXpathAndLeafAttributes(anchorEntity.getId(), cpsPathQuery
+ .getXpathPrefix(), cpsPathQuery.getLeafName(), cpsPathQuery.getLeafValue());
+ return fragmentEntities.stream()
+ .map(fragmentEntity -> toDataNode(fragmentEntity, OMIT_DESCENDANTS))
+ .collect(Collectors.toUnmodifiableList());
+ }
+
private static DataNode toDataNode(final FragmentEntity fragmentEntity,
final FetchDescendantsOption fetchDescendantsOption) {
final Map<String, Object> leaves = GSON.fromJson(fragmentEntity.getAttributes(), Map.class);
diff --git a/cps-ri/src/main/java/org/onap/cps/spi/query/CpsPathQuery.java b/cps-ri/src/main/java/org/onap/cps/spi/query/CpsPathQuery.java
new file mode 100644
index 0000000000..4fcf6e444b
--- /dev/null
+++ b/cps-ri/src/main/java/org/onap/cps/spi/query/CpsPathQuery.java
@@ -0,0 +1,76 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation
+ * Modifications Copyright (C) 2021 Bell Canada. 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.spi.query;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.Setter;
+import org.onap.cps.spi.exceptions.CpsPathException;
+
+@Getter
+@Setter(AccessLevel.PRIVATE)
+public class CpsPathQuery {
+
+ private String xpathPrefix;
+ private String leafName;
+ private Object leafValue;
+
+ public static final Pattern QUERY_CPS_PATH_WITH_SINGLE_LEAF_PATTERN =
+ Pattern.compile("(.*)\\[\\s*@(.*?)\\s*=\\s*(.*?)\\s*]");
+
+ public static final Pattern LEAF_STRING_VALUE_PATTERN = Pattern.compile("['\"](.*)['\"]");
+
+ public static final Pattern LEAF_INTEGER_VALUE_PATTERN = Pattern.compile("[-+]?\\d+");
+
+ /**
+ * Returns a xpath prefix, leaf name and leaf value for the given cps path.
+ *
+ * @param cpsPath cps path
+ * @return a CpsPath object containing the xpath prefix, leaf name and leaf value.
+ */
+ public static CpsPathQuery createFrom(final String cpsPath) {
+ final Matcher matcher = QUERY_CPS_PATH_WITH_SINGLE_LEAF_PATTERN.matcher(cpsPath);
+ if (matcher.matches()) {
+ final CpsPathQuery cpsPathQuery = new CpsPathQuery();
+ cpsPathQuery.setXpathPrefix(matcher.group(1));
+ cpsPathQuery.setLeafName(matcher.group(2));
+ cpsPathQuery.setLeafValue(convertLeafValueToCorrectType(matcher.group(3)));
+ return cpsPathQuery;
+ }
+ throw new CpsPathException("Invalid cps path.",
+ String.format("Cannot interpret or parse cps path %s.", cpsPath));
+ }
+
+ private static Object convertLeafValueToCorrectType(final String leafValueString) {
+ final Matcher stringValueWithQuotesMatcher = LEAF_STRING_VALUE_PATTERN.matcher(leafValueString);
+ if (stringValueWithQuotesMatcher.matches()) {
+ return stringValueWithQuotesMatcher.group(1);
+ }
+ final Matcher integerValueMatcher = LEAF_INTEGER_VALUE_PATTERN.matcher(leafValueString);
+ if (integerValueMatcher.matches()) {
+ return Integer.valueOf(leafValueString);
+ }
+ throw new CpsPathException("Unsupported leaf value.",
+ String.format("Unsupported leaf value %s in cps path.", leafValueString));
+ }
+}
diff --git a/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepository.java b/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepository.java
index bf551723f8..a40168a9d6 100755
--- a/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepository.java
+++ b/cps-ri/src/main/java/org/onap/cps/spi/repository/FragmentRepository.java
@@ -22,6 +22,7 @@
package org.onap.cps.spi.repository;
import java.util.Collection;
+import java.util.List;
import java.util.Optional;
import javax.validation.constraints.NotNull;
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -51,4 +52,12 @@ public interface FragmentRepository extends JpaRepository<FragmentEntity, Long>
@Query("DELETE FROM FragmentEntity fe WHERE fe.anchor IN (:anchors)")
void deleteByAnchorIn(@NotNull @Param("anchors") Collection<AnchorEntity> anchorEntities);
+ @Query(value =
+ "SELECT * FROM FRAGMENT WHERE (anchor_id = :anchor) AND (xpath = (:xpath) OR xpath LIKE "
+ + "CONCAT(:xpath,'\\[@%]')) AND attributes @> jsonb_build_object(:leafName , :leafValue)",
+ nativeQuery = true)
+ // Above query will match an xpath with or without the index for a list [@key=value]
+ // and match anchor id, leaf name and leaf value
+ List<FragmentEntity> getByAnchorAndXpathAndLeafAttributes(@Param("anchor") int anchorId, @Param("xpath")
+ String xpathPrefix, @Param("leafName") String leafName, @Param("leafValue") Object leafValue);
} \ No newline at end of file