BUG-2390: Lower HashMap allocation defaults
[yangtools.git] / yang / yang-data-impl / src / main / java / org / opendaylight / yangtools / yang / data / impl / schema / builder / impl / AbstractImmutableDataContainerNodeBuilder.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 java.util.HashMap;
11 import java.util.List;
12 import java.util.Map;
13 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
14 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
15 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
16 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
17 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
18 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
19 import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableDataContainerNode;
20
21 abstract class AbstractImmutableDataContainerNodeBuilder<I extends YangInstanceIdentifier.PathArgument, R extends DataContainerNode<I>> implements DataContainerNodeBuilder<I, R> {
22     private static final int DEFAULT_CAPACITY = 4;
23     private Map<YangInstanceIdentifier.PathArgument, DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?>> value;
24     private I nodeIdentifier;
25
26     /*
27      * Tracks whether the builder is dirty, e.g. whether the value map has been used
28      * to construct a child. If it has, we detect this condition before any further
29      * modification and create a new value map with same contents. This way we do not
30      * force a map copy if the builder is not reused.
31      */
32     private boolean dirty;
33
34     protected AbstractImmutableDataContainerNodeBuilder() {
35         this.value = new HashMap<>(DEFAULT_CAPACITY);
36         this.dirty = false;
37     }
38
39     protected AbstractImmutableDataContainerNodeBuilder(final int sizeHint) {
40         this.value = new HashMap<>(DEFAULT_CAPACITY);
41         this.dirty = false;
42     }
43
44     protected AbstractImmutableDataContainerNodeBuilder(final AbstractImmutableDataContainerNode<I> node) {
45         this.nodeIdentifier = node.getIdentifier();
46         this.value = node.getChildren();
47         this.dirty = true;
48     }
49
50     protected final I getNodeIdentifier() {
51         return nodeIdentifier;
52     }
53
54     protected final DataContainerChild<? extends PathArgument, ?> getChild(final PathArgument child) {
55         return value.get(child);
56     }
57
58     protected final Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> buildValue() {
59         dirty = true;
60         return value;
61     }
62
63     private void checkDirty() {
64         if (dirty) {
65             value = new HashMap<>(value);
66             dirty = false;
67         }
68     }
69
70     @Override
71     public DataContainerNodeBuilder<I, R> withValue(final List<DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?>> value) {
72         // TODO Replace or putAll ?
73         for (final DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?> dataContainerChild : value) {
74             withChild(dataContainerChild);
75         }
76         return this;
77     }
78
79     @Override
80     public DataContainerNodeBuilder<I, R> withChild(final DataContainerChild<?, ?> child) {
81         checkDirty();
82         this.value.put(child.getIdentifier(), child);
83         return this;
84     }
85
86     @Override
87     public DataContainerNodeBuilder<I, R> withoutChild(final PathArgument key) {
88         checkDirty();
89         this.value.remove(key);
90         return this;
91     }
92
93     @Override
94     public DataContainerNodeBuilder<I, R> withNodeIdentifier(final I nodeIdentifier) {
95         this.nodeIdentifier = nodeIdentifier;
96         return this;
97     }
98
99     @Override
100     public DataContainerNodeBuilder<I, R> addChild(
101             final DataContainerChild<? extends PathArgument, ?> child) {
102         return withChild(child);
103     }
104
105     @Override
106     public NormalizedNodeContainerBuilder<I, PathArgument, DataContainerChild<? extends PathArgument, ?>, R> removeChild(final PathArgument key) {
107         return withoutChild(key);
108     }
109 }