/*-
* ============LICENSE_START=======================================================
- * Copyright (C) 2021 Nordix Foundation.
+ * Copyright (C) 2021-2023 Nordix Foundation.
+ * Modifications Copyright (C) 2023 TechMahindra Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
package org.onap.cps.spi.repository;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-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 org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.onap.cps.cpspath.parser.CpsPathPrefixType;
+import javax.transaction.Transactional;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
import org.onap.cps.cpspath.parser.CpsPathQuery;
+import org.onap.cps.spi.PaginationOption;
+import org.onap.cps.spi.entities.AnchorEntity;
+import org.onap.cps.spi.entities.DataspaceEntity;
import org.onap.cps.spi.entities.FragmentEntity;
+@RequiredArgsConstructor
+@Slf4j
public class FragmentRepositoryCpsPathQueryImpl implements FragmentRepositoryCpsPathQuery {
- public static final String SIMILAR_TO_ABSOLUTE_PATH_PREFIX = "%/";
- public static final String SIMILAR_TO_OPTIONAL_LIST_INDEX_POSTFIX = "(\\[[^/]*])?";
-
@PersistenceContext
private EntityManager entityManager;
- private static final Gson GSON = new GsonBuilder().create();
+ private final FragmentQueryBuilder fragmentQueryBuilder;
@Override
- public List<FragmentEntity> findByAnchorAndCpsPath(final int anchorId, final CpsPathQuery cpsPathQuery) {
- final var 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);
- queryParameters.put("xpathRegex", xpathRegex);
- if (cpsPathQuery.hasLeafConditions()) {
- sqlStringBuilder.append(" AND attributes @> :leafDataAsJson\\:\\:jsonb");
- queryParameters.put("leafDataAsJson", GSON.toJson(cpsPathQuery.getLeavesData()));
- }
-
- addTextFunctionCondition(cpsPathQuery, sqlStringBuilder, queryParameters);
- final var query = entityManager.createNativeQuery(sqlStringBuilder.toString(), FragmentEntity.class);
- setQueryParameters(query, queryParameters);
- return query.getResultList();
- }
-
- @NotNull
- private static String getSimilarToXpathSqlRegex(final CpsPathQuery cpsPathQuery) {
- final var xpathRegexBuilder = new StringBuilder();
- if (CpsPathPrefixType.ABSOLUTE.equals(cpsPathQuery.getCpsPathPrefixType())) {
- xpathRegexBuilder.append(escapeXpath(cpsPathQuery.getXpathPrefix()));
- } else {
- xpathRegexBuilder.append(SIMILAR_TO_ABSOLUTE_PATH_PREFIX);
- xpathRegexBuilder.append(escapeXpath(cpsPathQuery.getDescendantName()));
- }
- xpathRegexBuilder.append(SIMILAR_TO_OPTIONAL_LIST_INDEX_POSTFIX);
- return xpathRegexBuilder.toString();
- }
-
- @NotNull
- 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("[@", "\\[@");
- }
-
- @Nullable
- private static Integer getTextValueAsInt(final CpsPathQuery cpsPathQuery) {
- try {
- return Integer.parseInt(cpsPathQuery.getTextFunctionConditionValue());
- } catch (final NumberFormatException e) {
- return null;
- }
+ @Transactional
+ public List<FragmentEntity> findByAnchorAndCpsPath(final AnchorEntity anchorEntity,
+ final CpsPathQuery cpsPathQuery) {
+ final Query query = fragmentQueryBuilder.getQueryForAnchorAndCpsPath(anchorEntity, cpsPathQuery);
+ final List<FragmentEntity> fragmentEntities = query.getResultList();
+ log.debug("Fetched {} fragment entities by anchor and cps path.", fragmentEntities.size());
+ return fragmentEntities;
}
- private static void addTextFunctionCondition(final CpsPathQuery cpsPathQuery, final StringBuilder sqlStringBuilder,
- final Map<String, Object> queryParameters) {
- if (cpsPathQuery.hasTextFunctionCondition()) {
- sqlStringBuilder.append(" AND (");
- sqlStringBuilder.append("attributes @> jsonb_build_object(:textLeafName, :textValue)");
- sqlStringBuilder
- .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);
- if (textValueAsInt != null) {
- sqlStringBuilder.append(" OR attributes @> jsonb_build_object(:textLeafName, :textValueAsInt)");
- sqlStringBuilder
- .append(" OR attributes @> jsonb_build_object(:textLeafName, json_build_array(:textValueAsInt))");
- queryParameters.put("textValueAsInt", textValueAsInt);
- }
- sqlStringBuilder.append(")");
- }
+ @Override
+ @Transactional
+ public List<FragmentEntity> findByDataspaceAndCpsPath(final DataspaceEntity dataspaceEntity,
+ final CpsPathQuery cpsPathQuery, final List<Long> anchorIds) {
+ final Query query = fragmentQueryBuilder.getQueryForDataspaceAndCpsPath(
+ dataspaceEntity, cpsPathQuery, anchorIds);
+ final List<FragmentEntity> fragmentEntities = query.getResultList();
+ log.debug("Fetched {} fragment entities by cps path across all anchors.", fragmentEntities.size());
+ return fragmentEntities;
}
- 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());
- }
+ @Override
+ @Transactional
+ public List<Long> findAnchorIdsForPagination(final DataspaceEntity dataspaceEntity, final CpsPathQuery cpsPathQuery,
+ final PaginationOption paginationOption) {
+ final Query query = fragmentQueryBuilder.getQueryForAnchorIdsForPagination(
+ dataspaceEntity, cpsPathQuery, paginationOption);
+ return query.getResultList();
}
}