X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=cps-ri%2Fsrc%2Fmain%2Fjava%2Forg%2Fonap%2Fcps%2Fspi%2Fimpl%2FCpsDataPersistenceServiceImpl.java;h=cca5d9c849ec6b6f9ab2ddeb7e04b9b202a46835;hb=1be9234c5234883be1e8d66baf7a780fa6be8ccf;hp=e3be0137d3fa8398d3984450c7e314f0b8f14aa3;hpb=b8b29c97ee64b395bceb1e100eaf2a6bf115871f;p=cps.git 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 e3be0137d..cca5d9c84 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 @@ -23,8 +23,10 @@ package org.onap.cps.spi.impl; +import com.google.common.base.Strings; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet.Builder; +import io.micrometer.core.annotation.Timed; import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; @@ -80,7 +82,9 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService private final JsonObjectMapper jsonObjectMapper; private final SessionManager sessionManager; - private static final String REG_EX_FOR_OPTIONAL_LIST_INDEX = "(\\[@[\\s\\S]+?])?)"; + private static final String REG_EX_FOR_OPTIONAL_LIST_INDEX = "(\\[@.+?])?)"; + private static final String QUERY_ACROSS_ANCHORS = null; + private static final AnchorEntity ALL_ANCHORS = null; @Override public void addChildDataNode(final String dataspaceName, final String anchorName, final String parentNodeXpath, @@ -166,11 +170,6 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService } } - @Override - public void storeDataNode(final String dataspaceName, final String anchorName, final DataNode dataNode) { - storeDataNodes(dataspaceName, anchorName, Collections.singletonList(dataNode)); - } - @Override public void storeDataNodes(final String dataspaceName, final String anchorName, final Collection dataNodes) { @@ -234,6 +233,8 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService } @Override + @Timed(value = "cps.data.persistence.service.datanode.get", + description = "Time taken to get a data node") public Collection getDataNodes(final String dataspaceName, final String anchorName, final String xpath, final FetchDescendantsOption fetchDescendantsOption) { @@ -247,16 +248,20 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService } @Override + @Timed(value = "cps.data.persistence.service.datanode.batch.get", + description = "Time taken to get data nodes") public Collection getDataNodesForMultipleXpaths(final String dataspaceName, final String anchorName, final Collection xpaths, final FetchDescendantsOption fetchDescendantsOption) { final AnchorEntity anchorEntity = getAnchorEntity(dataspaceName, anchorName); - final Collection fragmentEntities = getFragmentEntities(anchorEntity, xpaths); + final Collection fragmentEntities = + getFragmentEntities(anchorEntity, xpaths, fetchDescendantsOption); return toDataNodes(fragmentEntities, fetchDescendantsOption); } private Collection getFragmentEntities(final AnchorEntity anchorEntity, - final Collection xpaths) { + final Collection xpaths, + final FetchDescendantsOption fetchDescendantsOption) { final Collection nonRootXpaths = new HashSet<>(xpaths); final boolean haveRootXpath = nonRootXpaths.removeIf(CpsDataPersistenceServiceImpl::isRootXpath); @@ -268,15 +273,15 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService log.warn("Error parsing xpath \"{}\": {}", xpath, e.getMessage()); } } - final Collection fragmentEntities = - new HashSet<>(fragmentRepository.findByAnchorAndMultipleCpsPaths(anchorEntity.getId(), normalizedXpaths)); - if (haveRootXpath) { - final List fragmentExtracts = fragmentRepository.findAllExtractsByAnchor(anchorEntity); - fragmentEntities.addAll(FragmentEntityArranger.toFragmentEntityTrees(anchorEntity, fragmentExtracts)); + normalizedXpaths.addAll(fragmentRepository.findAllXpathByAnchorAndParentIdIsNull(anchorEntity)); } - return fragmentEntities; + final List fragmentExtracts = + fragmentRepository.findExtractsWithDescendants(anchorEntity.getId(), normalizedXpaths, + fetchDescendantsOption.getDepth()); + + return FragmentEntityArranger.toFragmentEntityTrees(anchorEntity, fragmentExtracts); } private FragmentEntity getFragmentEntity(final AnchorEntity anchorEntity, final String xpath) { @@ -302,9 +307,12 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService } @Override + @Timed(value = "cps.data.persistence.service.datanode.query", + description = "Time taken to query data nodes") public List queryDataNodes(final String dataspaceName, final String anchorName, final String cpsPath, final FetchDescendantsOption fetchDescendantsOption) { - final AnchorEntity anchorEntity = getAnchorEntity(dataspaceName, anchorName); + final AnchorEntity anchorEntity = (Strings.isNullOrEmpty(anchorName)) ? ALL_ANCHORS + : getAnchorEntity(dataspaceName, anchorName); final CpsPathQuery cpsPathQuery; try { cpsPathQuery = CpsPathUtil.getCpsPathQuery(cpsPath); @@ -316,40 +324,47 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService if (canUseRegexQuickFind(fetchDescendantsOption, cpsPathQuery)) { return getDataNodesUsingRegexQuickFind(fetchDescendantsOption, anchorEntity, cpsPathQuery); } - fragmentEntities = fragmentRepository.findByAnchorAndCpsPath(anchorEntity.getId(), cpsPathQuery); + fragmentEntities = (anchorEntity == ALL_ANCHORS) ? fragmentRepository.findByCpsPath(cpsPathQuery) + : fragmentRepository.findByAnchorAndCpsPath(anchorEntity.getId(), cpsPathQuery); if (cpsPathQuery.hasAncestorAxis()) { - fragmentEntities = getAncestorFragmentEntities(anchorEntity.getId(), cpsPathQuery, fragmentEntities); + final Collection ancestorXpaths = processAncestorXpath(fragmentEntities, cpsPathQuery); + fragmentEntities = (anchorEntity == ALL_ANCHORS) ? getAncestorFragmentEntitiesAcrossAnchors(cpsPathQuery, + fragmentEntities) : getFragmentEntities(anchorEntity, ancestorXpaths, fetchDescendantsOption); } return createDataNodesFromProxiedFragmentEntities(fetchDescendantsOption, anchorEntity, fragmentEntities); } + @Override + public List queryDataNodesAcrossAnchors(final String dataspaceName, final String cpsPath, + final FetchDescendantsOption fetchDescendantsOption) { + return queryDataNodes(dataspaceName, QUERY_ACROSS_ANCHORS, cpsPath, fetchDescendantsOption); + } + private static boolean canUseRegexQuickFind(final FetchDescendantsOption fetchDescendantsOption, final CpsPathQuery cpsPathQuery) { return fetchDescendantsOption.equals(FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS) + && !cpsPathQuery.hasAncestorAxis() && !cpsPathQuery.hasLeafConditions() - && !cpsPathQuery.hasTextFunctionCondition(); + && !cpsPathQuery.hasTextFunctionCondition() + && !cpsPathQuery.hasContainsFunctionCondition(); } private List getDataNodesUsingRegexQuickFind(final FetchDescendantsOption fetchDescendantsOption, final AnchorEntity anchorEntity, final CpsPathQuery cpsPathQuery) { - Collection fragmentEntities; - final String xpathRegex = FragmentQueryBuilder.getXpathSqlRegex(cpsPathQuery, true); - final List fragmentExtracts = - fragmentRepository.quickFindWithDescendants(anchorEntity.getId(), xpathRegex); - fragmentEntities = FragmentEntityArranger.toFragmentEntityTrees(anchorEntity, fragmentExtracts); - if (cpsPathQuery.hasAncestorAxis()) { - fragmentEntities = getAncestorFragmentEntities(anchorEntity.getId(), cpsPathQuery, fragmentEntities); - } + final String xpathRegex = FragmentQueryBuilder.getXpathSqlRegexForQuickFindWithDescendants(cpsPathQuery); + final List fragmentExtracts = (anchorEntity == ALL_ANCHORS) + ? fragmentRepository.quickFindWithDescendantsAcrossAnchors(xpathRegex) + : fragmentRepository.quickFindWithDescendants(anchorEntity.getId(), xpathRegex); + final Collection fragmentEntities = + FragmentEntityArranger.toFragmentEntityTrees(anchorEntity, fragmentExtracts); return createDataNodesFromFragmentEntities(fetchDescendantsOption, fragmentEntities); } - private Collection getAncestorFragmentEntities(final int anchorId, - final CpsPathQuery cpsPathQuery, - final Collection fragmentEntities) { + private Collection getAncestorFragmentEntitiesAcrossAnchors(final CpsPathQuery cpsPathQuery, + final Collection fragmentEntities) { final Collection ancestorXpaths = processAncestorXpath(fragmentEntities, cpsPathQuery); - return ancestorXpaths.isEmpty() ? Collections.emptyList() - : fragmentRepository.findByAnchorAndMultipleCpsPaths(anchorId, ancestorXpaths); + return ancestorXpaths.isEmpty() ? Collections.emptyList() : fragmentRepository.findAllByXpathIn(ancestorXpaths); } private List createDataNodesFromProxiedFragmentEntities( @@ -362,8 +377,10 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService dataNodes.add(toDataNode(proxiedFragmentEntity, fetchDescendantsOption)); } else { final String normalizedXpath = getNormalizedXpath(proxiedFragmentEntity.getXpath()); + final AnchorEntity anchorEntityForFragmentExtract = (anchorEntity == ALL_ANCHORS) + ? proxiedFragmentEntity.getAnchor() : anchorEntity; final Collection unproxiedFragmentEntities = - buildFragmentEntitiesFromFragmentExtracts(anchorEntity, normalizedXpath); + buildFragmentEntitiesFromFragmentExtracts(anchorEntityForFragmentExtract, normalizedXpath); for (final FragmentEntity unproxiedFragmentEntity : unproxiedFragmentEntities) { dataNodes.add(toDataNode(unproxiedFragmentEntity, fetchDescendantsOption)); } @@ -412,8 +429,8 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService final CpsPathQuery cpsPathQuery) { final Set ancestorXpath = new HashSet<>(); final Pattern pattern = - Pattern.compile("([\\s\\S]*/" + Pattern.quote(cpsPathQuery.getAncestorSchemaNodeIdentifier()) - + REG_EX_FOR_OPTIONAL_LIST_INDEX + "/[\\s\\S]*"); + Pattern.compile("(.*/" + Pattern.quote(cpsPathQuery.getAncestorSchemaNodeIdentifier()) + + REG_EX_FOR_OPTIONAL_LIST_INDEX + "/.*"); for (final FragmentEntity fragmentEntity : fragmentEntities) { final Matcher matcher = pattern.matcher(fragmentEntity.getXpath()); if (matcher.matches()) { @@ -433,6 +450,8 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService return new DataNodeBuilder() .withXpath(fragmentEntity.getXpath()) .withLeaves(leaves) + .withDataspace(fragmentEntity.getAnchor().getDataspace().getName()) + .withAnchor(fragmentEntity.getAnchor().getName()) .withChildDataNodes(childDataNodes).build(); } @@ -466,31 +485,17 @@ public class CpsDataPersistenceServiceImpl implements CpsDataPersistenceService fragmentRepository.save(fragmentEntity); } - @Override - public void updateDataNodeAndDescendants(final String dataspaceName, final String anchorName, - final DataNode dataNode) { - final AnchorEntity anchorEntity = getAnchorEntity(dataspaceName, anchorName); - final FragmentEntity fragmentEntity = getFragmentEntity(anchorEntity, dataNode.getXpath()); - updateFragmentEntityAndDescendantsWithDataNode(fragmentEntity, dataNode); - try { - fragmentRepository.save(fragmentEntity); - } catch (final StaleStateException staleStateException) { - throw new ConcurrencyException("Concurrent Transactions", - String.format("dataspace :'%s', Anchor : '%s' and xpath: '%s' is updated by another transaction.", - dataspaceName, anchorName, dataNode.getXpath())); - } - } - @Override public void updateDataNodesAndDescendants(final String dataspaceName, final String anchorName, - final List updatedDataNodes) { + final Collection updatedDataNodes) { final AnchorEntity anchorEntity = getAnchorEntity(dataspaceName, anchorName); final Map xpathToUpdatedDataNode = updatedDataNodes.stream() .collect(Collectors.toMap(DataNode::getXpath, dataNode -> dataNode)); final Collection xpaths = xpathToUpdatedDataNode.keySet(); - final Collection existingFragmentEntities = getFragmentEntities(anchorEntity, xpaths); + final Collection existingFragmentEntities = + getFragmentEntities(anchorEntity, xpaths, FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS); for (final FragmentEntity existingFragmentEntity : existingFragmentEntities) { final DataNode updatedDataNode = xpathToUpdatedDataNode.get(existingFragmentEntity.getXpath());