2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.yang.model.export;
10 import static com.google.common.base.Preconditions.checkArgument;
11 import static java.util.Objects.requireNonNull;
13 import com.google.common.annotations.Beta;
14 import com.google.common.collect.BiMap;
15 import com.google.common.collect.HashBiMap;
16 import java.io.OutputStream;
19 import java.util.Optional;
20 import javax.xml.stream.XMLEventReader;
21 import javax.xml.stream.XMLStreamException;
22 import javax.xml.transform.OutputKeys;
23 import javax.xml.transform.Transformer;
24 import javax.xml.transform.TransformerException;
25 import javax.xml.transform.TransformerFactory;
26 import javax.xml.transform.stax.StAXSource;
27 import javax.xml.transform.stream.StreamResult;
28 import org.opendaylight.yangtools.yang.common.Revision;
29 import org.opendaylight.yangtools.yang.common.YangConstants;
30 import org.opendaylight.yangtools.yang.model.api.Module;
31 import org.opendaylight.yangtools.yang.model.api.ModuleImport;
32 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
33 import org.opendaylight.yangtools.yang.model.api.stmt.ModuleEffectiveStatement;
34 import org.opendaylight.yangtools.yang.model.api.stmt.SubmoduleEffectiveStatement;
36 public final class YinExportUtils {
37 private static final TransformerFactory TRANSFORMER_FACTORY = TransformerFactory.newInstance();
39 private YinExportUtils() {
44 * Returns well-formed file name of YIN file as defined in RFC6020.
46 * @param name Module or submodule name
47 * @param revision Revision of module or submodule
48 * @return well-formed file name of YIN file as defined in RFC6020.
50 public static String wellFormedYinName(final String name, final Optional<Revision> revision) {
51 return wellFormedYinName(name, revision.map(Revision::toString).orElse(null));
55 * Returns well-formed file name of YIN file as defined in RFC6020.
57 * @param name name Module or submodule name
58 * @param revision Revision of module or submodule
59 * @return well-formed file name of YIN file as defined in RFC6020.
61 public static String wellFormedYinName(final String name, final String revision) {
62 if (revision == null) {
63 return name + YangConstants.RFC6020_YIN_FILE_EXTENSION;
65 return requireNonNull(name) + '@' + revision + YangConstants.RFC6020_YIN_FILE_EXTENSION;
69 * Write a module as a YIN text into specified {@link OutputStream}. Supplied module must have the
70 * {@link ModuleEffectiveStatement} trait.
72 * @param module Module to be exported
73 * @throws IllegalArgumentException if the module is not an ModuleEffectiveStatement or if it declared
74 * representation is not available.
75 * @throws NullPointerException if any of of the parameters is null
76 * @throws XMLStreamException if an input-output error occurs
79 public static void writeModuleAsYinText(final Module module, final OutputStream output) throws XMLStreamException {
80 requireNonNull(module);
81 checkArgument(module instanceof ModuleEffectiveStatement, "Module %s is not a ModuleEffectiveStatement",
83 final ModuleEffectiveStatement effective = (ModuleEffectiveStatement) module;
84 writeReaderToOutput(YinXMLEventReaderFactory.defaultInstance().createXMLEventReader(effective), output);
88 * Write a submodule as a YIN text into specified {@link OutputStream}. Supplied submodule must have the
89 * {@link SubmoduleEffectiveStatement} trait.
91 * @param parentModule Parent module
92 * @param submodule Submodule to be exported
93 * @throws IllegalArgumentException if the parent module is not a ModuleEffectiveStatement, if the submodule is not
94 * a SubmoduleEffectiveStatement or if its declared representation is not available
95 * @throws NullPointerException if any of of the parameters is null
96 * @throws XMLStreamException if an input-output error occurs
99 public static void writeSubmoduleAsYinText(final Module parentModule, final Module submodule,
100 final OutputStream output) throws XMLStreamException {
101 requireNonNull(parentModule);
102 checkArgument(parentModule instanceof ModuleEffectiveStatement, "Parent %s is not a ModuleEffectiveStatement",
104 requireNonNull(submodule);
105 checkArgument(submodule instanceof SubmoduleEffectiveStatement,
106 "Submodule %s is not a SubmoduleEffectiveStatement", submodule);
107 writeReaderToOutput(YinXMLEventReaderFactory.defaultInstance().createXMLEventReader(
108 (ModuleEffectiveStatement) parentModule, (SubmoduleEffectiveStatement)submodule), output);
111 private static Map<String, URI> prefixToNamespace(final SchemaContext ctx, final Module module) {
112 final BiMap<String, URI> prefixMap = HashBiMap.create(module.getImports().size() + 1);
113 prefixMap.put(module.getPrefix(), module.getNamespace());
114 for (final ModuleImport imp : module.getImports()) {
115 final String prefix = imp.getPrefix();
116 final URI namespace = getModuleNamespace(ctx, imp.getModuleName());
117 prefixMap.put(prefix, namespace);
122 private static URI getModuleNamespace(final SchemaContext ctx, final String moduleName) {
123 for (final Module module : ctx.getModules()) {
124 if (moduleName.equals(module.getName())) {
125 return module.getNamespace();
128 throw new IllegalArgumentException("Module " + moduleName + "does not exists in provided schema context");
131 private static void writeReaderToOutput(final XMLEventReader reader, final OutputStream output)
132 throws XMLStreamException {
134 final Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
135 transformer.setOutputProperty(OutputKeys.INDENT, "yes");
136 transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");
137 transformer.transform(new StAXSource(reader), new StreamResult(output));
138 } catch (TransformerException e) {
139 throw new XMLStreamException("Failed to stream XML events", e);