This is an automated email from the ASF dual-hosted git repository. reschke pushed a commit to branch trunk in repository https://gitbox.apache.org/repos/asf/jackrabbit-oak.git
commit acac0de477b4fe32e3a3268dd12bbef72e9267af Author: Julian Reschke <[email protected]> AuthorDate: Tue Oct 28 12:32:41 2025 +0100 Revert "OAK-11936: Allow updating the inference config via JMX (#2525)" This reverts commit 174dce112b33c0f3e59f665f96ab3ed390397506. --- .../jackrabbit/oak/api/jmx/InferenceMBean.java | 9 - .../elastic/query/inference/InferenceConfig.java | 24 +-- .../query/inference/InferenceMBeanImpl.java | 10 +- .../query/inference/InferenceConfigTest.java | 71 ------- .../jackrabbit/oak/json/JsonNodeBuilder.java | 211 --------------------- .../jackrabbit/oak/json/JsonNodeBuilderTest.java | 162 ---------------- 6 files changed, 6 insertions(+), 481 deletions(-) diff --git a/oak-api/src/main/java/org/apache/jackrabbit/oak/api/jmx/InferenceMBean.java b/oak-api/src/main/java/org/apache/jackrabbit/oak/api/jmx/InferenceMBean.java index 6f2187fe96..2690b6b64d 100644 --- a/oak-api/src/main/java/org/apache/jackrabbit/oak/api/jmx/InferenceMBean.java +++ b/oak-api/src/main/java/org/apache/jackrabbit/oak/api/jmx/InferenceMBean.java @@ -37,13 +37,4 @@ public interface InferenceMBean { * Get the inference configuration as a Json string. */ String getConfigNodeStateJson(); - - @Description("Adds or replaces the inference configuration at the specified path with the provided JSON. " + - "If saved successful, the system reInitializes with the updated configuration.") - void setConfigJson(@Name("path") - @Description("The node path where the configuration should be stored.") - String path, - @Name("configJson") - @Description("The inferenceConfig as a JSON sting.") - String configJson); } diff --git a/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/query/inference/InferenceConfig.java b/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/query/inference/InferenceConfig.java index 886fe5a362..7d0ae473c2 100644 --- a/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/query/inference/InferenceConfig.java +++ b/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/query/inference/InferenceConfig.java @@ -19,10 +19,8 @@ package org.apache.jackrabbit.oak.plugins.index.elastic.query.inference; import com.fasterxml.jackson.core.JsonProcessingException; -import org.apache.jackrabbit.oak.api.CommitFailedException; import org.apache.jackrabbit.oak.commons.PathUtils; import org.apache.jackrabbit.oak.commons.json.JsopBuilder; -import org.apache.jackrabbit.oak.json.JsonNodeBuilder; import org.apache.jackrabbit.oak.json.JsonUtils; import org.apache.jackrabbit.oak.plugins.index.IndexName; import org.apache.jackrabbit.oak.spi.state.NodeState; @@ -32,7 +30,6 @@ import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -245,25 +242,6 @@ public class InferenceConfig { } } - /** - * Updates the inference configuration with the provided JSON in the node store and reInitializes this class. - * - * @param path The node path where the configuration should be stored. - * @param jsonConfig The inferenceConfig as a JSON sting. - */ - public static void updateAndReInitializeConfigJson(String path, String jsonConfig) { - lock.writeLock().lock(); - try { - LOG.debug("Setting new InferenceConfig to path='{}' with content={}", path, jsonConfig); - JsonNodeBuilder.addOrReplace(INSTANCE.nodeStore, path, TYPE, jsonConfig); - InferenceConfig.reInitialize(INSTANCE.nodeStore, INSTANCE.statisticsProvider, path, INSTANCE.isInferenceEnabled, true); - } catch (CommitFailedException | IOException e) { - throw new RuntimeException(e); - } finally { - lock.writeLock().unlock(); - } - } - private @NotNull Map<String, InferenceIndexConfig> getIndexConfigs() { lock.readLock().lock(); try { @@ -318,4 +296,4 @@ public class InferenceConfig { builder.key(":enrich").encodedValue(enricherStatus.toString()).endObject(); return JsopBuilder.prettyPrint(builder.toString()); } -} \ No newline at end of file +} \ No newline at end of file diff --git a/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/query/inference/InferenceMBeanImpl.java b/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/query/inference/InferenceMBeanImpl.java index ef3f518356..bfd9f5f6fc 100644 --- a/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/query/inference/InferenceMBeanImpl.java +++ b/oak-search-elastic/src/main/java/org/apache/jackrabbit/oak/plugins/index/elastic/query/inference/InferenceMBeanImpl.java @@ -18,9 +18,14 @@ */ package org.apache.jackrabbit.oak.plugins.index.elastic.query.inference; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.jackrabbit.oak.api.jmx.InferenceMBean; import org.apache.jackrabbit.oak.commons.jmx.AnnotatedStandardMBean; +import org.apache.jackrabbit.oak.plugins.index.elastic.ElasticIndexProviderService; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; /** * An MBean that provides the inference configuration. @@ -41,9 +46,4 @@ public class InferenceMBeanImpl extends AnnotatedStandardMBean implements Infere public String getConfigNodeStateJson() { return InferenceConfig.getInstance().getInferenceConfigNodeState(); } - - @Override - public void setConfigJson(String path, String configJson) { - InferenceConfig.updateAndReInitializeConfigJson(path, configJson); - } } diff --git a/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/query/inference/InferenceConfigTest.java b/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/query/inference/InferenceConfigTest.java index f7a789725e..0af97b2428 100644 --- a/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/query/inference/InferenceConfigTest.java +++ b/oak-search-elastic/src/test/java/org/apache/jackrabbit/oak/plugins/index/elastic/query/inference/InferenceConfigTest.java @@ -24,7 +24,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import joptsimple.internal.Strings; import org.apache.jackrabbit.oak.api.CommitFailedException; import org.apache.jackrabbit.oak.commons.PathUtils; -import org.apache.jackrabbit.oak.json.JsonNodeBuilder; import org.apache.jackrabbit.oak.plugins.index.elastic.util.EnvironmentVariableProcessorUtil; import org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState; import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeBuilder; @@ -38,8 +37,6 @@ import org.junit.Before; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.mockito.MockedStatic; -import org.mockito.Mockito; import java.io.IOException; import java.util.Map; @@ -49,7 +46,6 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; public class InferenceConfigTest { @@ -1000,71 +996,4 @@ public class InferenceConfigTest { InferenceModelConfig resultForNonExistentIndexName = inferenceConfig.getInferenceModelConfig("nonExistentIndex", defaultModelName); assertEquals("Non-existent index name should return NOOP", InferenceModelConfig.NOOP, resultForNonExistentIndexName); } - - @Test - public void updateAndReInitializeCallsJsonNodeBuilder() { - String testPath = "/oak:index/testConfig"; - String testJson = "{\"type\":\"inferenceConfig\",\"enabled\":true}"; - InferenceConfig.reInitialize(nodeStore, testPath, true); - - try (MockedStatic<JsonNodeBuilder> mockedStatic = Mockito.mockStatic(JsonNodeBuilder.class)) { - InferenceConfig.updateAndReInitializeConfigJson(testPath, testJson); - mockedStatic.verify(() -> JsonNodeBuilder.addOrReplace( - nodeStore, - testPath, - InferenceConfig.TYPE, - testJson - ), Mockito.times(1)); - } - } - - @Test - public void updateAndReInitializeDoesReInitialize() throws Exception { - NodeBuilder inferenceConfigBuilder = createNodePath(rootBuilder, DEFAULT_CONFIG_PATH); - inferenceConfigBuilder.setProperty(InferenceConstants.ENABLED, false); - nodeStore.merge(rootBuilder, EmptyHook.INSTANCE, CommitInfo.EMPTY); - - InferenceConfig.reInitialize(nodeStore, DEFAULT_CONFIG_PATH, true); - InferenceConfig initialConfig = InferenceConfig.getInstance(); - assertFalse(initialConfig.isEnabled()); - - String enabledJson = "{\"type\":\"inferenceConfig\",\"enabled\":true}"; - InferenceConfig.updateAndReInitializeConfigJson(DEFAULT_CONFIG_PATH, enabledJson); - InferenceConfig updatedConfig = InferenceConfig.getInstance(); - assertTrue(updatedConfig.isEnabled()); - } - - @Test - public void updateAndReInitializeHandlesCommitFailedException() { - InferenceConfig.reInitialize(nodeStore, "/test", true); - try (MockedStatic<JsonNodeBuilder> mockedStatic = Mockito.mockStatic(JsonNodeBuilder.class)) { - mockedStatic.when(() -> JsonNodeBuilder.addOrReplace( - Mockito.any(NodeStore.class), Mockito.anyString(), Mockito.anyString(), Mockito.anyString() - )).thenThrow(new CommitFailedException("TEST", 0, "Test exception")); - - try { - InferenceConfig.updateAndReInitializeConfigJson("/test", "{}"); - fail("Expected RuntimeException to be thrown"); - } catch (RuntimeException e) { - assertTrue(e.getCause() instanceof CommitFailedException); - } - } - } - - @Test - public void updateAndReInitializeHandlesIOException() { - InferenceConfig.reInitialize(nodeStore, "/test", true); - try (MockedStatic<JsonNodeBuilder> mockedStatic = Mockito.mockStatic(JsonNodeBuilder.class)) { - mockedStatic.when(() -> JsonNodeBuilder.addOrReplace( - Mockito.any(NodeStore.class), Mockito.anyString(), Mockito.anyString(), Mockito.anyString() - )).thenThrow(new IOException("Test IO exception")); - - try { - InferenceConfig.updateAndReInitializeConfigJson("/test", "{}"); - fail("Expected RuntimeException to be thrown"); - } catch (RuntimeException e) { - assertTrue(e.getCause() instanceof IOException); - } - } - } } \ No newline at end of file diff --git a/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/json/JsonNodeBuilder.java b/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/json/JsonNodeBuilder.java deleted file mode 100644 index 2665ef5bc7..0000000000 --- a/oak-store-spi/src/main/java/org/apache/jackrabbit/oak/json/JsonNodeBuilder.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.jackrabbit.oak.json; - -import java.util.Map.Entry; -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Base64; -import java.util.UUID; - -import org.apache.jackrabbit.oak.api.Blob; -import org.apache.jackrabbit.oak.api.CommitFailedException; -import org.apache.jackrabbit.oak.api.PropertyState; -import org.apache.jackrabbit.oak.api.Type; -import org.apache.jackrabbit.oak.commons.PathUtils; -import org.apache.jackrabbit.oak.commons.json.JsonObject; -import org.apache.jackrabbit.oak.commons.json.JsopReader; -import org.apache.jackrabbit.oak.commons.json.JsopTokenizer; -import org.apache.jackrabbit.oak.spi.commit.CommitInfo; -import org.apache.jackrabbit.oak.spi.commit.EmptyHook; -import org.apache.jackrabbit.oak.spi.state.NodeBuilder; -import org.apache.jackrabbit.oak.spi.state.NodeStore; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * A utility class to persist a configuration that is in the form of JSON into - * the node store. - * <p> - * This is used to persist a small set of configuration nodes, eg. index - * definitions, using a simple JSON format. - * <p> - * The node type does not need to be set on a per-node basis. Where it is - * missing, the provided node type is used (e.g. "nt:unstructured") - * <p> - * A "jcr:uuid" is automatically added for nodes of type "nt:resource". - * <p> - * String, string arrays, boolean, blob, long, and double values are supported. - * Values that start with ":blobId:...base64..." are stored as binaries. "str:", - * "nam:" and "dat:" prefixes are removed. - * <p> - * "null" entries are not supported. - */ -public class JsonNodeBuilder { - - private static final Logger LOG = LoggerFactory.getLogger(JsonNodeBuilder.class); - - /** - * Add or replace a node in the node store, including all child nodes. - * - * @param nodeStore the target node store - * @param targetPath the target path where the node(s) is/are replaced - * @param nodeType the node type of the new node (eg. "nt:unstructured") - * @param jsonString the json string with the node data - * @throws CommitFailedException if storing the nodes failed - * @throws IOException if storing a blob failed - */ - public static void addOrReplace(NodeStore nodeStore, String targetPath, String nodeType, String jsonString) throws CommitFailedException, IOException { - LOG.info("Storing {}: {}", targetPath, jsonString); - JsonObject json = JsonObject.fromJson(jsonString, true); - NodeBuilder root = nodeStore.getRoot().builder(); - NodeBuilder builder = root; - for (String name : PathUtils.elements(targetPath)) { - NodeBuilder child = builder.child(name); - if (!child.hasProperty("jcr:primaryType")) { - if (nodeType.indexOf("/") >= 0) { - throw new IllegalStateException("Illegal node type: " + nodeType); - } - child.setProperty("jcr:primaryType", nodeType, Type.NAME); - } - builder = child; - } - storeConfigNode(nodeStore, builder, nodeType, json); - nodeStore.merge(root, EmptyHook.INSTANCE, CommitInfo.EMPTY); - } - - private static void storeConfigNode(NodeStore nodeStore, NodeBuilder builder, String nodeType, JsonObject json) throws IOException { - for (Entry<String, JsonObject> e : json.getChildren().entrySet()) { - String k = e.getKey(); - JsonObject v = e.getValue(); - storeConfigNode(nodeStore, builder.child(k), nodeType, v); - } - for (String child : builder.getChildNodeNames()) { - if (!json.getChildren().containsKey(child)) { - builder.child(child).remove(); - } - } - for (Entry<String, String> e : json.getProperties().entrySet()) { - String k = e.getKey(); - String v = e.getValue(); - storeConfigProperty(nodeStore, builder, k, v); - } - if (!json.getProperties().containsKey("jcr:primaryType")) { - builder.setProperty("jcr:primaryType", nodeType, Type.NAME); - } - for (PropertyState prop : builder.getProperties()) { - if ("jcr:primaryType".equals(prop.getName())) { - continue; - } - if (!json.getProperties().containsKey(prop.getName())) { - builder.removeProperty(prop.getName()); - } - } - if ("nt:resource".equals(JsonNodeBuilder.oakStringValue(json, "jcr:primaryType"))) { - if (!json.getProperties().containsKey("jcr:uuid")) { - String uuid = UUID.randomUUID().toString(); - builder.setProperty("jcr:uuid", uuid); - } - } - } - - private static void storeConfigProperty(NodeStore nodeStore, NodeBuilder builder, String propertyName, String value) throws IOException { - if (value.startsWith("\"")) { - // string or blob - value = JsopTokenizer.decodeQuoted(value); - if (value.startsWith(":blobId:")) { - String base64 = value.substring(":blobId:".length()); - byte[] bytes = Base64.getDecoder().decode(base64.getBytes(StandardCharsets.UTF_8)); - Blob blob; - blob = nodeStore.createBlob(new ByteArrayInputStream(bytes)); - builder.setProperty(propertyName, blob); - } else { - if ("jcr:primaryType".equals(propertyName)) { - builder.setProperty(propertyName, value, Type.NAME); - } else { - builder.setProperty(propertyName, value); - } - } - } else if (value.equals("null")) { - throw new IllegalArgumentException("Removing entries is not supported"); - } else if (value.equals("true")) { - builder.setProperty(propertyName, true); - } else if (value.equals("false")) { - builder.setProperty(propertyName, false); - } else if (value.startsWith("[")) { - JsopTokenizer tokenizer = new JsopTokenizer(value); - ArrayList<String> result = new ArrayList<>(); - tokenizer.matches('['); - if (!tokenizer.matches(']')) { - do { - if (!tokenizer.matches(JsopReader.STRING)) { - throw new IllegalArgumentException("Could not process string array " + value); - } - result.add(tokenizer.getEscapedToken()); - } while (tokenizer.matches(',')); - tokenizer.read(']'); - } - tokenizer.read(JsopReader.END); - builder.setProperty(propertyName, result, Type.STRINGS); - } else if (value.indexOf('.') >= 0 || value.toLowerCase().indexOf("e") >= 0) { - // double - try { - Double d = Double.parseDouble(value); - builder.setProperty(propertyName, d); - } catch (NumberFormatException e) { - throw new IllegalArgumentException("Could not parse double " + value); - } - } else if (value.startsWith("-") || (!value.isEmpty() && Character.isDigit(value.charAt(0)))) { - // long - try { - Long x = Long.parseLong(value); - builder.setProperty(propertyName, x); - } catch (NumberFormatException e) { - throw new IllegalArgumentException("Could not parse long " + value); - } - } else { - throw new IllegalArgumentException("Unsupported value " + value); - } - } - - static String oakStringValue(JsonObject json, String propertyName) { - String value = json.getProperties().get(propertyName); - if (value == null) { - return null; - } - return oakStringValue(value); - } - - static String oakStringValue(String value) { - if (!value.startsWith("\"")) { - // support numbers - return value; - } - value = JsopTokenizer.decodeQuoted(value); - if (value.startsWith(":blobId:")) { - value = value.substring(":blobId:".length()); - value = new String(Base64.getDecoder().decode(value.getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8); - } else if (value.startsWith("str:") || value.startsWith("nam:") || value.startsWith("dat:")) { - value = value.substring("str:".length()); - } - return value; - } -} diff --git a/oak-store-spi/src/test/java/org/apache/jackrabbit/oak/json/JsonNodeBuilderTest.java b/oak-store-spi/src/test/java/org/apache/jackrabbit/oak/json/JsonNodeBuilderTest.java deleted file mode 100644 index 5abc7094ef..0000000000 --- a/oak-store-spi/src/test/java/org/apache/jackrabbit/oak/json/JsonNodeBuilderTest.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.jackrabbit.oak.json; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThrows; - -import java.io.IOException; - -import org.apache.jackrabbit.oak.api.CommitFailedException; -import org.apache.jackrabbit.oak.commons.json.JsonObject; -import org.apache.jackrabbit.oak.plugins.memory.MemoryNodeStore; -import org.junit.Before; -import org.junit.Test; - -public class JsonNodeBuilderTest { - - private MemoryNodeStore ns; - - @Before - public void before() { - ns = new MemoryNodeStore(); - } - - @Test - public void addNodeTypeAndUUID() throws CommitFailedException, IOException { - JsonObject json = JsonObject.fromJson("{\n" - + " \"includedPaths\": \"/same\",\n" - + " \"jcr:primaryType\": \"nt:unstructured\",\n" - + " \"queryPaths\": \"/same\",\n" - + " \"type\": \"lucene\",\n" - + " \"diff.json\": {\n" - + " \"jcr:primaryType\": \"nt:file\",\n" - + " \"jcr:content\": {\n" - + " \"jcr:data\": \":blobId:dGVzdA==\",\n" - + " \"jcr:mimeType\": \"application/json\",\n" - + " \"jcr:primaryType\": \"nt:resource\"\n" - + " }\n" - + " }\n" - + "}" , true); - JsonNodeBuilder.addOrReplace(ns, "/test", "nt:test", json.toString()); - String json2 = JsonUtils.nodeStateToJson(ns.getRoot(), 5); - json2 = json2.replaceAll("jcr:uuid\" : \".*\"", "jcr:uuid\" : \"...\""); - assertEquals("{\n" - + " \"test\" : {\n" - + " \"queryPaths\" : \"/same\",\n" - + " \"includedPaths\" : \"/same\",\n" - + " \"jcr:primaryType\" : \"nt:unstructured\",\n" - + " \"type\" : \"lucene\",\n" - + " \"diff.json\" : {\n" - + " \"jcr:primaryType\" : \"nt:file\",\n" - + " \"jcr:content\" : {\n" - + " \"jcr:mimeType\" : \"application/json\",\n" - + " \"jcr:data\" : \"test\",\n" - + " \"jcr:primaryType\" : \"nt:resource\",\n" - + " \"jcr:uuid\" : \"...\"\n" - + " }\n" - + " }\n" - + " }\n" - + "}", json2); - - json = JsonObject.fromJson( - "{\"number\":1," + - "\"double2\":1.0," + - "\"child2\":{\"y\":2}}", true); - JsonNodeBuilder.addOrReplace(ns, "/test", "nt:test", json.toString()); - assertEquals("{\n" - + " \"test\" : {\n" - + " \"number\" : 1,\n" - + " \"double2\" : 1.0,\n" - + " \"jcr:primaryType\" : \"nt:test\",\n" - + " \"child2\" : {\n" - + " \"y\" : 2,\n" - + " \"jcr:primaryType\" : \"nt:test\"\n" - + " }\n" - + " }\n" - + "}", JsonUtils.nodeStateToJson(ns.getRoot(), 5)); - } - - @Test - public void storeDifferentDataTypes() throws CommitFailedException, IOException { - JsonObject json = JsonObject.fromJson( - "{\"number\":1," + - "\"double\":1.0," + - "\"string\":\"hello\"," + - "\"array\":[\"a\",\"b\"]," + - "\"child\":{\"x\":1}," + - "\"blob\":\":blobId:dGVzdA==\"}", true); - JsonNodeBuilder.addOrReplace(ns, "/test", "nt:test", json.toString()); - assertEquals("{\n" - + " \"test\" : {\n" - + " \"number\" : 1,\n" - + " \"blob\" : \"test\",\n" - + " \"string\" : \"hello\",\n" - + " \"array\" : [ \"a\", \"b\" ],\n" - + " \"double\" : 1.0,\n" - + " \"jcr:primaryType\" : \"nt:test\",\n" - + " \"child\" : {\n" - + " \"x\" : 1,\n" - + " \"jcr:primaryType\" : \"nt:test\"\n" - + " }\n" - + " }\n" - + "}", JsonUtils.nodeStateToJson(ns.getRoot(), 5)); - - json = JsonObject.fromJson( - "{\"number\":1," + - "\"boolTrue\":true," + - "\"boolFalse\":false," + - "\"double2\":1.0," + - "\"child2\":{\"y\":2}}", true); - JsonNodeBuilder.addOrReplace(ns, "/test", "nt:test", json.toString()); - assertEquals("{\n" - + " \"test\" : {\n" - + " \"number\" : 1,\n" - + " \"boolTrue\" : true,\n" - + " \"boolFalse\" : false,\n" - + " \"double2\" : 1.0,\n" - + " \"jcr:primaryType\" : \"nt:test\",\n" - + " \"child2\" : {\n" - + " \"y\" : 2,\n" - + " \"jcr:primaryType\" : \"nt:test\"\n" - + " }\n" - + " }\n" - + "}", JsonUtils.nodeStateToJson(ns.getRoot(), 5)); - } - - @Test - public void illegalNodeTypesAreProhibited() { - String simpleJson = "{\"property\": \"value\"}"; - - IllegalStateException exception = assertThrows( - IllegalStateException.class, - () -> JsonNodeBuilder.addOrReplace(ns, "/test", "invalid/nodetype", simpleJson) - ); - assertEquals("Illegal node type: invalid/nodetype", exception.getMessage()); - } - - @Test - public void removingEntriesIsProhibited() { - String jsonWithNull = "{\"nullProperty\": null}"; - - IllegalArgumentException exception = assertThrows( - IllegalArgumentException.class, - () -> JsonNodeBuilder.addOrReplace(ns, "/test", "nt:unstructured", jsonWithNull) - ); - assertEquals("Removing entries is not supported", exception.getMessage()); - } -}
