Extend Immutable contract
[yangtools.git] / yang / 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 static com.google.common.base.Preconditions.checkArgument;
11 import static com.google.common.base.Preconditions.checkState;
12 import static java.util.Objects.requireNonNull;
13
14 import com.google.common.annotations.Beta;
15 import java.io.Serializable;
16 import java.util.Optional;
17 import org.eclipse.jdt.annotation.NonNull;
18 import org.opendaylight.yangtools.concepts.Immutable;
19
20 /**
21  * Interface for mapping between {@link String} prefixes and {@link QNameModule} namespaces. The conceptual model
22  * matches prefix mapping inside a YANG {@code module} as defined through the use of {@code prefix} and {@code import}
23  * statements and detailed in <a href="https://tools.ietf.org/html/rfc7950#section-7.1.4">RFC7950 Section 7.1.4</a>.
24  *
25  * <p>
26  * Each namespace context can have a default namespace and a set of prefix/namespace mappings. A namespace can be bound
27  * to multiple prefixes at the same time. The default namespace must also have a prefix assigned.
28  *
29  * @author Robert Varga
30  */
31 @Beta
32 public interface YangNamespaceContext extends Immutable, Serializable {
33     /**
34      * Return the default namespace in this context.
35      *
36      * @return Default namespace, if supported.
37      */
38     @NonNull Optional<QNameModule> getDefaultNamespace();
39
40     /**
41      * Return QNameModule to which a particular prefix is bound.
42      *
43      * @param prefix Prefix to look up
44      * @return QNameModule bound to specified prefix
45      * @throws NullPointerException if {@code prefix} is null
46      */
47     @NonNull Optional<QNameModule> findNamespaceForPrefix(String prefix);
48
49     /**
50      * Return a prefix to which a particular QNameModule is bound. If a namespace is bound to multiple prefixes, it is
51      * left unspecified which of those prefixes is returned.
52      *
53      * @param namespace QNameModule to look up
54      * @return Prefix to which the QNameModule is bound
55      * @throws NullPointerException if {@code module} is null
56      */
57     @NonNull Optional<String> findPrefixForNamespace(QNameModule namespace);
58
59     /**
60      * Create a {@link QName} in the default namespace.
61      *
62      * @param localName QName local name
63      * @return A QName.
64      * @throws NullPointerException if {@code localName} is null
65      * @throws IllegalArgumentException if {@code localName} does not conform to local name requirements
66      * @throws IllegalStateException if this context does not have default namespace
67      */
68     default @NonNull QName createQName(final String localName) {
69         final Optional<QNameModule> namespace = getDefaultNamespace();
70         checkState(namespace.isPresent(), "%s does not have a default namespace", this);
71         return QName.create(namespace.get(), requireNonNull(localName));
72     }
73
74     /**
75      * Create a {@link QName} by resolving a prefix against currently-bound prefixes and combining it with specified
76      * local name.
77      *
78      * @param prefix Namespace prefix
79      * @param localName QName local name
80      * @return A QName.
81      * @throws NullPointerException if any argument is null
82      * @throws IllegalArgumentException if {@code localName} does not conform to local name requirements or if the
83      *                                  prefix is not bound in this context.
84      */
85     default @NonNull QName createQName(final String prefix, final String localName) {
86         final Optional<QNameModule> namespace = findNamespaceForPrefix(prefix);
87         checkArgument(namespace.isPresent(), "Prefix %s is not bound", prefix);
88         return QName.create(namespace.get(), localName);
89     }
90 }