12df3824833fba12aa32fc52626694114385066b
[yangtools.git] / model / 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.Iterators;
15 import com.google.common.collect.ListMultimap;
16 import java.util.Collection;
17 import java.util.Iterator;
18 import java.util.Map;
19 import java.util.Map.Entry;
20 import javax.xml.XMLConstants;
21 import javax.xml.namespace.NamespaceContext;
22 import org.eclipse.jdt.annotation.NonNull;
23 import org.opendaylight.yangtools.yang.common.QNameModule;
24 import org.opendaylight.yangtools.yang.common.YangConstants;
25 import org.opendaylight.yangtools.yang.model.api.stmt.ModuleEffectiveStatement;
26
27 final class ModuleNamespaceContext implements NamespaceContext {
28     private static final Entry<String, String> YIN_PREFIX_AND_NAMESPACE =
29             Map.entry(XMLConstants.DEFAULT_NS_PREFIX, YangConstants.RFC6020_YIN_NAMESPACE_STRING);
30
31     private final ListMultimap<@NonNull String, @NonNull String> namespaceToPrefix;
32     private final ModuleEffectiveStatement module;
33
34     ModuleNamespaceContext(final ModuleEffectiveStatement module) {
35         this.module = requireNonNull(module);
36
37         final var namespaces = ImmutableListMultimap.<String, String>builder();
38         for (var entry : module.namespacePrefixes()) {
39             namespaces.put(entry.getKey().namespace().toString(), entry.getValue());
40         }
41         namespaceToPrefix = namespaces.build();
42     }
43
44     @Override
45     public String getNamespaceURI(final String prefix) {
46         checkArgument(prefix != null);
47
48         return switch (prefix) {
49             case XMLConstants.DEFAULT_NS_PREFIX -> YangConstants.RFC6020_YIN_NAMESPACE_STRING;
50             case XMLConstants.XML_NS_PREFIX -> XMLConstants.XML_NS_URI;
51             case XMLConstants.XMLNS_ATTRIBUTE -> XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
52             default -> module.findReachableModule(prefix)
53                 .map(importedModule -> importedModule.localQNameModule().namespace().toString())
54                 .orElse(XMLConstants.NULL_NS_URI);
55         };
56     }
57
58     @Override
59     public String getPrefix(final String namespaceURI) {
60         checkArgument(namespaceURI != null);
61
62         return switch (namespaceURI) {
63             case YangConstants.RFC6020_YIN_NAMESPACE_STRING -> XMLConstants.DEFAULT_NS_PREFIX;
64             case XMLConstants.XML_NS_URI -> XMLConstants.XML_NS_PREFIX;
65             case XMLConstants.XMLNS_ATTRIBUTE_NS_URI -> XMLConstants.XMLNS_ATTRIBUTE;
66             default -> {
67                 final var prefixes = namespaceToPrefix.get(namespaceURI);
68                 yield prefixes.isEmpty() ? null : prefixes.get(0);
69             }
70         };
71     }
72
73     @Override
74     public Iterator<String> getPrefixes(final String namespaceURI) {
75         checkArgument(namespaceURI != null);
76
77         return switch (namespaceURI) {
78             case YangConstants.RFC6020_YIN_NAMESPACE_STRING ->
79                 Iterators.singletonIterator(XMLConstants.DEFAULT_NS_PREFIX);
80             case XMLConstants.XML_NS_URI -> Iterators.singletonIterator(XMLConstants.XML_NS_PREFIX);
81             case XMLConstants.XMLNS_ATTRIBUTE_NS_URI -> Iterators.singletonIterator(XMLConstants.XMLNS_ATTRIBUTE);
82             default -> namespaceToPrefix.get(namespaceURI).iterator();
83         };
84     }
85
86     Entry<String, String> prefixAndNamespaceFor(final QNameModule namespace) {
87         if (YangConstants.RFC6020_YIN_MODULE.equals(namespace)) {
88             return YIN_PREFIX_AND_NAMESPACE;
89         }
90
91         final String prefix = module.findNamespacePrefix(namespace)
92             .orElseThrow(() -> new IllegalArgumentException("Module " + namespace + " does not map to a prefix"));
93         return Map.entry(prefix, namespace.namespace().toString());
94     }
95
96     Collection<Entry<String, ModuleEffectiveStatement>> importedModules() {
97         return module.reachableModules();
98     }
99 }