+
+ @Override
+ protected final NormalizationResult<ContainerNode> parseDatastore(final InputStream stream,
+ final NodeIdentifier containerName, final Unqualified moduleName)
+ throws IOException, NormalizationException {
+ // This is bit more involved: given this example document:
+ //
+ // {
+ // "ietf-restconf:data" : {
+ // "foo:foo" : {
+ // "str" : "str"
+ // }
+ // }
+ // }
+ //
+ // we need to first peel this part:
+ //
+ // {
+ // "ietf-restconf:data" :
+ //
+ // validating it really the name matches rootName and that it is followed by '{', i.e. it really is an object.
+ //
+ // We then need to essentially do the equivalent of parseStream() on the EffectiveModelContext, but the receiver
+ // should be the builder for our resulting node -- we cannot and do not want to use a holder, as can legally
+ // more than one child.
+ //
+ // Then we need to take care of the last closing brace, raising an error if there is any other content -- i.e.
+ // we need to reach the end of JsonReader.
+ //
+ // And then it's just a matter of returning the built container.
+ try (var reader = new JsonReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) {
+ reader.beginObject();
+ final var name = reader.nextName();
+ final var expected = moduleName.getLocalName() + ':' + containerName.getNodeType().getLocalName();
+ if (!expected.equals(name)) {
+ throw NormalizationException.ofMessage("Expected name '" + expected + "', got '" + name + "'");
+ }
+
+ final var builder = ImmutableNodes.newContainerBuilder().withNodeIdentifier(containerName);
+
+ if (reader.peek() == JsonToken.BEGIN_OBJECT) {
+ try (var writer = ImmutableNormalizedNodeStreamWriter.from(builder)) {
+ try (var parser = JsonParserStream.create(writer, this)) {
+ parser.parse(reader);
+ } catch (JsonParseException e) {
+ throw NormalizationException.ofCause(e);
+ }
+ }
+ }
+
+ reader.endObject();
+ final var nextToken = reader.peek();
+ if (nextToken != JsonToken.END_DOCUMENT) {
+ throw NormalizationException.ofMessage("Expected end of JSON document, got " + nextToken);
+ }
+ return new NormalizationResult<>(builder.build());
+ } catch (IllegalStateException e) {
+ throw NormalizationException.ofCause(e);
+ }
+ }
+
+ @Override
+ protected final NormalizationResult<?> parseData(final SchemaInferenceStack stack, final InputStream stream)
+ throws IOException, NormalizationException {
+ // Point to parent node
+ stack.exit();
+ return parseStream(stack.toInference(), stream);
+ }
+
+ @Override
+ protected final NormalizationResult<?> parseChildData(final InputStream stream,
+ final EffectiveStatementInference inference) throws IOException, NormalizationException {
+ return parseStream(inference, stream);
+ }
+
+ @Override
+ protected final NormalizationResult<?> parseInputOutput(final SchemaInferenceStack stack, final QName expected,
+ final InputStream stream) throws IOException, NormalizationException {
+ return checkNodeName(parseStream(stack.toInference(), stream), expected);
+ }
+
+ private @NonNull NormalizationResult<?> parseStream(final @NonNull EffectiveStatementInference inference,
+ final @NonNull InputStream stream) throws IOException, NormalizationException {
+ try (var reader = new JsonReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) {
+ final var holder = new NormalizationResultHolder();
+ try (var writer = ImmutableNormalizedNodeStreamWriter.from(holder)) {
+ try (var parser = JsonParserStream.create(writer, this, inference)) {
+ parser.parse(reader);
+ } catch (JsonParseException e) {
+ throw NormalizationException.ofCause(e);
+ }
+ }
+ return holder.getResult();
+ }
+ }