Promote YangNamespaceContext
[yangtools.git] / common / yang-common / src / main / java / org / opendaylight / yangtools / yang / common / YangNamespaceContext.java
1 /*
2  * Copyright (c) 2019 Pantheon Technologies, s.r.o.  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.common;
9
10 import java.io.Serializable;
11 import java.util.Optional;
12 import org.eclipse.jdt.annotation.NonNull;
13 import org.eclipse.jdt.annotation.Nullable;
14 import org.opendaylight.yangtools.concepts.Immutable;
15
16 /**
17  * Interface for mapping between {@link String} prefixes and {@link QNameModule} namespaces. The conceptual model
18  * matches prefix mapping inside a YANG {@code module} as defined through the use of {@code prefix} and {@code import}
19  * statements and detailed in <a href="https://www.rfc-editor.org/rfc/rfc7950#section-7.1.4">RFC7950 Section 7.1.4</a>.
20  *
21  * <p>
22  * Each namespace context has a set of prefix/namespace mappings. A namespace can be bound to multiple prefixes at the
23  * same time.
24  */
25 public interface YangNamespaceContext extends Immutable, Serializable {
26     /**
27      * Return QNameModule to which a particular prefix is bound.
28      *
29      * @param prefix Prefix to look up
30      * @return QNameModule bound to specified prefix, or {@code null}
31      * @throws NullPointerException if {@code prefix} is {@code null}
32      */
33     @Nullable QNameModule namespaceForPrefix(String prefix);
34
35     /**
36      * Return QNameModule to which a particular prefix is bound.
37      *
38      * @implSpec Default implementation defers to {@link #namespaceForPrefix(String)}
39      * @param prefix Prefix to look up
40      * @return QNameModule bound to specified prefix
41      * @throws NullPointerException if {@code prefix} is {@code null}
42      */
43     default @NonNull Optional<QNameModule> findNamespaceForPrefix(final String prefix) {
44         return Optional.ofNullable(namespaceForPrefix(prefix));
45     }
46
47     /**
48      * Return a prefix to which a particular QNameModule is bound. If a namespace is bound to multiple prefixes, it is
49      * left unspecified which of those prefixes is returned.
50      *
51      * @param namespace QNameModule to look up
52      * @return Prefix to which the QNameModule is bound, or {@code null}
53      * @throws NullPointerException if {@code module} is {@code null}
54      */
55     @Nullable String prefixForNamespace(QNameModule namespace);
56
57     /**
58      * Return a prefix to which a particular QNameModule is bound. If a namespace is bound to multiple prefixes, it is
59      * left unspecified which of those prefixes is returned.
60      *
61      * @implSpec Default implementation defers to {@link #prefixForNamespace(QNameModule)}
62      * @param namespace QNameModule to look up
63      * @return Prefix to which the QNameModule is bound
64      * @throws NullPointerException if {@code module} is {@code null}
65      */
66     default @NonNull Optional<String> findPrefixForNamespace(final QNameModule namespace) {
67         return Optional.ofNullable(prefixForNamespace(namespace));
68     }
69
70     /**
71      * Create a {@link QName} by resolving a prefix against currently-bound prefixes and combining it with specified
72      * local name.
73      *
74      * @implSpec
75      *     Default implementation defers to {@link #namespaceForPrefix(String)} and constructs QName based on its
76      *     return.
77      * @param prefix Namespace prefix
78      * @param localName QName local name
79      * @return A QName.
80      * @throws NullPointerException if any argument is null
81      * @throws IllegalArgumentException if {@code localName} does not conform to local name requirements or if the
82      *                                  prefix is not bound in this context.
83      */
84     default @NonNull QName createQName(final String prefix, final String localName) {
85         final var namespace = namespaceForPrefix(prefix);
86         if (namespace == null) {
87             throw new IllegalArgumentException("Prefix " + prefix + " is not bound");
88         }
89         return QName.create(namespace, localName);
90     }
91 }