Fix checkstyle issues reported by odlparent-3.0.0's checkstyle
[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 com.google.common.collect.Maps;
11 import java.util.Collection;
12 import java.util.HashMap;
13 import java.util.Map;
14 import org.opendaylight.yangtools.util.ModifiableMapPhase;
15 import org.opendaylight.yangtools.util.UnmodifiableMapPhase;
16 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
17 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
18 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
19 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
20 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
21 import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableDataContainerNode;
22 import org.opendaylight.yangtools.yang.data.impl.schema.nodes.CloneableMap;
23
24 abstract class AbstractImmutableDataContainerNodeBuilder<I extends PathArgument, R extends DataContainerNode<I>>
25         implements DataContainerNodeBuilder<I, R> {
26     private static final int DEFAULT_CAPACITY = 4;
27     private Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> value;
28     private I nodeIdentifier;
29
30     /*
31      * Tracks whether the builder is dirty, e.g. whether the value map has been used
32      * to construct a child. If it has, we detect this condition before any further
33      * modification and create a new value map with same contents. This way we do not
34      * force a map copy if the builder is not reused.
35      */
36     private boolean dirty;
37
38     protected AbstractImmutableDataContainerNodeBuilder() {
39         this.value = new HashMap<>(DEFAULT_CAPACITY);
40         this.dirty = false;
41     }
42
43     protected AbstractImmutableDataContainerNodeBuilder(final int sizeHint) {
44         if (sizeHint >= 0) {
45             this.value = Maps.newHashMapWithExpectedSize(sizeHint);
46         } else {
47             this.value = new HashMap<>(DEFAULT_CAPACITY);
48         }
49         this.dirty = false;
50     }
51
52     protected AbstractImmutableDataContainerNodeBuilder(final AbstractImmutableDataContainerNode<I> node) {
53         this.nodeIdentifier = node.getIdentifier();
54
55         /*
56          * This quite awkward. What we actually want to be saying here is: give me
57          * a copy-on-write view of your children. The API involved in that could be
58          * a bit hairy, so we do the next best thing and rely on the fact that the
59          * returned object implements a specific interface, which leaks the functionality
60          * we need.
61          */
62         this.value = node.getChildren();
63         this.dirty = true;
64     }
65
66     protected final I getNodeIdentifier() {
67         return nodeIdentifier;
68     }
69
70     protected final DataContainerChild<? extends PathArgument, ?> getChild(final PathArgument child) {
71         return value.get(child);
72     }
73
74     protected final Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> buildValue() {
75         if (value instanceof ModifiableMapPhase) {
76             return ((ModifiableMapPhase<PathArgument, DataContainerChild<? extends PathArgument, ?>>)value)
77                     .toUnmodifiableMap();
78         }
79
80         dirty = true;
81         return value;
82     }
83
84     private void checkDirty() {
85         if (dirty) {
86             if (value instanceof UnmodifiableMapPhase) {
87                 value = ((UnmodifiableMapPhase<PathArgument, DataContainerChild<? extends PathArgument, ?>>) value)
88                         .toModifiableMap();
89             } else if (value instanceof CloneableMap) {
90                 value = ((CloneableMap<PathArgument, DataContainerChild<? extends PathArgument, ?>>) value)
91                         .createMutableClone();
92             } else {
93                 value = new HashMap<>(value);
94             }
95             dirty = false;
96         }
97     }
98
99     @Override
100     public DataContainerNodeBuilder<I, R> withValue(
101             final Collection<DataContainerChild<? extends PathArgument, ?>> withValue) {
102         // TODO Replace or putAll ?
103         for (final DataContainerChild<? extends PathArgument, ?> dataContainerChild : withValue) {
104             withChild(dataContainerChild);
105         }
106         return this;
107     }
108
109     @Override
110     public DataContainerNodeBuilder<I, R> withChild(final DataContainerChild<?, ?> child) {
111         checkDirty();
112         this.value.put(child.getIdentifier(), child);
113         return this;
114     }
115
116     @Override
117     public DataContainerNodeBuilder<I, R> withoutChild(final PathArgument key) {
118         checkDirty();
119         this.value.remove(key);
120         return this;
121     }
122
123     @Override
124     public DataContainerNodeBuilder<I, R> withNodeIdentifier(final I withNodeIdentifier) {
125         this.nodeIdentifier = withNodeIdentifier;
126         return this;
127     }
128
129     @Override
130     public DataContainerNodeBuilder<I, R> addChild(
131             final DataContainerChild<? extends PathArgument, ?> child) {
132         return withChild(child);
133     }
134
135     @Override
136     public NormalizedNodeContainerBuilder<I, PathArgument, DataContainerChild<? extends PathArgument, ?>, R>
137             removeChild(final PathArgument key) {
138         return withoutChild(key);
139     }
140 }