+ @SuppressWarnings("unchecked")
+ private void writeValue(final Object value, final JSONCodec<?> codec) throws IOException {
+ ((JSONCodec<Object>) codec).writeValue(writer, value);
+ }
+
+ private void writeAnydataValue(final Object value) throws IOException {
+ if (value instanceof NormalizedAnydata) {
+ writeNormalizedAnydata((NormalizedAnydata) value);
+ } else {
+ throw new IllegalStateException("Unexpected anydata value " + value);
+ }
+ }
+
+ private void writeNormalizedAnydata(final NormalizedAnydata anydata) throws IOException {
+ // Adjust state to point to parent node and ensure it can handle data tree nodes
+ final SchemaInferenceStack.Inference inference;
+ try {
+ final SchemaInferenceStack stack = SchemaInferenceStack.ofInference(anydata.getInference());
+ stack.exitToDataTree();
+ inference = stack.toInference();
+ } catch (IllegalArgumentException | IllegalStateException | NoSuchElementException e) {
+ throw new IOException("Cannot emit " + anydata, e);
+ }
+
+ anydata.writeTo(JSONNormalizedNodeStreamWriter.createNestedWriter(
+ codecs.rebaseTo(inference.getEffectiveModelContext()), inference, context.getNamespace(), writer));
+ }
+
+ private void writeAnyXmlValue(final DOMSource anyXmlValue) throws IOException {
+ writeXmlNode(anyXmlValue.getNode());
+ }
+
+ private void writeXmlNode(final Node node) throws IOException {
+ if (isArrayElement(node)) {
+ writeArrayContent(node);
+ return;
+ }
+ final Element firstChildElement = getFirstChildElement(node);
+ if (firstChildElement == null) {
+ writeXmlValue(node);
+ } else {
+ writeObjectContent(firstChildElement);
+ }
+ }
+
+ private void writeArrayContent(final Node node) throws IOException {
+ writer.beginArray();
+ handleArray(node);
+ writer.endArray();
+ }
+
+ private void writeObjectContent(final Element firstChildElement) throws IOException {
+ writer.beginObject();
+ writeObject(firstChildElement);
+ writer.endObject();
+ }
+
+ private static boolean isArrayElement(final Node node) {
+ if (Node.ELEMENT_NODE == node.getNodeType()) {
+ final String nodeName = node.getNodeName();
+ for (Node nextNode = node.getNextSibling(); nextNode != null; nextNode = nextNode.getNextSibling()) {
+ if (Node.ELEMENT_NODE == nextNode.getNodeType() && nodeName.equals(nextNode.getNodeName())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private void handleArray(final Node node) throws IOException {
+ final Element parentNode = (Element)node.getParentNode();
+ final NodeList elementsList = parentNode.getElementsByTagName(node.getNodeName());
+ for (int i = 0, length = elementsList.getLength(); i < length; i++) {
+ final Node arrayElement = elementsList.item(i);
+ final Element parent = (Element)arrayElement.getParentNode();
+ if (parentNode.isSameNode(parent)) {
+ final Element firstChildElement = getFirstChildElement(arrayElement);
+ if (firstChildElement != null) {
+ writeObjectContent(firstChildElement);
+ } else {
+ // It may be scalar
+ writeXmlValue(arrayElement);
+ }
+ }
+ }
+ }
+
+ private void writeObject(Node node) throws IOException {
+ String previousNodeName = "";
+ while (node != null) {
+ if (Node.ELEMENT_NODE == node.getNodeType()) {
+ if (!node.getNodeName().equals(previousNodeName)) {
+ previousNodeName = node.getNodeName();
+ writer.name(node.getNodeName());
+ writeXmlNode(node);
+ }
+ }
+ node = node.getNextSibling();
+ }