import org.opendaylight.yangtools.concepts.WritableObject;
/**
- * A BiMap-based implementation of {@link YangNamespaceContext}. This implementation requires the default namespace
- * to be present.
+ * A BiMap-based implementation of {@link YangNamespaceContext}.
*
+ * @author Robert Varga
*/
@Beta
public final class BiMapYangNamespaceContext implements YangNamespaceContext, WritableObject {
private final ImmutableBiMap<String, QNameModule> mapping;
private final QNameModule defaultNamespace;
- public BiMapYangNamespaceContext(final QNameModule defaultNamespace, final BiMap<String, QNameModule> mapping) {
- this.defaultNamespace = requireNonNull(defaultNamespace);
- checkArgument(mapping.containsValue(defaultNamespace), "Mapping %s does not contain default namespace %s",
- mapping, defaultNamespace);
+ public BiMapYangNamespaceContext(final BiMap<String, QNameModule> mapping) {
+ this(mapping, null);
+ }
+
+ public BiMapYangNamespaceContext(final BiMap<String, QNameModule> mapping,
+ final QNameModule defaultNamespace) {
+ this.defaultNamespace = defaultNamespace;
this.mapping = ImmutableBiMap.copyOf(mapping);
+ if (defaultNamespace != null) {
+ checkArgument(this.mapping.containsValue(defaultNamespace),
+ "Mapping %s does not contain default namespace %s", this.mapping, defaultNamespace);
+ }
}
@Override
public Optional<QNameModule> getDefaultNamespace() {
- return Optional.of(defaultNamespace);
+ return Optional.ofNullable(defaultNamespace);
}
@Override
@Override
public void writeTo(final DataOutput out) throws IOException {
- defaultNamespace.writeTo(out);
+ if (defaultNamespace != null) {
+ out.writeBoolean(true);
+ defaultNamespace.writeTo(out);
+ } else {
+ out.writeBoolean(false);
+ }
+
out.writeInt(mapping.size());
for (Entry<String, QNameModule> entry : mapping.entrySet()) {
out.writeUTF(entry.getKey());
}
public static BiMapYangNamespaceContext readFrom(final DataInput in) throws IOException {
- final QNameModule defaultNamespace = QNameModule.readFrom(in);
+ final boolean haveDefault = in.readBoolean();
+ final QNameModule defaultNamespace = haveDefault ? QNameModule.readFrom(in) : null;
final int size = in.readInt();
final Builder<String, QNameModule> builder = ImmutableBiMap.builder();
for (int i = 0; i < size; ++i) {
builder.put(prefix, namespace);
}
- return new BiMapYangNamespaceContext(defaultNamespace, builder.build());
+ return new BiMapYangNamespaceContext(builder.build(), defaultNamespace);
}
@Override
private static final QNameModule BAR = QNameModule.create(URI.create("bar"));
private static final QNameModule BAZ = QNameModule.create(URI.create("baz"));
- private final BiMapYangNamespaceContext context = new BiMapYangNamespaceContext(FOO,
- ImmutableBiMap.of("foo", FOO, "bar", BAR));
+ private final BiMapYangNamespaceContext context = new BiMapYangNamespaceContext(
+ ImmutableBiMap.of("foo", FOO, "bar", BAR), FOO);
@Test(expected = IllegalArgumentException.class)
public void testUnmappedDefault() {
- new BiMapYangNamespaceContext(FOO, ImmutableBiMap.of());
+ new BiMapYangNamespaceContext(ImmutableBiMap.of(), FOO);
}
@Test
@Test
public void testEquals() {
assertTrue(context.equals(context));
- assertTrue(context.equals(new BiMapYangNamespaceContext(FOO, ImmutableBiMap.of("foo", FOO, "bar", BAR))));
+ assertTrue(context.equals(new BiMapYangNamespaceContext(ImmutableBiMap.of("foo", FOO, "bar", BAR), FOO)));
assertFalse(context.equals(null));
- assertFalse(context.equals(new BiMapYangNamespaceContext(FOO, ImmutableBiMap.of("foo", FOO))));
- assertFalse(context.equals(new BiMapYangNamespaceContext(BAR, ImmutableBiMap.of("bar", BAR))));
+ assertFalse(context.equals(new BiMapYangNamespaceContext(ImmutableBiMap.of("foo", FOO), FOO)));
+ assertFalse(context.equals(new BiMapYangNamespaceContext(ImmutableBiMap.of("bar", BAR), BAR)));
}
@Test
--- /dev/null
+/*
+ * Copyright (c) 2019 Pantheon Technologies, s.r.o. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.model.util;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableBiMap;
+import com.google.common.collect.ImmutableBiMap.Builder;
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import org.opendaylight.yangtools.yang.common.BiMapYangNamespaceContext;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.common.YangNamespaceContext;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
+
+/**
+ * Utility {@link YangNamespaceContext} backed by a SchemaContext, resolving namespaces to their module names. This
+ * is useful for implementing namespace resolution according to
+ * <a href="https://tools.ietf.org/html/rfc7951#section-4">RFC7951 Section 4</a>.
+ *
+ * <p>
+ * When multiple revisions of a particular namespace are present in the backing SchemaContext, this ambiguity is
+ * resolved by using the latest revision available.
+ *
+ * @author Robert Varga
+ */
+@Beta
+public final class ModuleNameNamespaceContext implements YangNamespaceContext, SchemaContextProvider {
+ private static final long serialVersionUID = 1L;
+
+ @SuppressFBWarnings(value = "SE_BAD_FIELD", justification = "Handled through writeReplace()")
+ private final SchemaContext schemaContext;
+
+ public ModuleNameNamespaceContext(final SchemaContext schemaContext) {
+ this.schemaContext = requireNonNull(schemaContext);
+ }
+
+ /**
+ * Convert this object to an equivalent {@link BiMapYangNamespaceContext}.
+ *
+ * @return A BiMapYangNamespaceContext.
+ */
+ public BiMapYangNamespaceContext toBiMap() {
+ final Builder<String, QNameModule> builder = ImmutableBiMap.builder();
+ for (String name : schemaContext.getModules().stream().map(Module::getName).collect(Collectors.toSet())) {
+ builder.put(name, findNamespaceForPrefix(name).get());
+ }
+ return new BiMapYangNamespaceContext(builder.build());
+ }
+
+ @Override
+ public SchemaContext getSchemaContext() {
+ return schemaContext;
+ }
+
+ @Override
+ public Optional<QNameModule> getDefaultNamespace() {
+ throw new IllegalStateException("No default namespace is available");
+ }
+
+ @Override
+ public Optional<QNameModule> findNamespaceForPrefix(final String prefix) {
+ return schemaContext.findModules(prefix).stream().findFirst().map(Module::getQNameModule);
+ }
+
+ @Override
+ public Optional<String> findPrefixForNamespace(final QNameModule namespace) {
+ return schemaContext.findModule(namespace).map(Module::getName);
+ }
+
+ private Object writeReplace() {
+ return toBiMap();
+ }
+}