import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
import java.util.Map;
import java.util.Optional;
import org.eclipse.jdt.annotation.NonNull;
*/
public abstract static class DefaultWithSchemaTree<A, D extends DeclaredStatement<A>,
E extends SchemaTreeAwareEffectiveStatement<A, D>> extends WithSchemaTree<A, D, E> {
- private final @NonNull ImmutableMap<QName, SchemaTreeEffectiveStatement<?>> schemaTree;
+ private final @NonNull Map<QName, SchemaTreeEffectiveStatement<?>> schemaTree;
private final @NonNull Object substatements;
private final @NonNull D declared;
final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
this.declared = requireNonNull(declared);
this.substatements = maskList(substatements);
- this.schemaTree = ImmutableMap.copyOf(createSchemaTreeNamespace(substatements));
+ this.schemaTree = immutableNamespaceOf(createSchemaTreeNamespace(substatements));
}
protected DefaultWithSchemaTree(final DefaultWithSchemaTree<A, D, E> original) {
}
}
- private final @NonNull ImmutableMap<QName, SchemaTreeEffectiveStatement<?>> schemaTree;
- private final @NonNull ImmutableMap<QName, DataTreeEffectiveStatement<?>> dataTree;
+ private final @NonNull Map<QName, SchemaTreeEffectiveStatement<?>> schemaTree;
+ private final @NonNull Map<QName, DataTreeEffectiveStatement<?>> dataTree;
private final @NonNull Object substatements;
private final @NonNull D declared;
// Note we call schema.values() so we do not retain them, as that is just pure memory overhead
final Map<QName, SchemaTreeEffectiveStatement<?>> schema = createSchemaTreeNamespace(substatements);
- this.schemaTree = ImmutableMap.copyOf(schema);
+ this.schemaTree = immutableNamespaceOf(schema);
this.dataTree = createDataTreeNamespace(schema.values(), schemaTree);
}
return schemaChildren;
}
- protected static @NonNull ImmutableMap<QName, DataTreeEffectiveStatement<?>> createDataTreeNamespace(
+ protected static @NonNull Map<QName, DataTreeEffectiveStatement<?>> createDataTreeNamespace(
final Collection<SchemaTreeEffectiveStatement<?>> schemaTreeStatements,
// Note: this dance is needed to not retain ImmutableMap$Values
- final ImmutableMap<QName, SchemaTreeEffectiveStatement<?>> schemaTreeNamespace) {
+ final Map<QName, SchemaTreeEffectiveStatement<?>> schemaTreeNamespace) {
final Map<QName, DataTreeEffectiveStatement<?>> dataChildren = new LinkedHashMap<>();
boolean sameAsSchema = true;
// This is a mighty hack to lower memory usage: if we consumed all schema tree children as data nodes,
// the two maps are equal and hence we can share the instance.
- return sameAsSchema ? (ImmutableMap) schemaTreeNamespace : ImmutableMap.copyOf(dataChildren);
+ return sameAsSchema ? (Map) schemaTreeNamespace : immutableNamespaceOf(dataChildren);
+ }
+
+ protected static <T extends SchemaTreeEffectiveStatement<?>> @NonNull Map<QName, T> immutableNamespaceOf(
+ final Map<QName, T> map) {
+ return map.size() == 1 ? new SingletonNamespace<>(map.values().iterator().next()) : ImmutableMap.copyOf(map);
}
protected static @NonNull HashMap<QName, TypedefEffectiveStatement> createTypedefNamespace(
import com.google.common.annotations.Beta;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
import java.util.Map;
import java.util.Optional;
import org.eclipse.jdt.annotation.NonNull;
*/
public abstract static class DefaultWithSchemaTree<A, D extends DeclaredStatement<A>,
E extends SchemaTreeAwareEffectiveStatement<A, D>> extends WithSchemaTree<A, D, E> {
- private final @NonNull ImmutableMap<QName, SchemaTreeEffectiveStatement<?>> schemaTree;
+ private final @NonNull Map<QName, SchemaTreeEffectiveStatement<?>> schemaTree;
private final @NonNull Object substatements;
protected DefaultWithSchemaTree(final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
this.substatements = maskList(substatements);
- this.schemaTree = ImmutableMap.copyOf(createSchemaTreeNamespace(substatements));
+ this.schemaTree = immutableNamespaceOf(createSchemaTreeNamespace(substatements));
}
protected DefaultWithSchemaTree(final DefaultWithSchemaTree<A, D, E> original) {
*/
public abstract static class DefaultWithDataTree<A, D extends DeclaredStatement<A>,
E extends DataTreeAwareEffectiveStatement<A, D>> extends WithDataTree<A, D, E> {
- private final @NonNull ImmutableMap<QName, SchemaTreeEffectiveStatement<?>> schemaTree;
- private final @NonNull ImmutableMap<QName, DataTreeEffectiveStatement<?>> dataTree;
+ private final @NonNull Map<QName, SchemaTreeEffectiveStatement<?>> schemaTree;
+ private final @NonNull Map<QName, DataTreeEffectiveStatement<?>> dataTree;
private final @NonNull Object substatements;
protected DefaultWithDataTree(final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
final Map<QName, SchemaTreeEffectiveStatement<?>> schema = createSchemaTreeNamespace(substatements);
- this.schemaTree = ImmutableMap.copyOf(schema);
+ this.schemaTree = immutableNamespaceOf(schema);
this.dataTree = createDataTreeNamespace(schema.values(), schemaTree);
this.substatements = maskList(substatements);
}
--- /dev/null
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others. 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.spi.meta;
+
+import static java.util.Objects.requireNonNull;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.stmt.NamespacedEffectiveStatement;
+
+final class SingletonNamespace<T extends NamespacedEffectiveStatement<?>> implements Map<QName, T> {
+ private final @NonNull T item;
+
+ SingletonNamespace(final T item) {
+ this.item = requireNonNull(item);
+ }
+
+ @Override
+ public int size() {
+ return 1;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return false;
+ }
+
+ @Override
+ public boolean containsKey(final Object key) {
+ return key.equals(item.argument());
+ }
+
+ @Override
+ public boolean containsValue(final Object value) {
+ return value.equals(item);
+ }
+
+ @Override
+ public T get(final Object key) {
+ return containsKey(key) ? item : null;
+ }
+
+ @Override
+ public T put(final QName key, final T value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public T remove(final Object key) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ @SuppressWarnings("checkstyle:parameterName")
+ public void putAll(final Map<? extends QName, ? extends T> m) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Set<QName> keySet() {
+ return Set.of(item.argument());
+ }
+
+ @Override
+ public Collection<T> values() {
+ return List.of(item);
+ }
+
+ @Override
+ public Set<Entry<QName, T>> entrySet() {
+ return Set.of(Map.entry(item.argument(), item));
+ }
+
+ @Override
+ public int hashCode() {
+ return item.getIdentifier().hashCode() ^ item.hashCode();
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (obj == this) {
+ return true;
+ }
+ if (obj instanceof SingletonNamespace) {
+ return item.equals(((SingletonNamespace<?>) obj).item);
+ }
+ if (obj instanceof Map) {
+ final var it = ((Map<?, ?>) obj).entrySet().iterator();
+ if (it.hasNext()) {
+ final var entry = it.next();
+ if (!it.hasNext() && item.argument().equals(entry.getKey()) && item.equals(entry.getValue())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "{" + item.argument() + "=" + item + "}";
+ }
+}