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 Map<QName, SchemaTreeEffectiveStatement<?>> schemaTree;
+ private final @NonNull ImmutableMap<QName, SchemaTreeEffectiveStatement<?>> schemaTree;
private final @NonNull D declared;
protected DefaultWithSchemaTree(final D declared, final StmtContext<?, ?, ?> ctx,
final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
this.declared = requireNonNull(declared);
- this.schemaTree = AbstractSchemaEffectiveDocumentedNode.createSchemaTreeNamespace(
- ctx.getStatementSourceReference(), substatements);
+ this.schemaTree = ImmutableMap.copyOf(AbstractSchemaEffectiveDocumentedNode.createSchemaTreeNamespace(
+ ctx.getStatementSourceReference(), substatements));
}
@Override
*/
public abstract static class DefaultWithDataTree<A, D extends DeclaredStatement<A>,
E extends DataTreeAwareEffectiveStatement<A, D>> extends WithDataTree<A, D, E> {
- private final @NonNull Map<QName, SchemaTreeEffectiveStatement<?>> schemaTree;
- private final @NonNull Map<QName, DataTreeEffectiveStatement<?>> dataTree;
+ private final @NonNull ImmutableMap<QName, SchemaTreeEffectiveStatement<?>> schemaTree;
+ private final @NonNull ImmutableMap<QName, DataTreeEffectiveStatement<?>> dataTree;
private final @NonNull D declared;
protected DefaultWithDataTree(final D declared, final StmtContext<?, ?, ?> ctx,
final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
this.declared = requireNonNull(declared);
final StatementSourceReference ref = ctx.getStatementSourceReference();
- this.schemaTree = AbstractSchemaEffectiveDocumentedNode.createSchemaTreeNamespace(ref, substatements);
- this.dataTree = AbstractSchemaEffectiveDocumentedNode.createDataTreeNamespace(ref, schemaTree);
+ final Map<QName, SchemaTreeEffectiveStatement<?>> schema =
+ AbstractSchemaEffectiveDocumentedNode.createSchemaTreeNamespace(ref, substatements);
+ this.schemaTree = ImmutableMap.copyOf(schema);
+ this.dataTree = AbstractSchemaEffectiveDocumentedNode.createDataTreeNamespace(ref, schema.values(),
+ schemaTree);
}
@Override
import com.google.common.collect.ImmutableSet;
import java.lang.invoke.VarHandle;
import java.util.Collection;
-import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Optional;
import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.yang.common.QName;
@Beta
public abstract class AbstractSchemaEffectiveDocumentedNode<A, D extends DeclaredStatement<A>>
extends AbstractEffectiveDocumentedNode<A, D> {
- private final Map<QName, DataTreeEffectiveStatement<?>> dataTreeNamespace;
- private final Map<QName, SchemaTreeEffectiveStatement<?>> schemaTreeNamespace;
+ private final ImmutableMap<QName, DataTreeEffectiveStatement<?>> dataTreeNamespace;
+ private final ImmutableMap<QName, SchemaTreeEffectiveStatement<?>> schemaTreeNamespace;
protected AbstractSchemaEffectiveDocumentedNode(final StmtContext<A, D, ?> ctx) {
super(ctx);
// This check is rather weird, but comes from our desire to lower memory footprint while providing both
// EffectiveStatements and SchemaNode interfaces -- which do not overlap completely where child lookups are
// concerned. This ensures that we have SchemaTree index available for use with child lookups.
+ final Map<QName, SchemaTreeEffectiveStatement<?>> schemaTree;
if (this instanceof SchemaTreeAwareEffectiveStatement || this instanceof DataNodeContainer) {
- schemaTreeNamespace = createSchemaTreeNamespace(ctx.getStatementSourceReference(),
+ schemaTree = createSchemaTreeNamespace(ctx.getStatementSourceReference(),
effectiveSubstatements());
} else {
- schemaTreeNamespace = ImmutableMap.of();
+ schemaTree = ImmutableMap.of();
}
- if (this instanceof DataTreeAwareEffectiveStatement && !schemaTreeNamespace.isEmpty()) {
- dataTreeNamespace = createDataTreeNamespace(ctx.getStatementSourceReference(), schemaTreeNamespace);
+ schemaTreeNamespace = ImmutableMap.copyOf(schemaTree);
+
+ if (this instanceof DataTreeAwareEffectiveStatement && !schemaTree.isEmpty()) {
+ dataTreeNamespace = createDataTreeNamespace(ctx.getStatementSourceReference(), schemaTree.values(),
+ schemaTreeNamespace);
} else {
dataTreeNamespace = ImmutableMap.of();
}
final Map<QName, SchemaTreeEffectiveStatement<?>> schemaChildren = new LinkedHashMap<>();
substatements.stream().filter(SchemaTreeEffectiveStatement.class::isInstance)
.forEach(child -> putChild(schemaChildren, (SchemaTreeEffectiveStatement) child, ref, "schema"));
- return toImmutable(schemaChildren);
+ return schemaChildren;
}
- static @NonNull Map<QName, DataTreeEffectiveStatement<?>> createDataTreeNamespace(
+ static @NonNull ImmutableMap<QName, DataTreeEffectiveStatement<?>> createDataTreeNamespace(
final StatementSourceReference ref,
- final Map<QName, SchemaTreeEffectiveStatement<?>> schemaTreeNamespace) {
+ final Collection<SchemaTreeEffectiveStatement<?>> schemaTreeStatements,
+ // Note: this dance is needed to not retain ImmutableMap$Values
+ final ImmutableMap<QName, SchemaTreeEffectiveStatement<?>> schemaTreeNamespace) {
final Map<QName, DataTreeEffectiveStatement<?>> dataChildren = new LinkedHashMap<>();
boolean sameAsSchema = true;
- for (SchemaTreeEffectiveStatement<?> child : schemaTreeNamespace.values()) {
+ for (SchemaTreeEffectiveStatement<?> child : schemaTreeStatements) {
if (child instanceof DataTreeEffectiveStatement) {
putChild(dataChildren, (DataTreeEffectiveStatement<?>) child, ref, "data");
} else {
// 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 ? (Map) schemaTreeNamespace : toImmutable(dataChildren);
- }
-
- private static <K, V> Map<K, V> toImmutable(final Map<K, V> map) {
- switch (map.size()) {
- case 0:
- return ImmutableMap.of();
- case 1:
- // Special case: singleton ImmutableMap is actually SingletonImmutableBiMap, which allocates its inverse
- // view and its keySet() when asked for values() -- which costs us 64 bytes (40+24).
- // java.util.Collections can do the same job for less memory.
- final Entry<K, V> entry = map.entrySet().iterator().next();
- return Collections.singletonMap(entry.getKey(), entry.getValue());
- default:
- return ImmutableMap.copyOf(map);
- }
+ return sameAsSchema ? (ImmutableMap) schemaTreeNamespace : ImmutableMap.copyOf(dataChildren);
}
@SuppressWarnings("unchecked")