Fix immutable NormalizedNode equality
[yangtools.git] / data / yang-data-impl / src / main / java / org / opendaylight / yangtools / yang / data / impl / schema / builder / impl / ImmutableLeafSetNodeBuilder.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.eclipse.jdt.annotation.NonNull;
15 import org.opendaylight.yangtools.util.MapAdaptor;
16 import org.opendaylight.yangtools.util.UnmodifiableCollection;
17 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
18 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
19 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
20 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
21 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
22 import org.opendaylight.yangtools.yang.data.api.schema.SystemLeafSetNode;
23 import org.opendaylight.yangtools.yang.data.api.schema.builder.ListNodeBuilder;
24 import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedValueNode;
25 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
26
27 public class ImmutableLeafSetNodeBuilder<T> implements ListNodeBuilder<T, SystemLeafSetNode<T>> {
28     private static final int DEFAULT_CAPACITY = 4;
29
30     private final Map<NodeWithValue<?>, LeafSetEntryNode<T>> value;
31
32     private NodeIdentifier nodeIdentifier;
33
34     protected ImmutableLeafSetNodeBuilder() {
35         value = new HashMap<>(DEFAULT_CAPACITY);
36     }
37
38     protected ImmutableLeafSetNodeBuilder(final int sizeHint) {
39         if (sizeHint >= 0) {
40             value = Maps.newHashMapWithExpectedSize(sizeHint);
41         } else {
42             value = new HashMap<>(DEFAULT_CAPACITY);
43         }
44     }
45
46     protected ImmutableLeafSetNodeBuilder(final ImmutableLeafSetNode<T> node) {
47         nodeIdentifier = node.getIdentifier();
48         value = MapAdaptor.getDefaultInstance().takeSnapshot(node.children);
49     }
50
51     public static <T> @NonNull ListNodeBuilder<T, SystemLeafSetNode<T>> create() {
52         return new ImmutableLeafSetNodeBuilder<>();
53     }
54
55     public static <T> @NonNull ListNodeBuilder<T, SystemLeafSetNode<T>> create(final int sizeHint) {
56         return new ImmutableLeafSetNodeBuilder<>(sizeHint);
57     }
58
59     public static <T> @NonNull ListNodeBuilder<T, SystemLeafSetNode<T>> create(final SystemLeafSetNode<T> node) {
60         if (node instanceof ImmutableLeafSetNode) {
61             return new ImmutableLeafSetNodeBuilder<>((ImmutableLeafSetNode<T>) node);
62         }
63         throw new UnsupportedOperationException("Cannot initialize from class " + node.getClass());
64     }
65
66     @Deprecated(since = "6.0.7", forRemoval = true)
67     public static <T> @NonNull ListNodeBuilder<T, SystemLeafSetNode<T>> create(final LeafListSchemaNode schema) {
68         return new SchemaAwareImmutableLeafSetNodeBuilder<>(schema);
69     }
70
71     @Deprecated(since = "6.0.7", forRemoval = true)
72     public static <T> @NonNull ListNodeBuilder<T, SystemLeafSetNode<T>> create(final LeafListSchemaNode schema,
73             final LeafSetNode<T> node) {
74         if (node instanceof ImmutableLeafSetNode) {
75             return new SchemaAwareImmutableLeafSetNodeBuilder<>(schema, (ImmutableLeafSetNode<T>) node);
76         }
77         throw new UnsupportedOperationException("Cannot initialize from class " + node.getClass());
78     }
79
80     @Override
81     public ImmutableLeafSetNodeBuilder<T> withChild(final LeafSetEntryNode<T> child) {
82         this.value.put(child.getIdentifier(), child);
83         return this;
84     }
85
86     @Override
87     public ImmutableLeafSetNodeBuilder<T> withoutChild(final PathArgument key) {
88         this.value.remove(key);
89         return this;
90     }
91
92     @Override
93     public SystemLeafSetNode<T> build() {
94         return new ImmutableLeafSetNode<>(nodeIdentifier, MapAdaptor.getDefaultInstance().optimize(value));
95     }
96
97     @Override
98     public ImmutableLeafSetNodeBuilder<T> withNodeIdentifier(final NodeIdentifier withNodeIdentifier) {
99         this.nodeIdentifier = withNodeIdentifier;
100         return this;
101     }
102
103     @Override
104     public ImmutableLeafSetNodeBuilder<T> withValue(final Collection<LeafSetEntryNode<T>> withValue) {
105         for (final LeafSetEntryNode<T> leafSetEntry : withValue) {
106             withChild(leafSetEntry);
107         }
108         return this;
109     }
110
111     @Override
112     public ImmutableLeafSetNodeBuilder<T> withChildValue(final T childValue) {
113         return withChild(ImmutableLeafSetEntryNodeBuilder.<T>create()
114             .withNodeIdentifier(new NodeWithValue<>(nodeIdentifier.getNodeType(), childValue))
115             .withValue(childValue).build());
116     }
117
118
119     @Override
120     public ImmutableLeafSetNodeBuilder<T> addChild(final LeafSetEntryNode<T> child) {
121         return withChild(child);
122     }
123
124     @Override
125     public ImmutableLeafSetNodeBuilder<T> removeChild(final PathArgument key) {
126         return withoutChild(key);
127     }
128
129     protected static final class ImmutableLeafSetNode<T>
130             extends AbstractImmutableNormalizedValueNode<NodeIdentifier, SystemLeafSetNode<?>,
131                 Collection<@NonNull LeafSetEntryNode<T>>>
132             implements SystemLeafSetNode<T> {
133
134         private final Map<NodeWithValue<?>, LeafSetEntryNode<T>> children;
135
136         ImmutableLeafSetNode(final NodeIdentifier nodeIdentifier,
137                 final Map<NodeWithValue<?>, LeafSetEntryNode<T>> children) {
138             super(nodeIdentifier, UnmodifiableCollection.create(children.values()));
139             this.children = children;
140         }
141
142         @Override
143         public LeafSetEntryNode<T> childByArg(final NodeWithValue<?> child) {
144             return children.get(child);
145         }
146
147         @Override
148         public int size() {
149             return children.size();
150         }
151
152         @Override
153         protected Class<SystemLeafSetNode<?>> implementedType() {
154             return (Class) SystemLeafSetNode.class;
155         }
156
157         @Override
158         protected int valueHashCode() {
159             return children.hashCode();
160         }
161
162         @Override
163         protected boolean valueEquals(final SystemLeafSetNode<?> other) {
164             if (other instanceof ImmutableLeafSetNode) {
165                 return children.equals(((ImmutableLeafSetNode<?>) other).children);
166             }
167             if (size() != other.size()) {
168                 return false;
169             }
170             for (var child : children.values()) {
171                 if (!child.equals(other.childByArg(child.getIdentifier()))) {
172                     return false;
173                 }
174             }
175             return true;
176         }
177     }
178 }