Rename OrderedNodeContainer.getChild(int)
[yangtools.git] / yang / yang-data-impl / src / main / java / org / opendaylight / yangtools / yang / data / impl / schema / builder / impl / ImmutableUserMapNodeBuilder.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
9
10 import com.google.common.collect.Iterables;
11 import java.util.Collection;
12 import java.util.LinkedHashMap;
13 import java.util.Map;
14 import org.eclipse.jdt.annotation.NonNull;
15 import org.opendaylight.yangtools.util.UnmodifiableCollection;
16 import org.opendaylight.yangtools.util.UnmodifiableMap;
17 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
18 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
20 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
21 import org.opendaylight.yangtools.yang.data.api.schema.UserMapNode;
22 import org.opendaylight.yangtools.yang.data.api.schema.builder.CollectionNodeBuilder;
23 import org.opendaylight.yangtools.yang.data.api.schema.builder.NormalizedNodeContainerBuilder;
24 import org.opendaylight.yangtools.yang.data.spi.node.AbstractNormalizedNode;
25
26 public class ImmutableUserMapNodeBuilder implements CollectionNodeBuilder<MapEntryNode, UserMapNode> {
27     private static final int DEFAULT_CAPACITY = 4;
28
29     private Map<NodeIdentifierWithPredicates, MapEntryNode> value;
30     private NodeIdentifier nodeIdentifier;
31     private boolean dirty;
32
33     protected ImmutableUserMapNodeBuilder() {
34         this.value = new LinkedHashMap<>(DEFAULT_CAPACITY);
35         this.dirty = false;
36     }
37
38     protected ImmutableUserMapNodeBuilder(final int sizeHint) {
39         if (sizeHint >= 0) {
40             this.value = new LinkedHashMap<>(sizeHint + sizeHint / 3);
41         } else {
42             this.value = new LinkedHashMap<>(DEFAULT_CAPACITY);
43         }
44         this.dirty = false;
45     }
46
47     protected ImmutableUserMapNodeBuilder(final ImmutableUserMapNode node) {
48         this.nodeIdentifier = node.getIdentifier();
49         this.value = node.children;
50         this.dirty = true;
51     }
52
53     public static @NonNull CollectionNodeBuilder<MapEntryNode, UserMapNode> create() {
54         return new ImmutableUserMapNodeBuilder();
55     }
56
57     public static @NonNull CollectionNodeBuilder<MapEntryNode, UserMapNode> create(final int sizeHint) {
58         return new ImmutableUserMapNodeBuilder(sizeHint);
59     }
60
61     public static @NonNull CollectionNodeBuilder<MapEntryNode, UserMapNode> create(final UserMapNode node) {
62         if (!(node instanceof ImmutableUserMapNode)) {
63             throw new UnsupportedOperationException(String.format("Cannot initialize from class %s", node.getClass()));
64         }
65
66         return new ImmutableUserMapNodeBuilder((ImmutableUserMapNode) node);
67     }
68
69     private void checkDirty() {
70         if (dirty) {
71             value = new LinkedHashMap<>(value);
72             dirty = false;
73         }
74     }
75
76     @Override
77     public CollectionNodeBuilder<MapEntryNode, UserMapNode> withChild(final MapEntryNode child) {
78         checkDirty();
79         this.value.put(child.getIdentifier(), child);
80         return this;
81     }
82
83     @Override
84     public CollectionNodeBuilder<MapEntryNode, UserMapNode> withoutChild(final PathArgument key) {
85         checkDirty();
86         this.value.remove(key);
87         return this;
88     }
89
90     @Override
91     public CollectionNodeBuilder<MapEntryNode, UserMapNode> withValue(final Collection<MapEntryNode> withValue) {
92         // TODO replace or putAll ?
93         for (final MapEntryNode mapEntryNode : withValue) {
94             withChild(mapEntryNode);
95         }
96
97         return this;
98     }
99
100     @Override
101     public CollectionNodeBuilder<MapEntryNode, UserMapNode> withNodeIdentifier(
102             final NodeIdentifier withNodeIdentifier) {
103         this.nodeIdentifier = withNodeIdentifier;
104         return this;
105     }
106
107     @Override
108     public UserMapNode build() {
109         dirty = true;
110         return new ImmutableUserMapNode(nodeIdentifier, value);
111     }
112
113     @Override
114     public CollectionNodeBuilder<MapEntryNode, UserMapNode> addChild(
115             final MapEntryNode child) {
116         return withChild(child);
117     }
118
119
120     @Override
121     public NormalizedNodeContainerBuilder<NodeIdentifier, PathArgument, MapEntryNode, UserMapNode> removeChild(
122             final PathArgument key) {
123         return withoutChild(key);
124     }
125
126     protected static final class ImmutableUserMapNode
127             extends AbstractNormalizedNode<NodeIdentifier, UserMapNode> implements UserMapNode {
128         private final Map<NodeIdentifierWithPredicates, MapEntryNode> children;
129
130         ImmutableUserMapNode(final NodeIdentifier nodeIdentifier,
131                          final Map<NodeIdentifierWithPredicates, MapEntryNode> children) {
132             super(nodeIdentifier);
133             this.children = children;
134         }
135
136         @Override
137         public MapEntryNode childByArg(final NodeIdentifierWithPredicates child) {
138             return children.get(child);
139         }
140
141         @Override
142         public MapEntryNode childAt(final int position) {
143             return Iterables.get(children.values(), position);
144         }
145
146         @Override
147         public int size() {
148             return children.size();
149         }
150
151         @Override
152         public Collection<MapEntryNode> body() {
153             return UnmodifiableCollection.create(children.values());
154         }
155
156         @Override
157         public Map<NodeIdentifierWithPredicates, MapEntryNode> asMap() {
158             return UnmodifiableMap.of(children);
159         }
160
161         @Override
162         protected Class<UserMapNode> implementedType() {
163             return UserMapNode.class;
164         }
165
166         @Override
167         protected int valueHashCode() {
168             // Order is important
169             int hashCode = 1;
170             for (MapEntryNode child : children.values()) {
171                 hashCode = 31 * hashCode + child.hashCode();
172             }
173             return hashCode;
174         }
175
176         @Override
177         protected boolean valueEquals(final UserMapNode other) {
178             final Map<NodeIdentifierWithPredicates, MapEntryNode> otherChildren;
179             if (other instanceof ImmutableUserMapNode) {
180                 otherChildren = ((ImmutableUserMapNode) other).children;
181             } else {
182                 otherChildren = other.asMap();
183             }
184             return Iterables.elementsEqual(children.values(), otherChildren.values());
185         }
186     }
187 }