Merge branch 'master' of ../controller
[yangtools.git] / yang / yang-model-export / src / main / java / org / opendaylight / yangtools / yang / model / export / ModuleNamespaceContext.java
1 /*
2  * Copyright (c) 2018 Pantheon Technologies, s.r.o. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.yang.model.export;
9
10 import static com.google.common.base.Preconditions.checkArgument;
11 import static java.util.Objects.requireNonNull;
12
13 import com.google.common.collect.ImmutableListMultimap;
14 import com.google.common.collect.ImmutableListMultimap.Builder;
15 import com.google.common.collect.Iterators;
16 import com.google.common.collect.ListMultimap;
17 import com.google.common.collect.Maps;
18 import java.util.AbstractMap.SimpleImmutableEntry;
19 import java.util.Iterator;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Map.Entry;
23 import java.util.Optional;
24 import javax.xml.XMLConstants;
25 import javax.xml.namespace.NamespaceContext;
26 import org.eclipse.jdt.annotation.NonNull;
27 import org.opendaylight.yangtools.yang.common.QName;
28 import org.opendaylight.yangtools.yang.common.QNameModule;
29 import org.opendaylight.yangtools.yang.common.YangConstants;
30 import org.opendaylight.yangtools.yang.model.api.stmt.ModuleEffectiveStatement;
31 import org.opendaylight.yangtools.yang.model.api.stmt.ModuleEffectiveStatement.PrefixToEffectiveModuleNamespace;
32 import org.opendaylight.yangtools.yang.model.api.stmt.ModuleEffectiveStatement.QNameModuleToPrefixNamespace;
33
34 final class ModuleNamespaceContext implements NamespaceContext {
35     private static final Entry<String, String> YIN_PREFIX_AND_NAMESPACE =
36             new SimpleImmutableEntry<>(XMLConstants.DEFAULT_NS_PREFIX, YangConstants.RFC6020_YIN_NAMESPACE_STRING);
37
38     private final ListMultimap<@NonNull String, @NonNull String> namespaceToPrefix;
39     private final Map<String, @NonNull ModuleEffectiveStatement> prefixToModule;
40     private final Map<QNameModule, @NonNull String> moduleToPrefix;
41
42     ModuleNamespaceContext(final ModuleEffectiveStatement module) {
43         this.prefixToModule = requireNonNull(module.getAll(PrefixToEffectiveModuleNamespace.class));
44         this.moduleToPrefix = requireNonNull(module.getAll(QNameModuleToPrefixNamespace.class));
45
46         final Builder<String, String> namespaces = ImmutableListMultimap.builder();
47         for (Entry<QNameModule, @NonNull String> e : moduleToPrefix.entrySet()) {
48             namespaces.put(e.getKey().getNamespace().toString(), e.getValue());
49         }
50         namespaceToPrefix = namespaces.build();
51     }
52
53     @Override
54     public String getNamespaceURI(final String prefix) {
55         checkArgument(prefix != null);
56
57         switch (prefix) {
58             case XMLConstants.DEFAULT_NS_PREFIX:
59                 return YangConstants.RFC6020_YIN_NAMESPACE_STRING;
60             case XMLConstants.XML_NS_PREFIX:
61                 return XMLConstants.XML_NS_URI;
62             case XMLConstants.XMLNS_ATTRIBUTE:
63                 return XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
64             default:
65                 final ModuleEffectiveStatement module = prefixToModule.get(prefix);
66                 return module != null ? module.localQNameModule().getNamespace().toString()
67                         : XMLConstants.NULL_NS_URI;
68         }
69     }
70
71     @Override
72     public String getPrefix(final String namespaceURI) {
73         checkArgument(namespaceURI != null);
74
75         switch (namespaceURI) {
76             case YangConstants.RFC6020_YIN_NAMESPACE_STRING:
77                 return XMLConstants.DEFAULT_NS_PREFIX;
78             case XMLConstants.XML_NS_URI:
79                 return XMLConstants.XML_NS_PREFIX;
80             case XMLConstants.XMLNS_ATTRIBUTE_NS_URI:
81                 return XMLConstants.XMLNS_ATTRIBUTE;
82             default:
83                 final List<@NonNull String> prefixes = namespaceToPrefix.get(namespaceURI);
84                 return prefixes.isEmpty() ? null : prefixes.get(0);
85         }
86     }
87
88     @Override
89     public Iterator<String> getPrefixes(final String namespaceURI) {
90         checkArgument(namespaceURI != null);
91
92         switch (namespaceURI) {
93             case YangConstants.RFC6020_YIN_NAMESPACE_STRING:
94                 return Iterators.singletonIterator(XMLConstants.DEFAULT_NS_PREFIX);
95             case XMLConstants.XML_NS_URI:
96                 return Iterators.singletonIterator(XMLConstants.XML_NS_PREFIX);
97             case XMLConstants.XMLNS_ATTRIBUTE_NS_URI:
98                 return Iterators.singletonIterator(XMLConstants.XMLNS_ATTRIBUTE);
99             default:
100                 return namespaceToPrefix.get(namespaceURI).iterator();
101         }
102     }
103
104     Entry<String, String> prefixAndNamespaceFor(final QNameModule module) {
105         if (YangConstants.RFC6020_YIN_MODULE.equals(module)) {
106             return YIN_PREFIX_AND_NAMESPACE;
107         }
108
109         final String prefix = moduleToPrefix.get(module);
110         checkArgument(prefix != null, "Module %s does not map to a prefix", module);
111         return new SimpleImmutableEntry<>(prefix, module.getNamespace().toString());
112     }
113
114     Entry<String, String> prefixAndNamespaceForStatement(final QName stmtName) {
115         final Optional<String> prefix = ExportUtils.statementPrefix(moduleToPrefix, stmtName);
116         if (!prefix.isPresent()) {
117             return YIN_PREFIX_AND_NAMESPACE;
118         }
119
120         return new SimpleImmutableEntry<>(prefix.get(), stmtName.getNamespace().toString());
121     }
122
123     Map<String, String> prefixesAndNamespaces() {
124         return Maps.transformValues(prefixToModule, module -> module.localQNameModule().getNamespace().toString());
125     }
126 }