0ee0d9b32c990685c8169eb0430d35d64dacc2e0
[controller.git] / opendaylight / md-sal / sal-dom-broker / src / main / java / org / opendaylight / controller / md / sal / dom / store / impl / tree / data / StoreMetadataNode.java
1 /*
2  * Copyright (c) 2014 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.controller.md.sal.dom.store.impl.tree.data;
9
10 import static com.google.common.base.Preconditions.checkState;
11
12 import java.util.Collections;
13 import java.util.HashMap;
14 import java.util.Map;
15
16 import org.opendaylight.controller.md.sal.dom.store.impl.tree.StoreTreeNode;
17 import org.opendaylight.yangtools.concepts.Identifiable;
18 import org.opendaylight.yangtools.concepts.Immutable;
19 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
20 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
21 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
22
23 import com.google.common.base.Optional;
24 import com.google.common.base.Preconditions;
25 import com.google.common.primitives.UnsignedLong;
26
27 class StoreMetadataNode implements Immutable, Identifiable<PathArgument>, StoreTreeNode<StoreMetadataNode> {
28     private final Map<PathArgument, StoreMetadataNode> children;
29     private final UnsignedLong nodeVersion;
30     private final UnsignedLong subtreeVersion;
31     private final NormalizedNode<?, ?> data;
32
33     /**
34      *
35      * @param data
36      * @param nodeVersion
37      * @param subtreeVersion
38      * @param children Map of children, must not be modified externally
39      */
40     protected StoreMetadataNode(final NormalizedNode<?, ?> data, final UnsignedLong nodeVersion,
41             final UnsignedLong subtreeVersion, final Map<PathArgument, StoreMetadataNode> children) {
42         this.nodeVersion = Preconditions.checkNotNull(nodeVersion);
43         this.subtreeVersion = Preconditions.checkNotNull(subtreeVersion);
44         this.data = Preconditions.checkNotNull(data);
45         this.children = Preconditions.checkNotNull(children);
46     }
47
48     public static StoreMetadataNode createEmpty(final NormalizedNode<?, ?> data) {
49         return new StoreMetadataNode(data, UnsignedLong.ZERO, UnsignedLong.ZERO,
50                 Collections.<PathArgument, StoreMetadataNode>emptyMap());
51     }
52
53     public StoreMetadataNode(final NormalizedNode<?, ?> data, final UnsignedLong nodeVersion,
54             final UnsignedLong subtreeVersion) {
55         this(data, nodeVersion, subtreeVersion, Collections.<PathArgument, StoreMetadataNode>emptyMap());
56     }
57
58     public static Builder builder() {
59         return new Builder();
60     }
61
62     public static Builder builder(StoreMetadataNode node) {
63         return new Builder(node);
64     }
65
66     public UnsignedLong getNodeVersion() {
67         return this.nodeVersion;
68     }
69
70     @Override
71     public PathArgument getIdentifier() {
72         return data.getIdentifier();
73     }
74
75     public UnsignedLong getSubtreeVersion() {
76         return subtreeVersion;
77     }
78
79     public NormalizedNode<?, ?> getData() {
80         return this.data;
81     }
82
83     @Override
84     public Optional<StoreMetadataNode> getChild(final PathArgument key) {
85         return Optional.fromNullable(children.get(key));
86     }
87
88     @Override
89     public String toString() {
90         return "StoreMetadataNode [identifier=" + getIdentifier() + ", nodeVersion=" + nodeVersion + "]";
91     }
92
93     public static Optional<UnsignedLong> getVersion(final Optional<StoreMetadataNode> currentMetadata) {
94         if (currentMetadata.isPresent()) {
95             return Optional.of(currentMetadata.get().getNodeVersion());
96         }
97         return Optional.absent();
98     }
99
100     public static Optional<StoreMetadataNode> getChild(final Optional<StoreMetadataNode> parent,
101             final PathArgument child) {
102         if (parent.isPresent()) {
103             return parent.get().getChild(child);
104         }
105         return Optional.absent();
106     }
107
108     public static final StoreMetadataNode createRecursively(final NormalizedNode<?, ?> node,
109             final UnsignedLong nodeVersion, final UnsignedLong subtreeVersion) {
110         Builder builder = builder() //
111                 .setNodeVersion(nodeVersion) //
112                 .setSubtreeVersion(subtreeVersion) //
113                 .setData(node);
114         if (node instanceof NormalizedNodeContainer<?, ?, ?>) {
115
116             @SuppressWarnings("unchecked")
117             NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>> nodeContainer = (NormalizedNodeContainer<?, ?, NormalizedNode<?, ?>>) node;
118             for (NormalizedNode<?, ?> subNode : nodeContainer.getValue()) {
119                 builder.add(createRecursively(subNode, nodeVersion, subtreeVersion));
120             }
121         }
122         return builder.build();
123     }
124
125     public static class Builder {
126
127         private UnsignedLong nodeVersion;
128         private UnsignedLong subtreeVersion;
129         private NormalizedNode<?, ?> data;
130         private Map<PathArgument, StoreMetadataNode> children;
131         private boolean dirty = false;
132
133         private Builder() {
134             children = new HashMap<>();
135         }
136
137         public Builder(StoreMetadataNode node) {
138             children = new HashMap<>(node.children);
139         }
140
141         public UnsignedLong getVersion() {
142             return nodeVersion;
143
144         }
145
146         public Builder setNodeVersion(final UnsignedLong version) {
147             this.nodeVersion = version;
148             return this;
149         }
150
151         public Builder setSubtreeVersion(final UnsignedLong version) {
152             this.subtreeVersion = version;
153             return this;
154         }
155
156         public Builder setData(final NormalizedNode<?, ?> data) {
157             this.data = data;
158             return this;
159         }
160
161         public Builder add(final StoreMetadataNode node) {
162             if (dirty) {
163                 children = new HashMap<>(children);
164                 dirty = false;
165             }
166             children.put(node.getIdentifier(), node);
167             return this;
168         }
169
170         public Builder remove(final PathArgument id) {
171             if (dirty) {
172                 children = new HashMap<>(children);
173                 dirty = false;
174             }
175             children.remove(id);
176             return this;
177         }
178
179         public StoreMetadataNode build() {
180             checkState(data != null, "Data node should not be null.");
181             checkState(subtreeVersion.compareTo(nodeVersion) >= 0,
182                     "Subtree version must be equals or greater than node version.");
183             dirty = true;
184             return new StoreMetadataNode(data, nodeVersion, subtreeVersion, children);
185         }
186     }
187
188     public static StoreMetadataNode createRecursively(final NormalizedNode<?, ?> node, final UnsignedLong version) {
189         return createRecursively(node, version, version);
190     }
191 }