Make SchemaNode.getPath() implementations as deprecated
[yangtools.git] / yang / yang-model-util / src / main / java / org / opendaylight / yangtools / yang / model / util / AbstractSchemaContext.java
index 035173508f9bfbd8b548bf9f3180afc7249f2ee4..ad3aa608f096020a392cfbd55389e6a0aead36e0 100644 (file)
@@ -8,13 +8,21 @@
 
 package org.opendaylight.yangtools.yang.model.util;
 
+import static com.google.common.base.Preconditions.checkArgument;
 import static java.util.Objects.requireNonNull;
 
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Multimaps;
 import com.google.common.collect.SetMultimap;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
 import java.net.URI;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.List;
@@ -29,6 +37,7 @@ import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition;
 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
+import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
@@ -68,6 +77,21 @@ public abstract class AbstractSchemaContext implements SchemaContext {
         return new TreeSet<>(REVISION_COMPARATOR);
     }
 
+    private static final VarHandle DERIVED_IDENTITIES;
+
+    static {
+        try {
+            DERIVED_IDENTITIES = MethodHandles.lookup().findVarHandle(AbstractSchemaContext.class, "derivedIdentities",
+                ImmutableMap.class);
+        } catch (NoSuchFieldException | IllegalAccessException e) {
+            throw new ExceptionInInitializerError(e);
+        }
+    }
+
+    // Accessed via DERIVED_IDENTITIES
+    @SuppressWarnings("unused")
+    private volatile ImmutableMap<IdentitySchemaNode, ImmutableSet<IdentitySchemaNode>> derivedIdentities = null;
+
     /**
      * Returns the namespace-to-module mapping.
      *
@@ -90,7 +114,7 @@ public abstract class AbstractSchemaContext implements SchemaContext {
     protected abstract Map<QNameModule, Module> getModuleMap();
 
     @Override
-    public Set<DataSchemaNode> getDataDefinitions() {
+    public Collection<? extends DataSchemaNode> getDataDefinitions() {
         final Set<DataSchemaNode> dataDefs = new HashSet<>();
         for (Module m : getModules()) {
             dataDefs.addAll(m.getChildNodes());
@@ -99,7 +123,7 @@ public abstract class AbstractSchemaContext implements SchemaContext {
     }
 
     @Override
-    public Set<NotificationDefinition> getNotifications() {
+    public Collection<? extends NotificationDefinition> getNotifications() {
         final Set<NotificationDefinition> notifications = new HashSet<>();
         for (Module m : getModules()) {
             notifications.addAll(m.getNotifications());
@@ -108,7 +132,7 @@ public abstract class AbstractSchemaContext implements SchemaContext {
     }
 
     @Override
-    public Set<RpcDefinition> getOperations() {
+    public Collection<? extends RpcDefinition> getOperations() {
         final Set<RpcDefinition> rpcs = new HashSet<>();
         for (Module m : getModules()) {
             rpcs.addAll(m.getRpcs());
@@ -117,7 +141,7 @@ public abstract class AbstractSchemaContext implements SchemaContext {
     }
 
     @Override
-    public Set<ExtensionDefinition> getExtensions() {
+    public Collection<? extends ExtensionDefinition> getExtensions() {
         final Set<ExtensionDefinition> extensions = new HashSet<>();
         for (Module m : getModules()) {
             extensions.addAll(m.getExtensionSchemaNodes());
@@ -126,7 +150,7 @@ public abstract class AbstractSchemaContext implements SchemaContext {
     }
 
     @Override
-    public Optional<Module> findModule(final String name, final Optional<Revision> revision) {
+    public Optional<? extends Module> findModule(final String name, final Optional<Revision> revision) {
         for (final Module module : getNameToModules().get(name)) {
             if (revision.equals(module.getRevision())) {
                 return Optional.of(module);
@@ -142,12 +166,12 @@ public abstract class AbstractSchemaContext implements SchemaContext {
     }
 
     @Override
-    public Set<Module> findModules(final URI namespace) {
+    public Collection<? extends Module> findModules(final URI namespace) {
         return getNamespaceToModules().get(namespace);
     }
 
     @Override
-    public Set<Module> findModules(final String name) {
+    public Collection<? extends Module> findModules(final String name) {
         return getNameToModules().get(name);
     }
 
@@ -170,10 +194,12 @@ public abstract class AbstractSchemaContext implements SchemaContext {
 
     @Override
     public QName getQName() {
+        // FIXME: YANGTOOLS-1074: we do not want this name
         return SchemaContext.NAME;
     }
 
     @Override
+    @Deprecated
     public SchemaPath getPath() {
         return SchemaPath.ROOT;
     }
@@ -184,7 +210,7 @@ public abstract class AbstractSchemaContext implements SchemaContext {
     }
 
     @Override
-    public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+    public Collection<? extends UnknownSchemaNode> getUnknownSchemaNodes() {
         final List<UnknownSchemaNode> result = new ArrayList<>();
         for (Module module : getModules()) {
             result.addAll(module.getUnknownSchemaNodes());
@@ -193,7 +219,7 @@ public abstract class AbstractSchemaContext implements SchemaContext {
     }
 
     @Override
-    public Set<TypeDefinition<?>> getTypeDefinitions() {
+    public Collection<? extends TypeDefinition<?>> getTypeDefinitions() {
         final Set<TypeDefinition<?>> result = new LinkedHashSet<>();
         for (Module module : getModules()) {
             result.addAll(module.getTypeDefinitions());
@@ -202,7 +228,7 @@ public abstract class AbstractSchemaContext implements SchemaContext {
     }
 
     @Override
-    public Set<DataSchemaNode> getChildNodes() {
+    public Collection<? extends DataSchemaNode> getChildNodes() {
         final Set<DataSchemaNode> result = new LinkedHashSet<>();
         for (Module module : getModules()) {
             result.addAll(module.getChildNodes());
@@ -211,7 +237,7 @@ public abstract class AbstractSchemaContext implements SchemaContext {
     }
 
     @Override
-    public Set<GroupingDefinition> getGroupings() {
+    public Collection<? extends GroupingDefinition> getGroupings() {
         final Set<GroupingDefinition> result = new LinkedHashSet<>();
         for (Module module : getModules()) {
             result.addAll(module.getGroupings());
@@ -232,7 +258,7 @@ public abstract class AbstractSchemaContext implements SchemaContext {
     }
 
     @Override
-    public Set<UsesNode> getUses() {
+    public Collection<? extends UsesNode> getUses() {
         return Collections.emptySet();
     }
 
@@ -242,7 +268,45 @@ public abstract class AbstractSchemaContext implements SchemaContext {
     }
 
     @Override
-    public Set<AugmentationSchemaNode> getAvailableAugmentations() {
+    public Collection<? extends AugmentationSchemaNode> getAvailableAugmentations() {
         return Collections.emptySet();
     }
+
+    @Override
+    public Collection<? extends IdentitySchemaNode> getDerivedIdentities(final IdentitySchemaNode identity) {
+        ImmutableMap<IdentitySchemaNode, ImmutableSet<IdentitySchemaNode>> local =
+                (ImmutableMap<IdentitySchemaNode, ImmutableSet<IdentitySchemaNode>>)
+                DERIVED_IDENTITIES.getAcquire(this);
+        if (local == null) {
+            local = loadDerivedIdentities();
+        }
+        final ImmutableSet<IdentitySchemaNode> result = local.get(requireNonNull(identity));
+        checkArgument(result != null, "Identity %s not found", identity);
+        return result;
+    }
+
+    private ImmutableMap<IdentitySchemaNode, ImmutableSet<IdentitySchemaNode>> loadDerivedIdentities() {
+        final SetMultimap<IdentitySchemaNode, IdentitySchemaNode> tmp =
+                Multimaps.newSetMultimap(new HashMap<>(), HashSet::new);
+        final List<IdentitySchemaNode> identities = new ArrayList<>();
+        for (Module module : getModules()) {
+            final Collection<? extends IdentitySchemaNode> ids = module.getIdentities();
+            for (IdentitySchemaNode identity : ids) {
+                for (IdentitySchemaNode base : identity.getBaseIdentities()) {
+                    tmp.put(base, identity);
+                }
+            }
+            identities.addAll(ids);
+        }
+
+        final ImmutableMap.Builder<IdentitySchemaNode, ImmutableSet<IdentitySchemaNode>> builder =
+                ImmutableMap.builderWithExpectedSize(identities.size());
+        for (IdentitySchemaNode identity : identities) {
+            builder.put(identity, ImmutableSet.copyOf(tmp.get(identity)));
+        }
+
+        final ImmutableMap<IdentitySchemaNode, ImmutableSet<IdentitySchemaNode>> result = builder.build();
+        final Object witness = DERIVED_IDENTITIES.compareAndExchangeRelease(this, null, result);
+        return witness == null ? result : (ImmutableMap<IdentitySchemaNode, ImmutableSet<IdentitySchemaNode>>) witness;
+    }
 }