/*
 * Copyright (c) 2015 Cisco Systems, Inc. and others.  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 http://www.eclipse.org/legal/epl-v10.html
 */
package org.opendaylight.yangtools.yang.model.export;

import static java.util.Objects.requireNonNull;

import com.google.common.annotations.Beta;
import java.io.OutputStream;
import java.util.Optional;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLStreamException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stax.StAXSource;
import javax.xml.transform.stream.StreamResult;
import org.opendaylight.yangtools.yang.common.Revision;
import org.opendaylight.yangtools.yang.common.YangConstants;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.Submodule;
import org.opendaylight.yangtools.yang.model.api.stmt.ModuleEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.SubmoduleEffectiveStatement;

public final class YinExportUtils {
    private static final TransformerFactory TRANSFORMER_FACTORY = TransformerFactory.newInstance();

    private YinExportUtils() {
        // Hidden on purpose
    }

    /**
     * Returns well-formed file name of YIN file as defined in RFC6020.
     *
     * @param name Module or submodule name
     * @param revision Revision of module or submodule
     * @return well-formed file name of YIN file as defined in RFC6020.
     */
    public static String wellFormedYinName(final String name, final Optional<Revision> revision) {
        return wellFormedYinName(name, revision.map(Revision::toString).orElse(null));
    }

    /**
     * Returns well-formed file name of YIN file as defined in RFC6020.
     *
     * @param name name Module or submodule name
     * @param revision Revision of module or submodule
     * @return well-formed file name of YIN file as defined in RFC6020.
     */
    public static String wellFormedYinName(final String name, final String revision) {
        if (revision == null) {
            return name + YangConstants.RFC6020_YIN_FILE_EXTENSION;
        }
        return requireNonNull(name) + '@' + revision +  YangConstants.RFC6020_YIN_FILE_EXTENSION;
    }

    /**
     * Write a module as a YIN text into specified {@link OutputStream}. Supplied module must have the
     * {@link ModuleEffectiveStatement} trait.
     *
     * @param module Module to be exported
     * @throws IllegalArgumentException if the module is not an ModuleEffectiveStatement or if it declared
     *                                  representation is not available.
     * @throws NullPointerException if any of of the parameters is null
     * @throws XMLStreamException if an input-output error occurs
     * @deprecated Prefer {@link #writeModuleAsYinText(ModuleEffectiveStatement, OutputStream)}.
     */
    @Beta
    @Deprecated(forRemoval = true)
    public static void writeModuleAsYinText(final Module module, final OutputStream output) throws XMLStreamException {
        writeModuleAsYinText(module.asEffectiveStatement(), output);
    }

    /**
     * Write a module as a YIN text into specified {@link OutputStream}. Supplied module must have the
     * {@link ModuleEffectiveStatement} trait.
     *
     * @param module Module to be exported
     * @throws IllegalArgumentException if the module's declared representation is not available.
     * @throws NullPointerException if any of of the parameters is null
     * @throws XMLStreamException if an input-output error occurs
     */
    @Beta
    public static void writeModuleAsYinText(final ModuleEffectiveStatement module, final OutputStream output)
            throws XMLStreamException {
        writeReaderToOutput(YinXMLEventReaderFactory.defaultInstance().createXMLEventReader(module), output);
    }

    /**
     * Write a submodule as a YIN text into specified {@link OutputStream}. Supplied submodule must have the
     * {@link SubmoduleEffectiveStatement} trait.
     *
     * @param parentModule Parent module
     * @param submodule Submodule to be exported
     * @throws IllegalArgumentException if the parent module is not a ModuleEffectiveStatement, if the submodule is not
     *                                  a SubmoduleEffectiveStatement or if its declared representation is not available
     * @throws NullPointerException if any of of the parameters is null
     * @throws XMLStreamException if an input-output error occurs
     * @deprecated Prefer {@link #writeSubmoduleAsYinText(ModuleEffectiveStatement, SubmoduleEffectiveStatement,
     *             OutputStream)}.
     */
    @Beta
    @Deprecated(forRemoval = true)
    public static void writeSubmoduleAsYinText(final Module parentModule, final Submodule submodule,
            final OutputStream output) throws XMLStreamException {
        writeSubmoduleAsYinText(parentModule.asEffectiveStatement(), submodule.asEffectiveStatement(), output);
    }

    /**
     * Write a submodule as a YIN text into specified {@link OutputStream}. Supplied submodule must have the
     * {@link SubmoduleEffectiveStatement} trait.
     *
     * @param parentModule Parent module
     * @param submodule Submodule to be exported
     * @throws IllegalArgumentException if the parent module's or submodule's declared representation is not available
     * @throws NullPointerException if any of of the parameters is null
     * @throws XMLStreamException if an input-output error occurs
     */
    @Beta
    public static void writeSubmoduleAsYinText(final ModuleEffectiveStatement parentModule,
            final SubmoduleEffectiveStatement submodule, final OutputStream output) throws XMLStreamException {
        writeReaderToOutput(YinXMLEventReaderFactory.defaultInstance().createXMLEventReader(parentModule, submodule),
            output);
    }

    private static void writeReaderToOutput(final XMLEventReader reader, final OutputStream output)
            throws XMLStreamException {
        try {
            final Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
            transformer.setOutputProperty(OutputKeys.INDENT, "yes");
            transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
            transformer.transform(new StAXSource(reader), new StreamResult(output));
        } catch (TransformerException e) {
            throw new XMLStreamException("Failed to stream XML events", e);
        }
    }
}

@@ -976,125 +976,8 @@
 ts;%0A
-import org.opendaylight.yangtools.yang.model.api.Module;%0Aimport org.opendaylight.yangtools.yang.model.api.Submodule;%0A
 impo
@@ -2637,2460 +2637,457 @@
 dule
- is not an ModuleEffectiveStatement or if it declared%0A     *                                  representation is not available.%0A     * @throws NullPointerException if any of of the parameters is null%0A     * @throws XMLStreamException if an input-output error occurs%0A     * @deprecated Prefer %7B@link #writeModuleAsYinText(ModuleEffectiveStatement, OutputStream)%7D.%0A     */%0A    @Beta%0A    @Deprecated(forRemoval = true)%0A    public static void writeModuleAsYinText(final Module module, final OutputStream output) throws XMLStreamException %7B%0A        writeModuleAsYinText(module.asEffectiveStatement(), output);%0A    %7D%0A%0A    /**%0A     * Write a module as a YIN text into specified %7B@link OutputStream%7D. Supplied module must have the%0A     * %7B@link ModuleEffectiveStatement%7D trait.%0A     *%0A     * @param module Module to be exported%0A     * @throws IllegalArgumentException if the module's declared representation is not available.%0A     * @throws NullPointerException if any of of the parameters is null%0A     * @throws XMLStreamException if an input-output error occurs%0A     */%0A    @Beta%0A    public static void writeModuleAsYinText(final ModuleEffectiveStatement module, final OutputStream output)%0A            throws XMLStreamException %7B%0A        writeReaderToOutput(YinXMLEventReaderFactory.defaultInstance().createXMLEventReader(module), output);%0A    %7D%0A%0A    /**%0A     * Write a submodule as a YIN text into specified %7B@link OutputStream%7D. Supplied submodule must have the%0A     * %7B@link SubmoduleEffectiveStatement%7D trait.%0A     *%0A     * @param parentModule Parent module%0A     * @param submodule Submodule to be exported%0A     * @throws IllegalArgumentException if the parent module is not a ModuleEffectiveStatement, if the submodule is not%0A     *                                  a SubmoduleEffectiveStatement or if its declared representation is not available%0A     * @throws NullPointerException if any of of the parameters is null%0A     * @throws XMLStreamException if an input-output error occurs%0A     * @deprecated Prefer %7B@link #writeSubmoduleAsYinText(ModuleEffectiveStatement, SubmoduleEffectiveStatement,%0A     *             OutputStream)%7D.%0A     */%0A    @Beta%0A    @Deprecated(forRemoval = true)%0A    public static void writeSubmoduleAsYinText(final Module parentModule, final Submodule submodule,%0A            final OutputStream output) throws XMLStreamException %7B%0A        writeSubmoduleAsYinText(parentModule.asEffectiveStatement(), submodule.asEffectiveStatement(
+'s declared representation is not available.%0A     * @throws NullPointerException if any of of the parameters is null%0A     * @throws XMLStreamException if an input-output error occurs%0A     */%0A    @Beta%0A    public static void writeModuleAsYinText(final ModuleEffectiveStatement module, final OutputStream output)%0A            throws XMLStreamException %7B%0A        writeReaderToOutput(YinXMLEventReaderFactory.defaultInstance().createXMLEventReader(module
 ), o

Remove deprecated YingExportUtils methods