import com.google.common.collect.ImmutableSet.Builder;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
+import java.util.Collection;
import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.onap.cps.spi.CpsDataPersistenceService;
import org.onap.cps.spi.FetchDescendantsOption;
private FragmentRepository fragmentRepository;
private static final Gson GSON = new GsonBuilder().create();
+ private static final String REG_EX_FOR_OPTIONAL_LIST_INDEX = "(\\[@\\S+?]){0,1})";
@Override
public void addChildDataNode(final String dataspaceName, final String anchorName, final String parentXpath,
final var fragmentEntity =
toFragmentEntity(parentFragment.getDataspace(), parentFragment.getAnchor(), dataNode);
parentFragment.getChildFragments().add(fragmentEntity);
- fragmentRepository.save(parentFragment);
+ try {
+ fragmentRepository.save(parentFragment);
+ } catch (final DataIntegrityViolationException exception) {
+ throw AlreadyDefinedException.forDataNode(dataNode.getXpath(), anchorName, exception);
+ }
+ }
+
+ @Override
+ public void addListDataNodes(final String dataspaceName, final String anchorName, final String parentNodeXpath,
+ final Collection<DataNode> dataNodes) {
+ final FragmentEntity parentFragment = getFragmentByXpath(dataspaceName, anchorName, parentNodeXpath);
+ final List<FragmentEntity> newFragmentEntities =
+ dataNodes.stream().map(
+ dataNode -> toFragmentEntity(parentFragment.getDataspace(), parentFragment.getAnchor(), dataNode)
+ ).collect(Collectors.toUnmodifiableList());
+ parentFragment.getChildFragments().addAll(newFragmentEntities);
+ try {
+ fragmentRepository.save(parentFragment);
+ } catch (final DataIntegrityViolationException exception) {
+ final List<String> conflictXpaths = dataNodes.stream()
+ .map(DataNode::getXpath)
+ .collect(Collectors.toList());
+ throw AlreadyDefinedException.forDataNodes(conflictXpaths, anchorName, exception);
+ }
}
@Override
try {
fragmentRepository.save(fragmentEntity);
} catch (final DataIntegrityViolationException exception) {
- throw AlreadyDefinedException.forDataNode(dataNode.getXpath(), anchorName, exception);
+ throw AlreadyDefinedException.forDataNode(dataNode.getXpath(), anchorName, exception);
}
}
final var dataspaceEntity = dataspaceRepository.getByName(dataspaceName);
final var anchorEntity = anchorRepository.getByDataspaceAndName(dataspaceEntity, anchorName);
final var cpsPathQuery = CpsPathQuery.createFrom(cpsPath);
- final List<FragmentEntity> fragmentEntities;
+ List<FragmentEntity> fragmentEntities;
if (CpsPathQueryType.XPATH_LEAF_VALUE.equals(cpsPathQuery.getCpsPathQueryType())) {
fragmentEntities = fragmentRepository
.getByAnchorAndXpathAndLeafAttributes(anchorEntity.getId(), cpsPathQuery.getXpathPrefix(),
fragmentEntities = fragmentRepository
.getByAnchorAndXpathEndsInDescendantName(anchorEntity.getId(), cpsPathQuery.getDescendantName());
}
+ if (cpsPathQuery.hasAncestorAxis()) {
+ final Set<String> ancestorXpaths = processAncestorXpath(fragmentEntities, cpsPathQuery);
+ fragmentEntities = ancestorXpaths.isEmpty()
+ ? Collections.emptyList() : fragmentRepository.findAllByAnchorAndXpathIn(anchorEntity, ancestorXpaths);
+ }
return fragmentEntities.stream()
.map(fragmentEntity -> toDataNode(fragmentEntity, fetchDescendantsOption))
.collect(Collectors.toUnmodifiableList());
}
+ private static Set<String> processAncestorXpath(final List<FragmentEntity> fragmentEntities,
+ final CpsPathQuery cpsPathQuery) {
+ final Set<String> ancestorXpath = new HashSet<>();
+ final var pattern =
+ Pattern.compile("(\\S*\\/" + Pattern.quote(cpsPathQuery.getAncestorSchemaNodeIdentifier())
+ + REG_EX_FOR_OPTIONAL_LIST_INDEX + "\\/\\S*");
+ for (final FragmentEntity fragmentEntity : fragmentEntities) {
+ final var matcher = pattern.matcher(fragmentEntity.getXpath());
+ if (matcher.matches()) {
+ ancestorXpath.add(matcher.group(1));
+ }
+ }
+ return ancestorXpath;
+ }
+
private static DataNode toDataNode(final FragmentEntity fragmentEntity,
final FetchDescendantsOption fetchDescendantsOption) {
final Map<String, Object> leaves = GSON.fromJson(fragmentEntity.getAttributes(), Map.class);