import org.onap.cps.spi.entities.FragmentEntity;
import org.onap.cps.spi.exceptions.CpsPathException;
import org.onap.cps.spi.utils.EscapeUtils;
-import org.onap.cps.utils.JsonObjectMapper;
import org.springframework.stereotype.Component;
@RequiredArgsConstructor
@Slf4j
@Component
public class FragmentQueryBuilder {
- 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 AnchorEntity ACROSS_ALL_ANCHORS = null;
@PersistenceContext
private EntityManager entityManager;
- private final JsonObjectMapper jsonObjectMapper;
-
/**
* Create a sql query to retrieve by anchor(id) and cps path.
*
return getQueryForDataspaceOrAnchorAndCpsPath(dataspaceEntity, ACROSS_ALL_ANCHORS, cpsPathQuery);
}
- private static String getXpathSqlRegex(final CpsPathQuery cpsPathQuery) {
- final StringBuilder xpathRegexBuilder = getRegexStringBuilderWithPrefix(cpsPathQuery);
- xpathRegexBuilder.append(REGEX_OPTIONAL_LIST_INDEX_POSTFIX);
- return xpathRegexBuilder.toString();
- }
-
private Query getQueryForDataspaceOrAnchorAndCpsPath(final DataspaceEntity dataspaceEntity,
final AnchorEntity anchorEntity,
final CpsPathQuery cpsPathQuery) {
private static void addXpathSearch(final CpsPathQuery cpsPathQuery,
final StringBuilder sqlStringBuilder,
final Map<String, Object> queryParameters) {
- sqlStringBuilder.append(" AND xpath ~ :xpathRegex");
- final String xpathRegex = getXpathSqlRegex(cpsPathQuery);
- queryParameters.put("xpathRegex", xpathRegex);
- }
-
- private static StringBuilder getRegexStringBuilderWithPrefix(final CpsPathQuery cpsPathQuery) {
- final StringBuilder xpathRegexBuilder = new StringBuilder();
+ sqlStringBuilder.append(" AND (xpath LIKE :escapedXpath OR "
+ + "(xpath LIKE :escapedXpath||'[@%]' AND xpath NOT LIKE :escapedXpath||'[@%]/%[@%]'))");
if (CpsPathPrefixType.ABSOLUTE.equals(cpsPathQuery.getCpsPathPrefixType())) {
- xpathRegexBuilder.append(REGEX_ABSOLUTE_PATH_PREFIX);
- xpathRegexBuilder.append(escapeXpath(cpsPathQuery.getXpathPrefix()));
- return xpathRegexBuilder;
+ queryParameters.put("escapedXpath", EscapeUtils.escapeForSqlLike(cpsPathQuery.getXpathPrefix()));
+ } else {
+ queryParameters.put("escapedXpath", "%/" + EscapeUtils.escapeForSqlLike(cpsPathQuery.getDescendantName()));
}
- xpathRegexBuilder.append(REGEX_DESCENDANT_PATH_PREFIX);
- xpathRegexBuilder.append(escapeXpath(cpsPathQuery.getDescendantName()));
- return xpathRegexBuilder;
- }
-
- private static String escapeXpath(final String xpath) {
- // See https://jira.onap.org/browse/CPS-500 for limitations of this basic escape mechanism
- return xpath.replace("[@", "\\[@");
}
private static Integer getTextValueAsInt(final CpsPathQuery cpsPathQuery) {
sqlStringBuilder.append(" AND (");
final Queue<String> booleanOperatorsQueue = new LinkedList<>(cpsPathQuery.getBooleanOperators());
final Queue<String> comparativeOperatorQueue = new LinkedList<>(cpsPathQuery.getComparativeOperators());
- cpsPathQuery.getLeavesData().entrySet().forEach(entry -> {
+ cpsPathQuery.getLeavesData().forEach(leaf -> {
final String nextComparativeOperator = comparativeOperatorQueue.poll();
- if (entry.getValue() instanceof Integer) {
- sqlStringBuilder.append("(attributes ->> ");
- sqlStringBuilder.append("'").append(entry.getKey()).append("')\\:\\:int");
- sqlStringBuilder.append(" ").append(nextComparativeOperator).append(" ");
- sqlStringBuilder.append("'").append(jsonObjectMapper.asJsonString(entry.getValue())).append("'");
+ if (leaf.getValue() instanceof Integer) {
+ sqlStringBuilder.append("(attributes ->> '").append(leaf.getName()).append("')\\:\\:int");
+ sqlStringBuilder.append(nextComparativeOperator);
+ sqlStringBuilder.append(leaf.getValue());
} else {
if ("=".equals(nextComparativeOperator)) {
- sqlStringBuilder.append(" attributes @> ");
- sqlStringBuilder.append("'");
- sqlStringBuilder.append(jsonObjectMapper.asJsonString(entry));
+ final String leafValueAsText = leaf.getValue().toString();
+ sqlStringBuilder.append("attributes ->> '").append(leaf.getName()).append("'");
+ sqlStringBuilder.append(" = '");
+ sqlStringBuilder.append(EscapeUtils.escapeForSqlStringLiteral(leafValueAsText));
sqlStringBuilder.append("'");
} else {
throw new CpsPathException(" can use only " + nextComparativeOperator + " with integer ");