diff options
Diffstat (limited to 'cps-ri/src/main/java/org')
3 files changed, 73 insertions, 25 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 48f1de710d..ab135fd3ae 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 @@ -28,9 +28,11 @@ import com.google.common.collect.ImmutableSet.Builder; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.regex.Pattern; import java.util.stream.Collectors; import org.onap.cps.spi.CpsDataPersistenceService; import org.onap.cps.spi.FetchDescendantsOption; @@ -62,6 +64,7 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService private FragmentRepository fragmentRepository; private static final Gson GSON = new GsonBuilder().create(); + private static final String REG_EX_FOR_OPTIONAL_LIST_INDEX = "(\\[@\\S+?]){0,1})"; @Override public void addChildDataNode(final String dataspaceName, final String anchorName, final String parentXpath, @@ -82,7 +85,7 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService try { fragmentRepository.save(fragmentEntity); } catch (final DataIntegrityViolationException exception) { - throw AlreadyDefinedException.forDataNode(dataNode.getXpath(), anchorName, exception); + throw AlreadyDefinedException.forDataNode(dataNode.getXpath(), anchorName, exception); } } @@ -144,7 +147,7 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService final var dataspaceEntity = dataspaceRepository.getByName(dataspaceName); final var anchorEntity = anchorRepository.getByDataspaceAndName(dataspaceEntity, anchorName); final var cpsPathQuery = CpsPathQuery.createFrom(cpsPath); - final List<FragmentEntity> fragmentEntities; + List<FragmentEntity> fragmentEntities; if (CpsPathQueryType.XPATH_LEAF_VALUE.equals(cpsPathQuery.getCpsPathQueryType())) { fragmentEntities = fragmentRepository .getByAnchorAndXpathAndLeafAttributes(anchorEntity.getId(), cpsPathQuery.getXpathPrefix(), @@ -158,11 +161,31 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService fragmentEntities = fragmentRepository .getByAnchorAndXpathEndsInDescendantName(anchorEntity.getId(), cpsPathQuery.getDescendantName()); } + if (cpsPathQuery.hasAncestorAxis()) { + final Set<String> ancestorXpaths = processAncestorXpath(fragmentEntities, cpsPathQuery); + fragmentEntities = ancestorXpaths.isEmpty() + ? Collections.emptyList() : fragmentRepository.findAllByAnchorAndXpathIn(anchorEntity, ancestorXpaths); + } return fragmentEntities.stream() .map(fragmentEntity -> toDataNode(fragmentEntity, fetchDescendantsOption)) .collect(Collectors.toUnmodifiableList()); } + private static Set<String> processAncestorXpath(final List<FragmentEntity> fragmentEntities, + final CpsPathQuery cpsPathQuery) { + final Set<String> ancestorXpath = new HashSet<>(); + final var pattern = + Pattern.compile("(\\S*\\/" + cpsPathQuery.getAncestorSchemaNodeIdentifier() + REG_EX_FOR_OPTIONAL_LIST_INDEX + + "\\/\\S*"); + for (final FragmentEntity fragmentEntity : fragmentEntities) { + final var matcher = pattern.matcher(fragmentEntity.getXpath()); + if (matcher.matches()) { + ancestorXpath.add(matcher.group(1)); + } + } + return ancestorXpath; + } + 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 index 6f53e0013d..f48d16590e 100644 --- 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 @@ -20,6 +20,8 @@ package org.onap.cps.spi.query; +import static org.springframework.util.StringUtils.isEmpty; + import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; @@ -39,6 +41,7 @@ public class CpsPathQuery { private Object leafValue; private String descendantName; private Map<String, Object> leavesData; + private String ancestorSchemaNodeIdentifier; private static final String NON_CAPTURING_GROUP_1_TO_99_YANG_CONTAINERS = "((?:\\/[^\\/]+){1,99})"; @@ -48,14 +51,14 @@ public class CpsPathQuery { private static final Pattern QUERY_CPS_PATH_WITH_SINGLE_LEAF_PATTERN = Pattern.compile(NON_CAPTURING_GROUP_1_TO_99_YANG_CONTAINERS + YANG_LEAF_VALUE_EQUALS_CONDITION); - private static final Pattern DESCENDANT_ANYWHERE_PATTERN = Pattern.compile("\\/\\/([^\\/].+)"); + private static final Pattern DESCENDANT_ANYWHERE_PATTERN = Pattern.compile("\\/\\/([^\\/][^:]+)"); private static final Pattern LEAF_INTEGER_VALUE_PATTERN = Pattern.compile("[-+]?\\d+"); private static final Pattern LEAF_STRING_VALUE_IN_SINGLE_QUOTES_PATTERN = Pattern.compile("'(.*)'"); private static final Pattern LEAF_STRING_VALUE_IN_DOUBLE_QUOTES_PATTERN = Pattern.compile("\"(.*)\""); - private static final String YANG_MULTIPLE_LEAF_VALUE_EQUALS_CONDITION = "\\[(.*?)\\s{0,9}]"; + private static final String YANG_MULTIPLE_LEAF_VALUE_EQUALS_CONDITION = "\\[(.*?)\\s{0,9}]"; private static final Pattern DESCENDANT_ANYWHERE_PATTERN_WITH_MULTIPLE_LEAF_PATTERN = Pattern.compile(DESCENDANT_ANYWHERE_PATTERN + YANG_MULTIPLE_LEAF_VALUE_EQUALS_CONDITION); @@ -64,45 +67,60 @@ public class CpsPathQuery { private static final Pattern LEAF_VALUE_PATTERN = Pattern.compile("@(\\S+?)=(.*)"); + private static final Pattern ANCESTOR_AXIS_PATTERN = Pattern.compile("(\\S+)\\/ancestor::\\/?(\\S+)"); + /** * Returns a cps path query. * - * @param cpsPath cps path + * @param cpsPathSource cps path * @return a CpsPath object. */ - public static CpsPathQuery createFrom(final String cpsPath) { - var matcher = QUERY_CPS_PATH_WITH_SINGLE_LEAF_PATTERN.matcher(cpsPath); - final var cpsPathQuery = new CpsPathQuery(); + public static CpsPathQuery createFrom(final String cpsPathSource) { + var cpsPath = cpsPathSource; + final CpsPathQuery cpsPathQuery = new CpsPathQuery(); + var matcher = ANCESTOR_AXIS_PATTERN.matcher(cpsPath); if (matcher.matches()) { - return buildCpsPathQueryWithSingleLeafPattern(cpsPath, matcher, cpsPathQuery); + cpsPath = matcher.group(1); + cpsPathQuery.setAncestorSchemaNodeIdentifier(matcher.group(2)); + } + matcher = QUERY_CPS_PATH_WITH_SINGLE_LEAF_PATTERN.matcher(cpsPath); + if (matcher.matches()) { + cpsPathQuery.setParametersForSingleLeafValue(cpsPath, matcher); + return cpsPathQuery; } matcher = DESCENDANT_ANYWHERE_PATTERN_WITH_MULTIPLE_LEAF_PATTERN.matcher(cpsPath); if (matcher.matches()) { - return buildCpsQueryForDescendentWithLeafPattern(cpsPath, matcher, cpsPathQuery); + cpsPathQuery.setParametersForDescendantWithLeafValues(cpsPath, matcher); + return cpsPathQuery; } matcher = DESCENDANT_ANYWHERE_PATTERN.matcher(cpsPath); if (matcher.matches()) { - cpsPathQuery.setCpsPathQueryType(CpsPathQueryType.XPATH_HAS_DESCENDANT_ANYWHERE); - cpsPathQuery.setDescendantName(matcher.group(1)); + cpsPathQuery.setParametersForDescendantAnywhere(matcher); return cpsPathQuery; } throw new CpsPathException("Invalid cps path.", String.format("Cannot interpret or parse cps path '%s'.", cpsPath)); } - private static CpsPathQuery buildCpsPathQueryWithSingleLeafPattern(final String cpsPath, final Matcher matcher, - final CpsPathQuery cpsPathQuery) { - cpsPathQuery.setCpsPathQueryType(CpsPathQueryType.XPATH_LEAF_VALUE); - cpsPathQuery.setXpathPrefix(matcher.group(1)); - cpsPathQuery.setLeafName(matcher.group(2)); - cpsPathQuery.setLeafValue(convertLeafValueToCorrectType(matcher.group(3), cpsPath)); - return cpsPathQuery; + /** + * Has ancestor axis been populated. + * + * @return boolean value. + */ + public boolean hasAncestorAxis() { + return !(isEmpty(ancestorSchemaNodeIdentifier)); + } + + private void setParametersForSingleLeafValue(final String cpsPath, final Matcher matcher) { + setCpsPathQueryType(CpsPathQueryType.XPATH_LEAF_VALUE); + setXpathPrefix(matcher.group(1)); + setLeafName(matcher.group(2)); + setLeafValue(convertLeafValueToCorrectType(matcher.group(3), cpsPath)); } - private static CpsPathQuery buildCpsQueryForDescendentWithLeafPattern(final String cpsPath, final Matcher matcher, - final CpsPathQuery cpsPathQuery) { - cpsPathQuery.setCpsPathQueryType(CpsPathQueryType.XPATH_HAS_DESCENDANT_WITH_LEAF_VALUES); - cpsPathQuery.setDescendantName(matcher.group(1)); + private void setParametersForDescendantWithLeafValues(final String cpsPath, final Matcher matcher) { + setCpsPathQueryType(CpsPathQueryType.XPATH_HAS_DESCENDANT_WITH_LEAF_VALUES); + setDescendantName(matcher.group(1)); final Map<String, Object> leafData = new HashMap<>(); for (final String leafValuePair : matcher.group(2).split(INDIVIDUAL_LEAF_DETAIL_PATTERN)) { final var descendentMatcher = LEAF_VALUE_PATTERN.matcher(leafValuePair); @@ -114,8 +132,12 @@ public class CpsPathQuery { String.format("Cannot interpret or parse attributes in cps path '%s'.", cpsPath)); } } - cpsPathQuery.setLeavesData(leafData); - return cpsPathQuery; + setLeavesData(leafData); + } + + private void setParametersForDescendantAnywhere(final Matcher matcher) { + setCpsPathQueryType(CpsPathQueryType.XPATH_HAS_DESCENDANT_ANYWHERE); + setDescendantName(matcher.group(1)); } private static Object convertLeafValueToCorrectType(final String leafValueString, final String cpsPath) { 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 b9874484c0..c484ae9e87 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 @@ -57,6 +57,9 @@ public interface FragmentRepository extends JpaRepository<FragmentEntity, Long> .orElseThrow(() -> new DataNodeNotFoundException(dataspaceEntity.getName(), anchorEntity.getName()));
}
+ List<FragmentEntity> findAllByAnchorAndXpathIn(@NonNull AnchorEntity anchorEntity,
+ @NonNull Collection<String> xpath);
+
@Modifying
@Query("DELETE FROM FragmentEntity fe WHERE fe.anchor IN (:anchors)")
void deleteByAnchorIn(@NotNull @Param("anchors") Collection<AnchorEntity> anchorEntities);
|