Commit 8b08be56 authored by Devesh's avatar Devesh
Browse files

Add Copy Asterisk operation

parent c5216c5c
Pipeline #46860 failed with stages
in 44 seconds
......@@ -14,47 +14,55 @@ import org.springframework.util.StringUtils;
public class CopyOperationHandlerResolver {
public static final String ASTERISK = "[*]";
public static final String ASTERISK_IN_SQUARE_BRACKETS_EXP = "\\[\\*\\]\\.";
public static final String ASTERISK_IN_SQUARE_BRACKETS_EXP = "\\[\\*\\]";
public static final String HASH = "[#]";
Predicate<String> isAsteriskInPath = path -> (path.contains(ASTERISK));
Predicate<String> isHashInPath = path -> (path.contains(HASH));
Predicate<String> isOnlyOneAsteriskInPath = path -> (StringUtils.countOccurrencesOf(path, ASTERISK) == 1);
Predicate<String> ifOnlyOneHashInPath = path -> (StringUtils.countOccurrencesOf(path, HASH) == 1);
Predicate<String> isAsteriskAndHashBothInPath = path -> isAsteriskInPath.and(isHashInPath).test(path);
Predicate<String> isAsteriskOrHashInPath = path -> isAsteriskInPath.or(isHashInPath).test(path);
private boolean isPathExpressionSupported(String sourcePath, String targetPath) {
if (isHashInSourceAndAsteriskInTarget(sourcePath, targetPath) || isHashInTargetAndAsteriskInSource(sourcePath,
targetPath)
|| (isHashInPath.test(sourcePath) && isHashInPath.test(targetPath))) {
return false;
}
if (isAsteriskAndHashBothInPath.test(sourcePath) || isAsteriskAndHashBothInPath.test(targetPath)) {
Predicate<String> asteriskInPath = path -> (path.contains(ASTERISK));
Predicate<String> hashInPath = path -> (path.contains(HASH));
Predicate<String> OnlyOneAsteriskInPath = path -> (StringUtils.countOccurrencesOf(path, ASTERISK) == 1);
Predicate<String> onlyOneHashInPath = path -> (StringUtils.countOccurrencesOf(path, HASH) == 1);
Predicate<String> asteriskAndHashBothInPath = path -> asteriskInPath.and(hashInPath).test(path);
Predicate<String> asteriskOrHashInPath = path -> asteriskInPath.or(hashInPath).test(path);
private boolean pathExpressionSupported(String sourcePath, String targetPath) {
if (hashInSourceAndAsteriskInTarget(sourcePath, targetPath)
|| hashInTargetAndAsteriskInSource(sourcePath,targetPath)
|| hashInBothSourceAndTarget(sourcePath, targetPath)
|| asteriskAndHashBothInPath.test(sourcePath)
|| asteriskAndHashBothInPath.test(targetPath)
) {
return false;
}
return true;
}
private boolean isHashInTargetAndAsteriskInSource(String sourcePath, String targetPath) {
return isHashInPath.test(targetPath) && isAsteriskInPath.test(sourcePath);
private boolean hashInBothSourceAndTarget(String sourcePath, String targetPath) {
return hashInPath.test(sourcePath) && hashInPath.test(targetPath);
}
private boolean isHashInSourceAndAsteriskInTarget(String sourcePath, String targetPath) {
return isHashInPath.test(sourcePath) && isAsteriskInPath.test(targetPath);
private boolean hashInTargetAndAsteriskInSource(String sourcePath, String targetPath) {
return hashInPath.test(targetPath) && asteriskInPath.test(sourcePath);
}
private boolean hashInSourceAndAsteriskInTarget(String sourcePath, String targetPath) {
return hashInPath.test(sourcePath) && asteriskInPath.test(targetPath);
}
public Optional<OperationHandler> getSpecificCopyOperationHandler(Operation operation) {
String sourcePath = operation.getSourceProperty();
String targetPath = operation.getTargetProperty();
if (ifThereIsNoAsteriskOrHashInPath(sourcePath, targetPath)) {
if (noAsteriskOrHashInPath(sourcePath, targetPath)) {
return Optional.of(new CopyObjectOperationHandler());
}
if (!isPathExpressionSupported(sourcePath, targetPath))
if (!pathExpressionSupported(sourcePath, targetPath)) {
return Optional.empty();
if (isOnlyOneAsteriskInPath.test(sourcePath)) {
return getCopyAsteriskOperationHandler(sourcePath, targetPath);
} else if (ifOnlyOneHashInPath.test(sourcePath)) {
}
if (onlyOneAsteriskInSourceAndTargetEach(sourcePath, targetPath)) {
return resolveAsteriskOperationHandler(sourcePath, targetPath);
} else if (onlyOneHashInPath.test(sourcePath)) {
getMatches(HASH, sourcePath);
}
......@@ -62,16 +70,29 @@ public class CopyOperationHandlerResolver {
}
private boolean ifThereIsNoAsteriskOrHashInPath(
private boolean onlyOneAsteriskInSourceAndTargetEach(String sourcePath, String targetPath) {
return OnlyOneAsteriskInPath.test(sourcePath) && OnlyOneAsteriskInPath.test(targetPath);
}
private boolean noAsteriskOrHashInPath(
String sourcePath, String targetPath) {
return !(isAsteriskOrHashInPath.test(sourcePath) || isAsteriskOrHashInPath.test(targetPath));
return !(asteriskOrHashInPath.test(sourcePath) || asteriskOrHashInPath.test(targetPath));
}
private Optional<OperationHandler> getCopyAsteriskOperationHandler(String sourcePath, String targetPath) {
String sourcePathBeforeAsterisk = sourcePath.split(ASTERISK_IN_SQUARE_BRACKETS_EXP)[0];
String sourcePathAfterAsterisk = sourcePath.split(ASTERISK_IN_SQUARE_BRACKETS_EXP)[1];
String targetPathBeforeAsterisk = targetPath.split(ASTERISK_IN_SQUARE_BRACKETS_EXP)[0];
String targetPathAfterAsterisk = targetPath.split(ASTERISK_IN_SQUARE_BRACKETS_EXP)[1];
private Optional<OperationHandler> resolveAsteriskOperationHandler(String sourcePath, String targetPath) {
String[] splitPath = sourcePath.split(ASTERISK_IN_SQUARE_BRACKETS_EXP);
String sourcePathBeforeAsterisk = splitPath[0];
String sourcePathAfterAsterisk = splitPath.length==2?splitPath[1].substring(1):null;
splitPath = targetPath.split(ASTERISK_IN_SQUARE_BRACKETS_EXP);
String targetPathBeforeAsterisk = splitPath[0];
String targetPathAfterAsterisk = splitPath.length==2?splitPath[1].substring(1):null;
if(sourcePathAfterAsterisk == null && targetPathAfterAsterisk == null){
CopyObjectOperationHandler copyObjectOperationHandler = new CopyObjectOperationHandler();
copyObjectOperationHandler.setSourceBasePath(sourcePathBeforeAsterisk);
copyObjectOperationHandler.setTargetBasePath(targetPathBeforeAsterisk);
return Optional.of(copyObjectOperationHandler);
}
CopyArrayAsteriskHandler copyArrayAsteriskHandler = new CopyArrayAsteriskHandler();
copyArrayAsteriskHandler.setSourceBasePath(sourcePathBeforeAsterisk);
copyArrayAsteriskHandler.setTargetBasePath(targetPathBeforeAsterisk);
......
......@@ -22,11 +22,29 @@ public class CopyArrayAsteriskHandler implements OperationHandler {
@Override
public Optional<Tree> performOperation(Operation operation, Tree rawTree, Tree transformedTree) {
Tree result = transformedTree.clone();
IntStream.range(0,rawTree.get(sourceBasePath).size()).forEach(index->{
result.putObject(targetBasePath+".["+index+"]."+targetChildPath,rawTree.get(sourceBasePath).get(index).get(sourceChildPath));
IntStream.range(0,rawTree.get(sourceBasePath).size())
.forEach(index->{
String targetPath = prepareTargetPath(index);
String sourcePath = prepareSourcePath(index);
result.putObject(targetPath,rawTree.get(sourcePath));
});
return Optional.of(result);
}
private String prepareTargetPath(int index) {
if(targetChildPath != null) {
return targetBasePath + "[" + index + "]." + targetChildPath;
}
return targetBasePath + "[" + index + "]";
}
private String prepareSourcePath(int index) {
if(sourceChildPath != null) {
return sourceBasePath + "[" + index + "]." + sourceChildPath;
}
return sourceBasePath + "[" + index + "]";
}
}
......@@ -6,13 +6,18 @@ import java.util.Optional;
import org.opengroup.osdu.wks.service.transformer.handler.operation.OperationHandler;
import org.opengroup.osdu.wks.service.transformer.model.mapping.operation.Operation;
import io.datatree.Tree;
import lombok.Setter;
@Setter
public class CopyObjectOperationHandler implements OperationHandler {
private String sourceBasePath;
private String targetBasePath;
@Override
public Optional<Tree> performOperation(
Operation operation, Tree rawTree, Tree transformedTree) {
String sourceProperty = operation.getSourceProperty();
String targetProperty = operation.getTargetProperty();
String sourceProperty = null!=sourceBasePath?sourceBasePath:operation.getSourceProperty();
String targetProperty = null!=targetBasePath?targetBasePath:operation.getTargetProperty();
if(Objects.isNull(sourceProperty) || sourceProperty.isEmpty() || Objects.isNull(targetProperty) || targetProperty.isEmpty()){
return Optional.empty();
}
......
......@@ -128,7 +128,16 @@ class CopyOperationHandlerResolverTest {
assertEquals("EffectiveDateTime",copyArrayAsteriskHandler.getTargetChildPath());
}
@DisplayName("If both source and target has no child path after [*] ")
void returnCopyObjectOperationHandler_NoChildPathAfterAsterisk() {
Operation operation = new Operation();
operation.setSourceProperty("data.Measurements[*]");
operation.setTargetProperty("data.VerticalMeasurements[*]");
Optional copyOperation = resolver.getSpecificCopyOperationHandler(operation);
assertTrue(copyOperation.isPresent());
// Then Copy Object Operation Handler is returned
assertTrue(copyOperation.get() instanceof CopyObjectOperationHandler);
}
@DisplayName("If both source and target does not contain * or # ")
void returnCopyObjectOperationHandler() {
......
......@@ -12,6 +12,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
import io.datatree.Tree;
import lombok.SneakyThrows;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ExtendWith(SpringExtension.class)
class CopyArrayAsteriskHandlerTest {
......@@ -21,10 +22,12 @@ class CopyArrayAsteriskHandlerTest {
.append(" \"data\": {\n")
.append(" \"Measurements\": [\n")
.append(" {\n")
.append(" \"EffectiveTimestamp\": \"2020-02-13\"\n")
.append(" \"EffectiveTimestamp\": \"2020-02-13\",\n")
.append(" \"BoreholeName\": \"ABCD\"\n")
.append(" },\n")
.append(" {\n")
.append(" \"EffectiveTimestamp\": \"2020-02-14\"\n")
.append(" \"EffectiveTimestamp\": \"2020-02-14\",\n")
.append(" \"BoreholeName\": \"PQRS\"\n")
.append(" }\n")
.append(" ]\n")
.append(" }\n")
......@@ -33,9 +36,9 @@ class CopyArrayAsteriskHandlerTest {
@SneakyThrows
@Test
@DisplayName("Array path is iterated and values copied to target")
void performOperationTest() {
Operation operation = createOperation();
@DisplayName("Test Copy Source Array Element To Target Element Operation")
void performCopySourceArrayElementToTargetElementOperationTest() {
Operation operation = createCopySourceArrayElementToTargetElementOperation();
Tree rawTree = new Tree(sourceData);
Tree transformedTree = new Tree();
Optional<OperationHandler> copyArrayAsteriskHandler
......@@ -45,15 +48,76 @@ class CopyArrayAsteriskHandlerTest {
// Target has 2 elements at array path
assertTrue(result.get().get("data.VerticalMeasurements").isList());
assertEquals(2, result.get().get("data.VerticalMeasurements").size());
// Each array element object has exact one element
assertEquals(1, result.get().get("data.VerticalMeasurements[0]").size());
assertEquals(1, result.get().get("data.VerticalMeasurements[1]").size());
// Values from source indexes are copied to respective indexes in target
assertEquals("2020-02-13", result.get().get("data.VerticalMeasurements[0].EffectiveDateTime").asString());
assertEquals("2020-02-14", result.get().get("data.VerticalMeasurements[1].EffectiveDateTime").asString());
}
Operation createOperation(){
@SneakyThrows
@Test
@DisplayName("Test Copy Array Object Operation")
void performCopyArrayObjectOperationTest() {
Operation operation = createCopyArrayObjectOperation();
Tree rawTree = new Tree(sourceData);
Tree transformedTree = new Tree();
Optional<OperationHandler> copyArrayAsteriskHandler
= (new CopyOperationHandlerResolver()).getSpecificCopyOperationHandler(operation);
assertTrue(copyArrayAsteriskHandler.isPresent());
Optional<Tree> result = copyArrayAsteriskHandler.get().performOperation(operation, rawTree, transformedTree);
// Target has 2 elements at array path
assertTrue(result.get().get("data.VerticalMeasurements").isList());
assertEquals(2, result.get().get("data.VerticalMeasurements").size());
// All values from source indexes are copied to respective indexes in target
assertEquals(2, result.get().get("data.VerticalMeasurements[0]").size());
assertEquals(2, result.get().get("data.VerticalMeasurements[1]").size());
assertEquals("2020-02-13", result.get().get("data.VerticalMeasurements[0].EffectiveTimestamp").asString());
assertEquals("ABCD", result.get().get("data.VerticalMeasurements[0].BoreholeName").asString());
assertEquals("2020-02-14",result.get().get("data.VerticalMeasurements[1].EffectiveTimestamp").asString());
assertEquals("PQRS",result.get().get("data.VerticalMeasurements[1].BoreholeName").asString());
}
@SneakyThrows
@Test
@DisplayName("Test Copy Array Element Operation No Target Child Path")
void performCopyArrayElementOperationNoTargetChildPathTest() {
Operation operation = createCopyArrayElementOperationNoTargetChildPath();
Tree rawTree = new Tree(sourceData);
Tree transformedTree = new Tree();
Optional<OperationHandler> copyArrayAsteriskHandler
= (new CopyOperationHandlerResolver()).getSpecificCopyOperationHandler(operation);
assertTrue(copyArrayAsteriskHandler.isPresent());
Optional<Tree> result = copyArrayAsteriskHandler.get().performOperation(operation, rawTree, transformedTree);
// Target has 2 elements at array path
assertTrue(result.get().get("data.VerticalMeasurements").isList());
assertEquals(2, result.get().get("data.VerticalMeasurements").size());
// All values from source indexes are copied to respective indexes in target
assertEquals("2020-02-13", result.get().get("data.VerticalMeasurements[0]").asString());
assertEquals("2020-02-14", result.get().get("data.VerticalMeasurements[1]").asString());
}
Operation createCopyArrayObjectOperation(){
Operation operation = new Operation();
operation.setSourceProperty("data.Measurements[*]");
operation.setTargetProperty("data.VerticalMeasurements[*]");
return operation;
}
Operation createCopySourceArrayElementToTargetElementOperation(){
Operation operation = new Operation();
operation.setSourceProperty("data.Measurements[*].EffectiveTimestamp");
operation.setTargetProperty("data.VerticalMeasurements[*].EffectiveDateTime");
return operation;
}
Operation createCopyArrayElementOperationNoTargetChildPath(){
Operation operation = new Operation();
operation.setSourceProperty("data.Measurements[*].EffectiveTimestamp");
operation.setTargetProperty("data.VerticalMeasurements[*]");
return operation;
}
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment