Remove useless UnsupportedOperationException throws
[yangtools.git] / yang / yang-model-export / src / main / java / org / opendaylight / yangtools / yang / model / export / YinExportUtils.java
index e5180508aa85a4197144eaee2c6185d046dc54a3..ec536266e7fdf54748ad5f9f04c58481d8c7ac8e 100644 (file)
  */
 package org.opendaylight.yangtools.yang.model.export;
 
-import com.google.common.base.Preconditions;
-import com.google.common.collect.BiMap;
-import com.google.common.collect.HashBiMap;
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.Beta;
 import java.io.OutputStream;
-import java.net.URI;
-import java.util.Date;
-import java.util.Map;
-import javax.xml.stream.XMLOutputFactory;
+import java.util.Optional;
+import javax.xml.stream.XMLEventReader;
 import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamWriter;
-import org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil;
+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.ModuleImport;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-public class YinExportUtils {
+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() {
-        throw new UnsupportedOperationException("Utility class");
+        // 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 Date revision) {
-        return wellFormedYinName(name, SimpleDateFormatUtil.getRevisionFormat().format(revision));
+    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
+     * @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) {
-        return String.format("%s@%s.yin", Preconditions.checkNotNull(name),Preconditions.checkNotNull(revision));
+        if (revision == null) {
+            return name + YangConstants.RFC6020_YIN_FILE_EXTENSION;
+        }
+        return requireNonNull(name) + '@' + revision +  YangConstants.RFC6020_YIN_FILE_EXTENSION;
     }
 
     /**
-     * Writes YIN representation of supplied module to specified output stream.
+     * Write a module as a YIN text into specified {@link OutputStream}. Supplied module must have the
+     * {@link ModuleEffectiveStatement} trait.
      *
-     * @param ctx
-     *            Schema Context which contains module and extension definitions
-     *            to be used during export of model.
-     * @param module
-     *            Module to be exported.
-     * @param str
-     *            Output stream to which YIN representation of model will be
-     *            written.
-     * @throws XMLStreamException
+     * @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
      */
-    public static void writeModuleToOutputStream(final SchemaContext ctx, final Module module, final OutputStream str) throws XMLStreamException {
-        final XMLOutputFactory factory = XMLOutputFactory.newFactory();
-        final XMLStreamWriter xmlStreamWriter = factory.createXMLStreamWriter(str);
-        writeModuleToOutputStream(ctx,module, xmlStreamWriter);
+    @Beta
+    public static void writeModuleAsYinText(final Module module, final OutputStream output) throws XMLStreamException {
+        requireNonNull(module);
+        checkArgument(module instanceof ModuleEffectiveStatement, "Module %s is not a ModuleEffectiveStatement",
+            module);
+        final ModuleEffectiveStatement effective = (ModuleEffectiveStatement) module;
+        writeReaderToOutput(YinXMLEventReaderFactory.defaultInstance().createXMLEventReader(effective), output);
     }
 
-    private static void writeModuleToOutputStream(final SchemaContext ctx, final Module module, final XMLStreamWriter xmlStreamWriter) {
-        final URI moduleNs = module.getNamespace();
-        final Map<String, URI> prefixToNs = prefixToNamespace(ctx,module);
-        final StatementTextWriter yinWriter = SingleModuleYinStatementWriter.create(xmlStreamWriter, moduleNs, prefixToNs);
-        SchemaContextEmitter.writeToStatementWriter(module, ctx,yinWriter);
-    }
-
-    private static Map<String, URI> prefixToNamespace(final SchemaContext ctx, final Module module) {
-        final BiMap<String, URI> prefixMap = HashBiMap.create(module.getImports().size() + 1);
-        prefixMap.put(module.getPrefix(), module.getNamespace());
-        for(final ModuleImport imp : module.getImports()) {
-            final String prefix = imp.getPrefix();
-            final URI namespace = getModuleNamespace(ctx,imp.getModuleName());
-            prefixMap.put(prefix, namespace);
-        }
-        return prefixMap;
+    /**
+     * 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
+     */
+    @Beta
+    public static void writeSubmoduleAsYinText(final Module parentModule, final Module submodule,
+            final OutputStream output) throws XMLStreamException {
+        requireNonNull(parentModule);
+        checkArgument(parentModule instanceof ModuleEffectiveStatement, "Parent %s is not a ModuleEffectiveStatement",
+            parentModule);
+        requireNonNull(submodule);
+        checkArgument(submodule instanceof SubmoduleEffectiveStatement,
+            "Submodule %s is not a SubmoduleEffectiveStatement", submodule);
+        writeReaderToOutput(YinXMLEventReaderFactory.defaultInstance().createXMLEventReader(
+            (ModuleEffectiveStatement) parentModule, (SubmoduleEffectiveStatement)submodule), output);
     }
 
-    private static URI getModuleNamespace(final SchemaContext ctx, final String moduleName) {
-        for(final Module module : ctx.getModules()) {
-            if(moduleName.equals(module.getName())) {
-                return module.getNamespace();
-            }
+    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);
         }
-        throw new IllegalArgumentException("Module " + moduleName + "does not exists in provided schema context");
     }
-
 }