Modernize SchemaInferenceStack
[yangtools.git] / model / yang-model-util / src / main / java / org / opendaylight / yangtools / yang / model / util / ModuleNameNamespaceContext.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.model.util;
9
10 import static java.util.Objects.requireNonNull;
11
12 import com.google.common.annotations.Beta;
13 import com.google.common.collect.ImmutableBiMap;
14 import java.io.IOException;
15 import java.io.NotSerializableException;
16 import java.io.ObjectInputStream;
17 import java.io.ObjectOutputStream;
18 import java.io.ObjectStreamException;
19 import org.eclipse.jdt.annotation.NonNull;
20 import org.opendaylight.yangtools.yang.common.BiMapYangNamespaceContext;
21 import org.opendaylight.yangtools.yang.common.QNameModule;
22 import org.opendaylight.yangtools.yang.common.YangNamespaceContext;
23 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
24
25 /**
26  * Utility {@link YangNamespaceContext} backed by a SchemaContext, resolving namespaces to their module names. This
27  * is useful for implementing namespace resolution according to
28  * <a href="https://www.rfc-editor.org/rfc/rfc7951#section-4">RFC7951 Section 4</a>.
29  *
30  * <p>
31  * When multiple revisions of a particular namespace are present in the backing SchemaContext, this ambiguity is
32  * resolved by using the latest revision available.
33  */
34 @Beta
35 public final class ModuleNameNamespaceContext implements YangNamespaceContext {
36     @java.io.Serial
37     private static final long serialVersionUID = 2L;
38
39     private final @NonNull EffectiveModelContext modelContext;
40
41     public ModuleNameNamespaceContext(final EffectiveModelContext modelContext) {
42         this.modelContext = requireNonNull(modelContext);
43     }
44
45     /**
46      * Convert this object to an equivalent {@link BiMapYangNamespaceContext}.
47      *
48      * @return A BiMapYangNamespaceContext.
49      */
50     public BiMapYangNamespaceContext toBiMap() {
51         final var builder = ImmutableBiMap.<String, QNameModule>builder();
52         for (var module : modelContext.getModuleStatements().values()) {
53             final var name = module.argument().getLocalName();
54             builder.put(name, findNamespaceForPrefix(name).orElseThrow());
55         }
56         return new BiMapYangNamespaceContext(builder.build());
57     }
58
59     @Override
60     public QNameModule namespaceForPrefix(final String prefix) {
61         final var modules = modelContext.findModuleStatements(prefix).iterator();
62         return modules.hasNext() ? modules.next().localQNameModule() : null;
63     }
64
65     @Override
66     public String prefixForNamespace(final QNameModule namespace) {
67         return modelContext.findModuleStatement(namespace)
68             .map(module -> module.argument().getLocalName())
69             .orElse(null);
70     }
71
72     @java.io.Serial
73     private Object writeReplace() {
74         return toBiMap();
75     }
76
77     @java.io.Serial
78     private void readObject(final ObjectInputStream stream) throws IOException, ClassNotFoundException {
79         throwNSE();
80     }
81
82     @java.io.Serial
83     private void readObjectNoData() throws ObjectStreamException {
84         throwNSE();
85     }
86
87     @java.io.Serial
88     private void writeObject(final ObjectOutputStream stream) throws IOException {
89         throwNSE();
90     }
91
92     private static void throwNSE() throws NotSerializableException {
93         throw new NotSerializableException(ModuleNameNamespaceContext.class.getName());
94     }
95 }