diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index abb98de..63e05f7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -30,14 +30,14 @@ jobs: run: ./gradlew clean build - name: Archive test results - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 if: always() # run even if build failed with: name: test-results path: build/reports - name: Archive libs - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: libs path: build/libs \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8f053e3..d5e6b65 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -65,7 +65,7 @@ jobs: run: ./gradlew jreleaserFullRelease - name: Archive artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: artifacts path: | diff --git a/src/main/java/blue/language/merge/processor/DictionaryProcessor.java b/src/main/java/blue/language/merge/processor/DictionaryProcessor.java index 58c1257..ee96f8a 100644 --- a/src/main/java/blue/language/merge/processor/DictionaryProcessor.java +++ b/src/main/java/blue/language/merge/processor/DictionaryProcessor.java @@ -15,7 +15,7 @@ public class DictionaryProcessor implements MergingProcessor { @Override public void process(Node target, Node source, NodeProvider nodeProvider, NodeResolver nodeResolver) { - if ((source.getKeyType() != null || source.getValueType() != null) && !Types.isDictionaryType(source.getType())) { + if ((source.getKeyType() != null || source.getValueType() != null) && !Types.isDictionaryType(source.getType(), nodeProvider)) { throw new IllegalArgumentException("Source node with keyType or valueType must have a Dictionary type"); } diff --git a/src/main/java/blue/language/merge/processor/ListProcessor.java b/src/main/java/blue/language/merge/processor/ListProcessor.java index f8810c3..6336f61 100644 --- a/src/main/java/blue/language/merge/processor/ListProcessor.java +++ b/src/main/java/blue/language/merge/processor/ListProcessor.java @@ -14,7 +14,7 @@ public class ListProcessor implements MergingProcessor { @Override public void process(Node target, Node source, NodeProvider nodeProvider, NodeResolver nodeResolver) { - if (source.getItemType() != null && !Types.isListType(source.getType())) { + if (source.getItemType() != null && !Types.isListType(source.getType(), nodeProvider)) { throw new IllegalArgumentException("Source node with itemType must have a List type"); } diff --git a/src/main/java/blue/language/utils/Types.java b/src/main/java/blue/language/utils/Types.java index 907a5cf..3dce885 100644 --- a/src/main/java/blue/language/utils/Types.java +++ b/src/main/java/blue/language/utils/Types.java @@ -113,12 +113,12 @@ public static boolean isBooleanType(Node typeNode, NodeProvider nodeProvider) { } - public static boolean isListType(Node typeNode) { - return typeNode.getBlueId() != null && LIST_TYPE_BLUE_ID.equals(typeNode.getBlueId()); + public static boolean isListType(Node typeNode, NodeProvider nodeProvider) { + return isSubtype(typeNode, new Node().blueId(LIST_TYPE_BLUE_ID), nodeProvider); } - public static boolean isDictionaryType(Node typeNode) { - return typeNode.getBlueId() != null && DICTIONARY_TYPE_BLUE_ID.equals(typeNode.getBlueId()); + public static boolean isDictionaryType(Node typeNode, NodeProvider nodeProvider) { + return isSubtype(typeNode, new Node().blueId(DICTIONARY_TYPE_BLUE_ID), nodeProvider); } } \ No newline at end of file diff --git a/src/test/java/blue/language/merge/MergerIntegrationTest.java b/src/test/java/blue/language/merge/MergerIntegrationTest.java new file mode 100644 index 0000000..b44e925 --- /dev/null +++ b/src/test/java/blue/language/merge/MergerIntegrationTest.java @@ -0,0 +1,59 @@ +package blue.language.merge; + +import blue.language.Blue; +import blue.language.model.Node; +import blue.language.provider.BasicNodeProvider; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +public class MergerIntegrationTest { + + private BasicNodeProvider nodeProvider; + + @BeforeEach + public void setup() { + nodeProvider = new BasicNodeProvider(); + } + + @Test + public void shouldBeIdempotentWhenResolvingTheSameNodeTwice() { + nodeProvider.addSingleDocs( + "name: Document Anchor\n" + + "template:\n" + + " description: Optional Blue document template.\n" + ); + + nodeProvider.addSingleDocs( + "name: Document Anchors\n" + + "type: Dictionary\n" + + "keyType: Text\n" + + "valueType:\n" + + " blueId: " + nodeProvider.getBlueIdByName("Document Anchor") + "\n" + ); + + nodeProvider.addSingleDocs( + "name: My Entry\n" + + "type:\n" + + " blueId: " + nodeProvider.getBlueIdByName("Document Anchors") + "\n" + + "anchor1:\n" + + " type:\n" + + " blueId: " + nodeProvider.getBlueIdByName("Document Anchor") + "\n" + + "anchor2:\n" + + " type:\n" + + " blueId: " + nodeProvider.getBlueIdByName("Document Anchor") + "\n" + ); + + Blue blue = new Blue(nodeProvider); + + Node myEntry = nodeProvider.getNodeByName("My Entry"); + + Node resolvedNode = blue.resolve(myEntry); + Node resolvedNode2 = blue.resolve(resolvedNode); + + assertEquals(blue.nodeToJson(resolvedNode), blue.nodeToJson(resolvedNode2)); + } +} + +