Get Node API fix for attribute values with '/'
[cps.git] / cps-ri / src / main / java / org / onap / cps / spi / repository / FragmentRepositoryCpsPathQueryImpl.java
index 3720249..4489cdd 100644 (file)
 
 package org.onap.cps.spi.repository;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import javax.persistence.EntityManager;
 import javax.persistence.PersistenceContext;
 import javax.persistence.Query;
+import javax.transaction.Transactional;
 import lombok.RequiredArgsConstructor;
 import org.onap.cps.cpspath.parser.CpsPathPrefixType;
 import org.onap.cps.cpspath.parser.CpsPathQuery;
@@ -35,20 +37,21 @@ import org.onap.cps.utils.JsonObjectMapper;
 @RequiredArgsConstructor
 public class FragmentRepositoryCpsPathQueryImpl implements FragmentRepositoryCpsPathQuery {
 
-    public static final String SIMILAR_TO_ABSOLUTE_PATH_PREFIX = "%/";
-    public static final String SIMILAR_TO_OPTIONAL_LIST_INDEX_POSTFIX = "(\\[[^/]*])?";
+    public static final String REGEX_ABSOLUTE_PATH_PREFIX = ".*\\/";
+    public static final String REGEX_OPTIONAL_LIST_INDEX_POSTFIX = "(\\[@(?!.*\\[).*?])?$";
 
     @PersistenceContext
     private EntityManager entityManager;
     private final JsonObjectMapper jsonObjectMapper;
 
     @Override
+    @Transactional
     public List<FragmentEntity> findByAnchorAndCpsPath(final int anchorId, final CpsPathQuery cpsPathQuery) {
-        final var sqlStringBuilder = new StringBuilder("SELECT * FROM FRAGMENT WHERE anchor_id = :anchorId");
+        final StringBuilder sqlStringBuilder = new StringBuilder("SELECT * FROM FRAGMENT WHERE anchor_id = :anchorId");
         final Map<String, Object> queryParameters = new HashMap<>();
         queryParameters.put("anchorId", anchorId);
-        sqlStringBuilder.append(" AND xpath SIMILAR TO :xpathRegex");
-        final String xpathRegex = getSimilarToXpathSqlRegex(cpsPathQuery);
+        sqlStringBuilder.append(" AND xpath ~ :xpathRegex");
+        final String xpathRegex = getXpathSqlRegex(cpsPathQuery);
         queryParameters.put("xpathRegex", xpathRegex);
         if (cpsPathQuery.hasLeafConditions()) {
             sqlStringBuilder.append(" AND attributes @> :leafDataAsJson\\:\\:jsonb");
@@ -57,20 +60,30 @@ public class FragmentRepositoryCpsPathQueryImpl implements FragmentRepositoryCps
         }
 
         addTextFunctionCondition(cpsPathQuery, sqlStringBuilder, queryParameters);
-        final var query = entityManager.createNativeQuery(sqlStringBuilder.toString(), FragmentEntity.class);
+        final Query query = entityManager.createNativeQuery(sqlStringBuilder.toString(), FragmentEntity.class);
         setQueryParameters(query, queryParameters);
-        return query.getResultList();
+        return getFragmentEntitiesAsStream(query);
     }
 
-    private static String getSimilarToXpathSqlRegex(final CpsPathQuery cpsPathQuery) {
-        final var xpathRegexBuilder = new StringBuilder();
+    private List<FragmentEntity> getFragmentEntitiesAsStream(final Query query) {
+        final List<FragmentEntity> fragmentEntities = new ArrayList<>();
+        query.getResultStream().forEach(fragmentEntity -> {
+            fragmentEntities.add((FragmentEntity) fragmentEntity);
+            entityManager.detach(fragmentEntity);
+        });
+
+        return fragmentEntities;
+    }
+
+    private static String getXpathSqlRegex(final CpsPathQuery cpsPathQuery) {
+        final StringBuilder xpathRegexBuilder = new StringBuilder();
         if (CpsPathPrefixType.ABSOLUTE.equals(cpsPathQuery.getCpsPathPrefixType())) {
             xpathRegexBuilder.append(escapeXpath(cpsPathQuery.getXpathPrefix()));
         } else {
-            xpathRegexBuilder.append(SIMILAR_TO_ABSOLUTE_PATH_PREFIX);
+            xpathRegexBuilder.append(REGEX_ABSOLUTE_PATH_PREFIX);
             xpathRegexBuilder.append(escapeXpath(cpsPathQuery.getDescendantName()));
         }
-        xpathRegexBuilder.append(SIMILAR_TO_OPTIONAL_LIST_INDEX_POSTFIX);
+        xpathRegexBuilder.append(REGEX_OPTIONAL_LIST_INDEX_POSTFIX);
         return xpathRegexBuilder.toString();
     }
 
@@ -96,7 +109,7 @@ public class FragmentRepositoryCpsPathQueryImpl implements FragmentRepositoryCps
                 .append(" OR attributes @> jsonb_build_object(:textLeafName, json_build_array(:textValue))");
             queryParameters.put("textLeafName", cpsPathQuery.getTextFunctionConditionLeafName());
             queryParameters.put("textValue", cpsPathQuery.getTextFunctionConditionValue());
-            final var textValueAsInt = getTextValueAsInt(cpsPathQuery);
+            final Integer textValueAsInt = getTextValueAsInt(cpsPathQuery);
             if (textValueAsInt != null) {
                 sqlStringBuilder.append(" OR attributes @> jsonb_build_object(:textLeafName, :textValueAsInt)");
                 sqlStringBuilder