BindingRuntimeTypes should be an interface
[mdsal.git] / binding / mdsal-binding-runtime-api / src / main / java / org / opendaylight / mdsal / binding / runtime / api / BindingRuntimeTypes.java
index 70622a9da979e995959e50f5ffbf95d84a463bc4..d0ac16642ab2fbe5979223eccbdfe1f15bd1d7fb 100644 (file)
  */
 package org.opendaylight.mdsal.binding.runtime.api;
 
-import static java.util.Objects.requireNonNull;
-
 import com.google.common.annotations.Beta;
-import com.google.common.base.MoreObjects;
-import com.google.common.collect.BiMap;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableMultimap;
 import com.google.common.collect.Multimap;
-import java.lang.invoke.MethodHandles;
-import java.lang.invoke.VarHandle;
 import java.util.Collection;
-import java.util.IdentityHashMap;
-import java.util.Map;
 import java.util.Optional;
-import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.mdsal.binding.model.api.Type;
 import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DocumentedNode.WithStatus;
-import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
 import org.opendaylight.yangtools.yang.model.api.EffectiveModelContextProvider;
-import org.opendaylight.yangtools.yang.model.api.SchemaNode;
-import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absolute;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * The result of BindingGenerator run. Contains mapping between Types and SchemaNodes.
  */
 @Beta
-public final class BindingRuntimeTypes implements EffectiveModelContextProvider, Immutable {
-    private static final Logger LOG = LoggerFactory.getLogger(BindingRuntimeTypes.class);
-    private static final VarHandle TYPE_TO_IDENTIFIER;
-
-    static {
-        try {
-            TYPE_TO_IDENTIFIER = MethodHandles.lookup().findVarHandle(BindingRuntimeTypes.class, "typeToIdentifier",
-                ImmutableMap.class);
-        } catch (NoSuchFieldException | IllegalAccessException e) {
-            throw new ExceptionInInitializerError(e);
-        }
-    }
-
-    private final @NonNull EffectiveModelContext schemaContext;
-    private final ImmutableMap<Type, AugmentationSchemaNode> typeToAugmentation;
-    private final ImmutableMap<Type, WithStatus> typeToSchema;
-    private final ImmutableMultimap<Type, Type> choiceToCases;
-    private final ImmutableMap<QName, Type> identities;
-    // Not Immutable as we use two different implementations
-    private final Map<WithStatus, Type> schemaToType;
-
-    @SuppressWarnings("unused")
-    // Accessed via TYPE_TO_IDENTIFIER
-    private volatile ImmutableMap<Type, Absolute> typeToIdentifier = ImmutableMap.of();
-
-    public BindingRuntimeTypes(final EffectiveModelContext schemaContext,
-            final Map<Type, AugmentationSchemaNode> typeToAugmentation,
-            final Map<Type, WithStatus> typeToSchema, final Map<WithStatus, Type> schemaToType,
-            final Multimap<Type, Type> choiceToCases, final Map<QName, Type> identities) {
-        this.schemaContext = requireNonNull(schemaContext);
-        this.typeToAugmentation = ImmutableMap.copyOf(typeToAugmentation);
-        this.typeToSchema = ImmutableMap.copyOf(typeToSchema);
-        this.choiceToCases = ImmutableMultimap.copyOf(choiceToCases);
-        this.identities = ImmutableMap.copyOf(identities);
-
-        // Careful to use identity for SchemaNodes, but only if needed
-        // FIXME: 8.0.0: YT should be switching to identity for equals(), so this should become unnecessary
-        Map<WithStatus, Type> copy;
-        try {
-            copy = ImmutableMap.copyOf(schemaToType);
-        } catch (IllegalArgumentException e) {
-            LOG.debug("Equality-duplicates found in {}", schemaToType.keySet());
-            copy = new IdentityHashMap<>(schemaToType);
-        }
-
-        this.schemaToType = copy;
-    }
-
-    public BindingRuntimeTypes(final EffectiveModelContext schemaContext,
-            final Map<Type, AugmentationSchemaNode> typeToAugmentation,
-            final BiMap<Type, WithStatus> typeToDefiningSchema,
-            final Multimap<Type, Type> choiceToCases, final Map<QName, Type> identities) {
-        this(schemaContext, typeToAugmentation, typeToDefiningSchema, typeToDefiningSchema.inverse(), choiceToCases,
-            identities);
-    }
-
-    @Override
-    public EffectiveModelContext getEffectiveModelContext() {
-        return schemaContext;
-    }
-
-    public Optional<AugmentationSchemaNode> findAugmentation(final Type type) {
-        return Optional.ofNullable(typeToAugmentation.get(type));
-    }
-
-    public Optional<Type> findIdentity(final QName qname) {
-        return Optional.ofNullable(identities.get(qname));
-    }
-
-    public Optional<WithStatus> findSchema(final Type type) {
-        return Optional.ofNullable(typeToSchema.get(type));
-    }
-
-    public Optional<Absolute> findSchemaNodeIdentifier(final Type type) {
-        final ImmutableMap<Type, Absolute> local = (ImmutableMap<Type, Absolute>) TYPE_TO_IDENTIFIER.getAcquire(this);
-        final Absolute existing = local.get(type);
-        return existing != null ? Optional.of(existing) : loadSchemaNodeIdentifier(local, type);
-    }
-
-    public Optional<Type> findType(final WithStatus schema) {
-        return Optional.ofNullable(schemaToType.get(schema));
-    }
-
-    public Multimap<Type, Type> getChoiceToCases() {
-        return choiceToCases;
-    }
-
-    public Collection<Type> findCases(final Type choiceType) {
-        return choiceToCases.get(choiceType);
-    }
+public interface BindingRuntimeTypes extends EffectiveModelContextProvider, Immutable {
 
-    @Override
-    public String toString() {
-        return MoreObjects.toStringHelper(this)
-                .add("typeToAugmentation", typeToAugmentation)
-                .add("typeToSchema", typeToSchema)
-                .add("choiceToCases", choiceToCases)
-                .add("identities", identities)
-                .toString();
-    }
+    Optional<AugmentationSchemaNode> findAugmentation(Type type);
 
-    private Optional<Absolute> loadSchemaNodeIdentifier(final ImmutableMap<Type, Absolute> local, final Type type) {
-        final WithStatus schema = typeToSchema.get(type);
-        if (!(schema instanceof SchemaNode)) {
-            return Optional.empty();
-        }
+    Optional<Type> findIdentity(QName qname);
 
-        // TODO: do not rely on getPath() here
-        final Absolute created = Absolute.of(ImmutableList.copyOf(((SchemaNode) schema).getPath().getPathFromRoot()))
-                .intern();
+    Optional<WithStatus> findSchema(Type type);
 
-        ImmutableMap<Type, Absolute> prev = local;
-        while (true) {
-            // Compute next cache
-            final ImmutableMap<Type, Absolute> next =
-                    ImmutableMap.<Type, Absolute>builderWithExpectedSize(prev.size() + 1)
-                        .putAll(prev)
-                        .put(type, created).build();
+    Optional<Type> findType(WithStatus schema);
 
-            final Object witness = TYPE_TO_IDENTIFIER.compareAndExchangeRelease(this, prev, next);
-            if (witness == prev) {
-                // Cache populated successfully, we are all done now
-                return Optional.of(created);
-            }
+    Optional<Type> findOriginalAugmentationType(AugmentationSchemaNode augment);
 
-            // Remember cache for next computation
-            prev = (ImmutableMap<Type, Absolute>) witness;
-            final Absolute raced = prev.get(type);
-            if (raced != null) {
-                // We have raced on this item, use it from cache
-                return Optional.of(raced);
-            }
+    Multimap<Type, Type> getChoiceToCases();
 
-            // We have raced on a different item, loop around and repeat
-        }
-    }
+    Collection<Type> findCases(Type choiceType);
 }