All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.lighty.codecs.util.XmlNodeConverter Maven / Gradle / Ivy

There is a newer version: 20.2.0
Show newest version
/*
 * Copyright (c) 2021 PANTHEON.tech s.r.o. All Rights Reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at https://www.eclipse.org/legal/epl-v10.html
 */
package io.lighty.codecs.util;

import com.google.common.base.Preconditions;
import io.lighty.codecs.util.exception.DeserializationException;
import io.lighty.codecs.util.exception.SerializationException;
import java.io.IOException;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import javax.xml.XMLConstants;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import org.opendaylight.yangtools.yang.common.XMLNamespace;
import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeWriter;
import org.opendaylight.yangtools.yang.data.codec.xml.XMLStreamNormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.codec.xml.XmlParserStream;
import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
import org.opendaylight.yangtools.yang.data.impl.schema.NormalizationResultHolder;
import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.opendaylight.yangtools.yang.model.util.SchemaInferenceStack.Inference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The implementation of {@link NodeConverter} which serializes and deserializes binding independent
 * representation into/from XML representation.
 *
 * @see JsonNodeConverter
 */
public class XmlNodeConverter implements NodeConverter {

    private static final Logger LOG = LoggerFactory.getLogger(XmlNodeConverter.class);

    private static final XMLInputFactory XML_IN_FACTORY;
    private static final XMLOutputFactory XML_OUT_FACTORY;

    static {
        XML_IN_FACTORY = XMLInputFactory.newInstance();
        XML_OUT_FACTORY = XMLOutputFactory.newFactory();
        XML_OUT_FACTORY.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, true);
    }

    private final EffectiveModelContext effectiveModelContext;

    /**
     * The only constructor will create an instance of {@link XmlNodeConverter} with the given
     * {@link EffectiveModelContext}. This effective model context will be used for proper RPC and Node resolution
     *
     * @param effectiveModelContext initial effective model context
     */
    public XmlNodeConverter(final EffectiveModelContext effectiveModelContext) {
        this.effectiveModelContext = effectiveModelContext;
    }

    /**
     * Serializes the given {@link NormalizedNode} into its {@link Writer} representation.
     *
     * @param inference      {@link Inference} pointing to normalizedNode's parent
     * @param normalizedNode normalized node to serialize
     * @return {@link Writer}
     * @throws SerializationException if something goes wrong with serialization
     */
    @Override
    public Writer serializeData(final Inference inference,
            final NormalizedNode normalizedNode) throws SerializationException {
        final Writer writer = new StringWriter();
        XMLStreamWriter xmlStreamWriter;
        try {
            xmlStreamWriter = XML_OUT_FACTORY.createXMLStreamWriter(writer);
        } catch (XMLStreamException | FactoryConfigurationError e) {
            throw new SerializationException(e);
        }
        final NormalizedNodeStreamWriter nnStreamWriter = XMLStreamNormalizedNodeStreamWriter
                .create(xmlStreamWriter, inference);
        try (NormalizedNodeWriter nnWriter = NormalizedNodeWriter.forStreamWriter(nnStreamWriter)) {
            nnWriter.write(normalizedNode);
            return writer;
        } catch (IOException e) {
            throw new SerializationException(e);
        }
    }

    @Override
    public Writer serializeRpc(final Inference inference, final NormalizedNode normalizedNode)
            throws SerializationException {
        Preconditions.checkState(normalizedNode instanceof ContainerNode,
                "RPC input/output to serialize is expected to be a ContainerNode");
        final Writer writer = new StringWriter();
        XMLStreamWriter xmlStreamWriter;
        try {
            xmlStreamWriter = XML_OUT_FACTORY.createXMLStreamWriter(writer);
        } catch (XMLStreamException | FactoryConfigurationError e) {
            throw new SerializationException(e);
        }
        final XMLNamespace namespace = normalizedNode.name().getNodeType().getNamespace();
        // Input/output
        final String localName = normalizedNode.name().getNodeType().getLocalName();
        final NormalizedNodeStreamWriter nnStreamWriter = XMLStreamNormalizedNodeStreamWriter
                .create(xmlStreamWriter, inference);
        try (NormalizedNodeWriter nnWriter = NormalizedNodeWriter.forStreamWriter(nnStreamWriter)) {
            xmlStreamWriter.writeStartElement(XMLConstants.DEFAULT_NS_PREFIX, localName, namespace.toString());
            xmlStreamWriter.writeDefaultNamespace(namespace.toString());
            for (NormalizedNode child : ((ContainerNode) normalizedNode).body()) {
                nnWriter.write(child);
            }
            xmlStreamWriter.writeEndElement();
            return writer;
        } catch (XMLStreamException | IOException e) {
            throw new SerializationException(e);
        }
    }

    /**
     * Deserializes a given XML input data into {@link NormalizedNode}.
     *
     * 

* In the case of deserializing multiple top level list entries, entries are expected to be wrapped in * {@code }. * * @param inference {@link Inference} pointing to a node we are trying to deserialize * @param inputData Reader containing input JSON data describing node to deserialize * @return deserialized {@link NormalizedNode} * @throws DeserializationException is thrown in case of an error during deserialization */ @Override public NormalizedNode deserialize(final Inference inference, final Reader inputData) throws DeserializationException { final XMLStreamReader reader; try { reader = XML_IN_FACTORY.createXMLStreamReader(inputData); } catch (XMLStreamException e) { throw new DeserializationException(e); } final NormalizationResultHolder result = new NormalizationResultHolder(); final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result); try (XmlParserStream xmlParser = XmlParserStream.create(streamWriter, inference)) { xmlParser.parse(reader); return result.getResult().data(); } catch (XMLStreamException | IOException e) { throw new DeserializationException(e); } finally { try { reader.close(); } catch (XMLStreamException e) { LOG.warn("Failed to close XML stream", e); } } } @Override public EffectiveModelContext getModelContext() { return effectiveModelContext; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy