package org.onap.cps.spi.repository;
import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
import java.util.Map;
+import java.util.Queue;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
@Slf4j
@Component
public class FragmentQueryBuilder {
- private static final String REGEX_ABSOLUTE_PATH_PREFIX = ".*\\/";
- private static final String REGEX_OPTIONAL_LIST_INDEX_POSTFIX = "(\\[@(?!.*\\[).*?])?";
- private static final String REGEX_DESCENDANT_PATH_POSTFIX = "(\\/.*)?";
- private static final String REGEX_END_OF_INPUT = "$";
+ private static final String REGEX_ABSOLUTE_PATH_PREFIX = "^";
+ private static final String REGEX_DESCENDANT_PATH_PREFIX = "^.*\\/";
+ private static final String REGEX_OPTIONAL_LIST_INDEX_POSTFIX = "(\\[@(?!.*\\[).*?])?$";
+ private static final String REGEX_FOR_QUICK_FIND_WITH_DESCENDANTS = "(\\[@.*?])?(\\/.*)?$";
@PersistenceContext
private EntityManager entityManager;
final Map<String, Object> queryParameters = new HashMap<>();
queryParameters.put("anchorId", anchorId);
sqlStringBuilder.append(" AND xpath ~ :xpathRegex");
- final String xpathRegex = getXpathSqlRegex(cpsPathQuery, false);
- queryParameters.put("xpathRegex", xpathRegex);
- if (cpsPathQuery.hasLeafConditions()) {
- sqlStringBuilder.append(" AND attributes @> :leafDataAsJson\\:\\:jsonb");
- queryParameters.put("leafDataAsJson", jsonObjectMapper.asJsonString(
- cpsPathQuery.getLeavesData()));
- }
-
- addTextFunctionCondition(cpsPathQuery, sqlStringBuilder, queryParameters);
- final Query query = entityManager.createNativeQuery(sqlStringBuilder.toString(), FragmentEntity.class);
- setQueryParameters(query, queryParameters);
- return query;
+ return getQuery(cpsPathQuery, sqlStringBuilder, queryParameters);
}
/**
public Query getQueryForCpsPath(final CpsPathQuery cpsPathQuery) {
final StringBuilder sqlStringBuilder = new StringBuilder("SELECT * FROM FRAGMENT WHERE xpath ~ :xpathRegex");
final Map<String, Object> queryParameters = new HashMap<>();
- final String xpathRegex = getXpathSqlRegex(cpsPathQuery, false);
+ return getQuery(cpsPathQuery, sqlStringBuilder, queryParameters);
+ }
+
+ /**
+ * Create a regular expression (string) for matching xpaths based on the given cps path query.
+ *
+ * @param cpsPathQuery the cps path query to determine the required regular expression
+ * @return a string representing the required regular expression
+ */
+ public static String getXpathSqlRegex(final CpsPathQuery cpsPathQuery) {
+ final StringBuilder xpathRegexBuilder = getRegexStringBuilderWithPrefix(cpsPathQuery);
+ xpathRegexBuilder.append(REGEX_OPTIONAL_LIST_INDEX_POSTFIX);
+ return xpathRegexBuilder.toString();
+ }
+
+ /**
+ * Create a regular expression (string) for matching xpaths with (all) descendants
+ * based on the given cps path query.
+ *
+ * @param cpsPathQuery the cps path query to determine the required regular expression
+ * @return a string representing the required regular expression
+ */
+ public static String getXpathSqlRegexForQuickFindWithDescendants(final CpsPathQuery cpsPathQuery) {
+ final StringBuilder xpathRegexBuilder = getRegexStringBuilderWithPrefix(cpsPathQuery);
+ xpathRegexBuilder.append(REGEX_FOR_QUICK_FIND_WITH_DESCENDANTS);
+ return xpathRegexBuilder.toString();
+ }
+
+ private Query getQuery(final CpsPathQuery cpsPathQuery, final StringBuilder sqlStringBuilder,
+ final Map<String, Object> queryParameters) {
+ final String xpathRegex = getXpathSqlRegex(cpsPathQuery);
queryParameters.put("xpathRegex", xpathRegex);
+ final List<String> queryBooleanOperatorsType = cpsPathQuery.getBooleanOperatorsType();
if (cpsPathQuery.hasLeafConditions()) {
- sqlStringBuilder.append(" AND attributes @> :leafDataAsJson\\:\\:jsonb");
- queryParameters.put("leafDataAsJson", jsonObjectMapper.asJsonString(
- cpsPathQuery.getLeavesData()));
+ sqlStringBuilder.append(" AND (");
+ final Queue<String> booleanOperatorsQueue = (queryBooleanOperatorsType == null) ? null : new LinkedList<>(
+ queryBooleanOperatorsType);
+ cpsPathQuery.getLeavesData().entrySet().forEach(entry -> {
+ sqlStringBuilder.append(" attributes @> ");
+ sqlStringBuilder.append("'" + jsonObjectMapper.asJsonString(entry) + "'");
+ if (!(booleanOperatorsQueue == null || booleanOperatorsQueue.isEmpty())) {
+ sqlStringBuilder.append(" " + booleanOperatorsQueue.poll() + " ");
+ }
+ });
+ sqlStringBuilder.append(")");
}
-
addTextFunctionCondition(cpsPathQuery, sqlStringBuilder, queryParameters);
+ addContainsFunctionCondition(cpsPathQuery, sqlStringBuilder, queryParameters);
final Query query = entityManager.createNativeQuery(sqlStringBuilder.toString(), FragmentEntity.class);
setQueryParameters(query, queryParameters);
return query;
}
- /**
- * Create a regular expression (string) for xpath based on the given cps path query.
- *
- * @param cpsPathQuery the cps path query to determine the required regular expression
- * @param includeDescendants include descendants yes or no
- * @return a string representing the required regular expression
- */
- public static String getXpathSqlRegex(final CpsPathQuery cpsPathQuery, final boolean includeDescendants) {
+ private static StringBuilder getRegexStringBuilderWithPrefix(final CpsPathQuery cpsPathQuery) {
final StringBuilder xpathRegexBuilder = new StringBuilder();
if (CpsPathPrefixType.ABSOLUTE.equals(cpsPathQuery.getCpsPathPrefixType())) {
- xpathRegexBuilder.append(escapeXpath(cpsPathQuery.getXpathPrefix()));
- } else {
xpathRegexBuilder.append(REGEX_ABSOLUTE_PATH_PREFIX);
- xpathRegexBuilder.append(escapeXpath(cpsPathQuery.getDescendantName()));
- }
- xpathRegexBuilder.append(REGEX_OPTIONAL_LIST_INDEX_POSTFIX);
- if (includeDescendants) {
- xpathRegexBuilder.append(REGEX_DESCENDANT_PATH_POSTFIX);
+ xpathRegexBuilder.append(escapeXpath(cpsPathQuery.getXpathPrefix()));
+ return xpathRegexBuilder;
}
- xpathRegexBuilder.append(REGEX_END_OF_INPUT);
- return xpathRegexBuilder.toString();
+ xpathRegexBuilder.append(REGEX_DESCENDANT_PATH_PREFIX);
+ xpathRegexBuilder.append(escapeXpath(cpsPathQuery.getDescendantName()));
+ return xpathRegexBuilder;
}
private static String escapeXpath(final String xpath) {
}
}
+ private static void addContainsFunctionCondition(final CpsPathQuery cpsPathQuery,
+ final StringBuilder sqlStringBuilder,
+ final Map<String, Object> queryParameters) {
+ if (cpsPathQuery.hasContainsFunctionCondition()) {
+ sqlStringBuilder.append(" AND attributes ->> :containsLeafName LIKE CONCAT('%',:containsValue,'%') ");
+ queryParameters.put("containsLeafName", cpsPathQuery.getContainsFunctionConditionLeafName());
+ queryParameters.put("containsValue", cpsPathQuery.getContainsFunctionConditionValue());
+ }
+ }
+
private static void setQueryParameters(final Query query, final Map<String, Object> queryParameters) {
for (final Map.Entry<String, Object> queryParameter : queryParameters.entrySet()) {
query.setParameter(queryParameter.getKey(), queryParameter.getValue());