package org.opendaylight.yangtools.yang.data.impl.schema;
import com.google.common.base.Preconditions;
-
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.List;
-
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListNodeBuilder;
/**
* <p>
* This method is useful for clients, which knows there will be one
* top level node written, but does not know which type of {@link NormalizedNode}
- * will be writen.
- *
+ * will be written.
*
* @param result {@link NormalizedNodeResult} object which will hold result value.
- * @return {@link NormalizedNodeStreamWriter} whcih will write item to supplied result holder.
+ * @return {@link NormalizedNodeStreamWriter} which will write item to supplied result holder.
*/
public static final NormalizedNodeStreamWriter from(final NormalizedNodeResult result) {
return new ImmutableNormalizedNodeStreamWriter(new NormalizedNodeResultBuilder(result));
}
@Override
- public void startLeafSet(final NodeIdentifier name,final int childSizeHint) throws IllegalArgumentException {
+ public void startLeafSet(final NodeIdentifier name, final int childSizeHint) throws IllegalArgumentException {
checkDataNodeContainer();
- ListNodeBuilder<Object, LeafSetEntryNode<Object>> builder = Builders.leafSetBuilder();
+ ListNodeBuilder<Object, LeafSetEntryNode<Object>> builder = UNKNOWN_SIZE == childSizeHint ?
+ ImmutableLeafSetNodeBuilder.create() : ImmutableLeafSetNodeBuilder.create(childSizeHint);
builder.withNodeIdentifier(name);
enter(builder);
}
@Override
public void anyxmlNode(final NodeIdentifier name, final Object value) throws IllegalArgumentException {
checkDataNodeContainer();
-
-
}
@Override
- public void startContainerNode(final NodeIdentifier name,final int childSizeHint) throws IllegalArgumentException {
+ public void startContainerNode(final NodeIdentifier name, final int childSizeHint) throws IllegalArgumentException {
checkDataNodeContainer();
- enter(Builders.containerBuilder().withNodeIdentifier(name));
+
+ final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> builder = UNKNOWN_SIZE == childSizeHint ?
+ ImmutableContainerNodeBuilder.create() : ImmutableContainerNodeBuilder.create(childSizeHint);
+ enter(builder.withNodeIdentifier(name));
}
@Override
- public void startUnkeyedList(final NodeIdentifier name,final int childSizeHint) throws IllegalArgumentException {
+ public void startUnkeyedList(final NodeIdentifier name, final int childSizeHint) throws IllegalArgumentException {
checkDataNodeContainer();
- enter(Builders.unkeyedListBuilder().withNodeIdentifier(name));
+
+ final CollectionNodeBuilder<UnkeyedListEntryNode, UnkeyedListNode> builder = UNKNOWN_SIZE == childSizeHint ?
+ ImmutableUnkeyedListNodeBuilder.create() : ImmutableUnkeyedListNodeBuilder.create(childSizeHint);
+ enter(builder.withNodeIdentifier(name));
}
@Override
- public void startUnkeyedListItem(final NodeIdentifier name,final int childSizeHint) throws IllegalStateException {
+ public void startUnkeyedListItem(final NodeIdentifier name, final int childSizeHint) throws IllegalStateException {
Preconditions.checkArgument(getCurrent() instanceof ImmutableUnkeyedListNodeBuilder);
- enter(Builders.unkeyedListEntryBuilder().withNodeIdentifier(name));
+
+ final DataContainerNodeAttrBuilder<NodeIdentifier, UnkeyedListEntryNode> builder = UNKNOWN_SIZE == childSizeHint ?
+ ImmutableUnkeyedListEntryNodeBuilder.create() : ImmutableUnkeyedListEntryNodeBuilder.create(childSizeHint);
+ enter(builder.withNodeIdentifier(name));
}
@Override
- public void startMapNode(final NodeIdentifier name,final int childSizeHint) throws IllegalArgumentException {
+ public void startMapNode(final NodeIdentifier name, final int childSizeHint) throws IllegalArgumentException {
checkDataNodeContainer();
- enter(Builders.mapBuilder().withNodeIdentifier(name));
+
+ final CollectionNodeBuilder<MapEntryNode, MapNode> builder = UNKNOWN_SIZE == childSizeHint ?
+ ImmutableMapNodeBuilder.create() : ImmutableMapNodeBuilder.create(childSizeHint);
+ enter(builder.withNodeIdentifier(name));
}
@Override
- public void startMapEntryNode(final NodeIdentifierWithPredicates identifier,final int childSizeHint) throws IllegalArgumentException {
+ public void startMapEntryNode(final NodeIdentifierWithPredicates identifier, final int childSizeHint) throws IllegalArgumentException {
if(!(getCurrent() instanceof NormalizedNodeResultBuilder)) {
Preconditions.checkArgument(getCurrent() instanceof ImmutableMapNodeBuilder || getCurrent() instanceof ImmutableOrderedMapNodeBuilder);
}
- enter(Builders.mapEntryBuilder().withNodeIdentifier(identifier));
+
+ final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> builder = UNKNOWN_SIZE == childSizeHint ?
+ ImmutableMapEntryNodeBuilder.create() : ImmutableMapEntryNodeBuilder.create(childSizeHint);
+ enter(builder.withNodeIdentifier(identifier));
}
@Override
- public void startOrderedMapNode(final NodeIdentifier name,final int childSizeHint) throws IllegalArgumentException {
+ public void startOrderedMapNode(final NodeIdentifier name, final int childSizeHint) throws IllegalArgumentException {
checkDataNodeContainer();
- enter(Builders.orderedMapBuilder().withNodeIdentifier(name));
+
+ final CollectionNodeBuilder<MapEntryNode, OrderedMapNode> builder = UNKNOWN_SIZE == childSizeHint ?
+ ImmutableOrderedMapNodeBuilder.create() : ImmutableOrderedMapNodeBuilder.create(childSizeHint);
+ enter(builder.withNodeIdentifier(name));
}
@Override
- public void startChoiceNode(final NodeIdentifier name,final int childSizeHint) throws IllegalArgumentException {
+ public void startChoiceNode(final NodeIdentifier name, final int childSizeHint) throws IllegalArgumentException {
checkDataNodeContainer();
- enter(Builders.choiceBuilder().withNodeIdentifier(name));
+
+ final DataContainerNodeBuilder<NodeIdentifier, ChoiceNode> builder = UNKNOWN_SIZE == childSizeHint ?
+ ImmutableChoiceNodeBuilder.create() : ImmutableChoiceNodeBuilder.create(childSizeHint);
+ enter(builder.withNodeIdentifier(name));
}
+
@Override
public void startAugmentationNode(final AugmentationIdentifier identifier) throws IllegalArgumentException {
checkDataNodeContainer();
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableDataContainerNode;
abstract class AbstractImmutableDataContainerNodeBuilder<I extends YangInstanceIdentifier.PathArgument, R extends DataContainerNode<I>> implements DataContainerNodeBuilder<I, R> {
-
+ private static final int DEFAULT_CAPACITY = 4;
private Map<YangInstanceIdentifier.PathArgument, DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?>> value;
private I nodeIdentifier;
private boolean dirty;
protected AbstractImmutableDataContainerNodeBuilder() {
- this.value = new HashMap<>();
+ this.value = new HashMap<>(DEFAULT_CAPACITY);
this.dirty = false;
}
protected AbstractImmutableDataContainerNodeBuilder(final int sizeHint) {
- this.value = new HashMap<>(sizeHint);
+ this.value = new HashMap<>(DEFAULT_CAPACITY);
this.dirty = false;
}
*/
package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
+import com.google.common.base.Preconditions;
import java.util.Map;
-
+import java.util.Objects;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedValueAttrNode;
-import com.google.common.base.Preconditions;
-
public class ImmutableLeafSetEntryNodeBuilder<T> extends AbstractImmutableNormalizedNodeBuilder<YangInstanceIdentifier.NodeWithValue, T, LeafSetEntryNode<T>> {
public static <T> ImmutableLeafSetEntryNodeBuilder<T> create() {
ImmutableLeafSetEntryNode(final YangInstanceIdentifier.NodeWithValue nodeIdentifier, final T value, final Map<QName, String> attributes) {
super(nodeIdentifier, value, attributes);
- Preconditions.checkArgument(nodeIdentifier.getValue().equals(value),
+ Preconditions.checkArgument(Objects.deepEquals(nodeIdentifier.getValue(), value),
"Node identifier contains different value: %s than value itself: %s", nodeIdentifier, value);
}
}
*/
package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
+import com.google.common.base.Optional;
+import com.google.common.collect.Iterables;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-
import org.opendaylight.yangtools.concepts.Immutable;
import org.opendaylight.yangtools.util.MapAdaptor;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedNode;
import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedValueNode;
-import com.google.common.base.Optional;
-import com.google.common.collect.Iterables;
-
public class ImmutableLeafSetNodeBuilder<T> implements ListNodeBuilder<T, LeafSetEntryNode<T>> {
-
+ private static final int DEFAULT_CAPACITY = 4;
private final Map<YangInstanceIdentifier.NodeWithValue, LeafSetEntryNode<T>> value;
private YangInstanceIdentifier.NodeIdentifier nodeIdentifier;
protected ImmutableLeafSetNodeBuilder() {
- value = new HashMap<>();
+ value = new HashMap<>(DEFAULT_CAPACITY);
+ }
+
+ protected ImmutableLeafSetNodeBuilder(final int sizeHint) {
+ value = new HashMap<>(sizeHint * 4 / 3);
}
protected ImmutableLeafSetNodeBuilder(final ImmutableLeafSetNode<T> node) {
return new ImmutableLeafSetNodeBuilder<>();
}
+ public static <T> ListNodeBuilder<T, LeafSetEntryNode<T>> create(final int sizeHint) {
+ return new ImmutableLeafSetNodeBuilder<>(sizeHint);
+ }
+
public static <T> ListNodeBuilder<T, LeafSetEntryNode<T>> create(final LeafSetNode<T> node) {
if (!(node instanceof ImmutableLeafSetNode<?>)) {
throw new UnsupportedOperationException(String.format("Cannot initialize from class %s", node.getClass()));
*/
package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
+import com.google.common.base.Optional;
+import com.google.common.collect.Iterables;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-
import org.opendaylight.yangtools.concepts.Immutable;
import org.opendaylight.yangtools.util.MapAdaptor;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedNode;
-import com.google.common.base.Optional;
-import com.google.common.collect.Iterables;
-
-public class ImmutableMapNodeBuilder
- implements CollectionNodeBuilder<MapEntryNode, MapNode> {
-
+public class ImmutableMapNodeBuilder implements CollectionNodeBuilder<MapEntryNode, MapNode> {
+ private static final int DEFAULT_CAPACITY = 4;
private final Map<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> value;
private YangInstanceIdentifier.NodeIdentifier nodeIdentifier;
protected ImmutableMapNodeBuilder() {
- this.value = new HashMap<>();
+ this.value = new HashMap<>(DEFAULT_CAPACITY);
+ }
+
+ protected ImmutableMapNodeBuilder(final int sizeHint) {
+ this.value = new HashMap<>(DEFAULT_CAPACITY);
}
protected ImmutableMapNodeBuilder(final ImmutableMapNode node) {
return new ImmutableMapNodeBuilder();
}
+ public static CollectionNodeBuilder<MapEntryNode, MapNode> create(final int sizeHint) {
+ return new ImmutableMapNodeBuilder(sizeHint);
+ }
+
public static CollectionNodeBuilder<MapEntryNode, MapNode> create(final MapNode node) {
if (!(node instanceof ImmutableMapNode)) {
throw new UnsupportedOperationException(String.format("Cannot initialize from class %s", node.getClass()));
import com.google.common.base.Optional;
import com.google.common.collect.Iterables;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
import org.opendaylight.yangtools.concepts.Immutable;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedNode;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-public class ImmutableOrderedMapNodeBuilder
- implements CollectionNodeBuilder<MapEntryNode, OrderedMapNode> {
-
+public class ImmutableOrderedMapNodeBuilder implements CollectionNodeBuilder<MapEntryNode, OrderedMapNode> {
+ private static final int DEFAULT_CAPACITY = 4;
private Map<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> value;
private YangInstanceIdentifier.NodeIdentifier nodeIdentifier;
- private boolean dirty = false;
+ private boolean dirty;
protected ImmutableOrderedMapNodeBuilder() {
- this.value = new LinkedHashMap<>();
+ this.value = new LinkedHashMap<>(DEFAULT_CAPACITY);
+ this.dirty = false;
+ }
+
+ protected ImmutableOrderedMapNodeBuilder(final int sizeHint) {
+ this.value = new LinkedHashMap<>(DEFAULT_CAPACITY);
this.dirty = false;
}
return new ImmutableOrderedMapNodeBuilder();
}
+ public static CollectionNodeBuilder<MapEntryNode, OrderedMapNode> create(final int sizeHint) {
+ return new ImmutableOrderedMapNodeBuilder(sizeHint);
+ }
+
public static CollectionNodeBuilder<MapEntryNode, OrderedMapNode> create(final MapNode node) {
if (!(node instanceof ImmutableOrderedMapNode)) {
throw new UnsupportedOperationException(String.format("Cannot initialize from class %s", node.getClass()));
return children.size();
}
- @Override
- public Iterable<MapEntryNode> getValue() {
- return Iterables.unmodifiableIterable(children.values());
- }
+ @Override
+ public Iterable<MapEntryNode> getValue() {
+ return Iterables.unmodifiableIterable(children.values());
+ }
}
}
*/
package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
-
import org.opendaylight.yangtools.concepts.Immutable;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedNode;
import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedValueNode;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-
public class ImmutableUnkeyedListNodeBuilder implements CollectionNodeBuilder<UnkeyedListEntryNode, UnkeyedListNode> {
-
private List<UnkeyedListEntryNode> value;
private YangInstanceIdentifier.NodeIdentifier nodeIdentifier;
- private boolean dirty = false;
+ private boolean dirty;
protected ImmutableUnkeyedListNodeBuilder() {
this.value = new LinkedList<>();
return new ImmutableUnkeyedListNodeBuilder();
}
+ public static CollectionNodeBuilder<UnkeyedListEntryNode, UnkeyedListNode> create(final int sizeHint) {
+ return new ImmutableUnkeyedListNodeBuilder();
+ }
+
public static CollectionNodeBuilder<UnkeyedListEntryNode, UnkeyedListNode> create(final UnkeyedListNode node) {
if (!(node instanceof ImmutableUnkeyedListNode)) {
throw new UnsupportedOperationException(String.format("Cannot initialize from class %s", node.getClass()));
@Override
public UnkeyedListNode build() {
dirty = true;
- return new ImmutableUnkeyedListNode(nodeIdentifier, ImmutableList.copyOf(value));
+ if (value.isEmpty()) {
+ return new EmptyImmutableUnkeyedListNode(nodeIdentifier);
+ } else {
+ return new ImmutableUnkeyedListNode(nodeIdentifier, ImmutableList.copyOf(value));
+ }
}
@Override
return withoutChild(key);
}
+ protected static final class EmptyImmutableUnkeyedListNode extends AbstractImmutableNormalizedNode<YangInstanceIdentifier.NodeIdentifier, Iterable<UnkeyedListEntryNode>> implements Immutable, UnkeyedListNode {
+ protected EmptyImmutableUnkeyedListNode(final NodeIdentifier nodeIdentifier) {
+ super(nodeIdentifier);
+ }
+
+ @Override
+ public Iterable<UnkeyedListEntryNode> getValue() {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public UnkeyedListEntryNode getChild(final int position) {
+ return null;
+ }
+
+ @Override
+ public int getSize() {
+ return 0;
+ }
+
+ @Override
+ protected boolean valueEquals(final AbstractImmutableNormalizedNode<?, ?> other) {
+ return Collections.EMPTY_LIST.equals(other.getValue());
+ }
+
+ @Override
+ protected int valueHashCode() {
+ return Collections.EMPTY_LIST.hashCode();
+ }
+ }
+
protected static final class ImmutableUnkeyedListNode extends
AbstractImmutableNormalizedValueNode<YangInstanceIdentifier.NodeIdentifier, Iterable<UnkeyedListEntryNode>>
implements Immutable, UnkeyedListNode {
package org.opendaylight.yangtools.yang.data.impl.schema.nodes;
import com.google.common.base.Optional;
-
-import java.util.Collections;
import java.util.Map;
-
import org.opendaylight.yangtools.concepts.Immutable;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
public abstract class AbstractImmutableDataContainerNode<K extends PathArgument> extends AbstractImmutableNormalizedNode<K, Iterable<DataContainerChild<? extends PathArgument, ?>>> implements Immutable, DataContainerNode<K> {
- private static final Logger LOG = LoggerFactory.getLogger(AbstractImmutableDataContainerNode.class);
private final Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> children;
public AbstractImmutableDataContainerNode(
final Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> children, final K nodeIdentifier) {
super(nodeIdentifier);
- /*
- * There is a code path where AbstractImmutableDataContainerNodeBuilder can reflect
- * the collection acquired via getChildren() back to us. This is typically the case
- * in the datastore where transactions cancel each other out, leaving an unmodified
- * node. In that case we want to skip wrapping the map again (and again and again).
- *
- * In a perfect world, Collection.unmodifiableMap() would be doing the instanceof
- * check which would stop the proliferation. Unfortunately this not the case and the
- * 'unmodifiable' trait is not exposed by anything we can query. Furthermore the API
- * contract there is sufficiently vague so an implementation may actually return a
- * different implementation based on input map -- for example
- * Collections.unmodifiableMap(Collections.emptyMap()) returning the same thing as
- * Collections.emptyMap().
- *
- * This means that we have to perform the instantiation here (as opposed to once at
- * class load time) and then compare the classes.
- */
- final Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> pub = Collections.unmodifiableMap(children);
- if (children.getClass().equals(pub.getClass())) {
- LOG.trace("Reusing already-unmodifiable children {}", children);
- this.children = children;
- } else {
- this.children = pub;
- }
+ this.children = UnmodifiableChildrenMap.create(children);
}
@Override
--- /dev/null
+/*
+ * Copyright (c) 2014 Cisco Systems, Inc. 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.data.impl.schema.nodes;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Internal equivalent of {@link Collections}' unmodifiable Map. It does not retain
+ * keySet/entrySet references, thus lowering the memory overhead.
+ */
+final class UnmodifiableChildrenMap implements Map<PathArgument, DataContainerChild<? extends PathArgument, ?>>, Serializable {
+ private static final Logger LOG = LoggerFactory.getLogger(UnmodifiableChildrenMap.class);
+ private static final long serialVersionUID = 1L;
+ private final Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> delegate;
+ private transient Collection<DataContainerChild<? extends PathArgument, ?>> values;
+
+ private UnmodifiableChildrenMap(final Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> delegate) {
+ this.delegate = Preconditions.checkNotNull(delegate);
+ }
+
+ /**
+ * Create an unmodifiable view of a particular map. Does not perform unnecessary
+ * encapsulation if the map is known to be already unmodifiable.
+ *
+ * @param map Backing map
+ * @return Unmodifiable view
+ */
+ static Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> create(final Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> map) {
+ if (map instanceof UnmodifiableChildrenMap) {
+ return map;
+ }
+ if (map instanceof ImmutableMap) {
+ return map;
+ }
+ if (map.isEmpty()) {
+ return Collections.emptyMap();
+ }
+
+ return new UnmodifiableChildrenMap(map);
+ }
+
+ @Override
+ public int size() {
+ return delegate.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return delegate.isEmpty();
+ }
+
+ @Override
+ public boolean containsKey(final Object key) {
+ return delegate.containsKey(key);
+ }
+
+ @Override
+ public boolean containsValue(final Object value) {
+ return delegate.containsValue(value);
+ }
+
+ @Override
+ public DataContainerChild<? extends PathArgument, ?> get(final Object key) {
+ return delegate.get(key);
+ }
+
+ @Override
+ public DataContainerChild<? extends PathArgument, ?> put(final PathArgument key,
+ final DataContainerChild<? extends PathArgument, ?> value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public DataContainerChild<? extends PathArgument, ?> remove(final Object key) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void putAll(final Map<? extends PathArgument, ? extends DataContainerChild<? extends PathArgument, ?>> m) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Set<PathArgument> keySet() {
+ return Collections.unmodifiableSet(delegate.keySet());
+ }
+
+ @Override
+ public Collection<DataContainerChild<? extends PathArgument, ?>> values() {
+ if (values == null) {
+ values = Collections.unmodifiableCollection(delegate.values());
+ }
+ return values;
+ }
+
+ @Override
+ public Set<Entry<PathArgument, DataContainerChild<? extends PathArgument, ?>>> entrySet() {
+ LOG.warn("Invocation of inefficient entrySet()", new Throwable().fillInStackTrace());
+ return Collections.unmodifiableMap(delegate).entrySet();
+ }
+
+
+ @Override
+ public boolean equals(final Object o) {
+ return this == o || delegate.equals(o);
+ }
+
+ @Override
+ public int hashCode() {
+ return delegate.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return delegate.toString();
+ }
+}