Merge "BUG-731: remove unused methods"
[yangtools.git] / yang / yang-data-api / src / main / java / org / opendaylight / yangtools / yang / data / api / InstanceIdentifier.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.yangtools.yang.data.api;
9
10 import java.io.Serializable;
11 import java.util.List;
12 import java.util.Map;
13 import java.util.Set;
14
15 import org.opendaylight.yangtools.concepts.Builder;
16 import org.opendaylight.yangtools.concepts.Immutable;
17 import org.opendaylight.yangtools.concepts.Path;
18 import org.opendaylight.yangtools.yang.common.QName;
19 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
20 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
21 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
22 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
23 import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
24
25 import com.google.common.collect.ImmutableList;
26 import com.google.common.collect.ImmutableMap;
27 import com.google.common.collect.ImmutableSet;
28
29 public class InstanceIdentifier implements Path<InstanceIdentifier>, Immutable, Serializable {
30
31     private static final long serialVersionUID = 8467409862384206193L;
32     private final List<PathArgument> path;
33
34     private transient String toStringCache = null;
35     private transient Integer hashCodeCache = null;
36
37     public List<PathArgument> getPath() {
38         return path;
39     }
40
41     public InstanceIdentifier(final List<? extends PathArgument> path) {
42         this.path = ImmutableList.copyOf(path);
43     }
44
45     private InstanceIdentifier(final NodeIdentifier nodeIdentifier) {
46         this.path = ImmutableList.<PathArgument> of(nodeIdentifier);
47     }
48
49     @Override
50     public int hashCode() {
51         /*
52          * The hashCodeCache is safe, since the object contract requires
53          * immutability of the object and all objects referenced from this
54          * object.
55          *
56          * Used lists, maps are immutable. Path Arguments (elements) are also
57          * immutable, since the PathArgument contract requires immutability.
58          *
59          * The cache is thread-safe - if multiple computations occurs at the
60          * same time, cache will be overwritten with same result.
61          */
62         if (hashCodeCache == null) {
63             final int prime = 31;
64             int result = 1;
65             result = prime * result + ((path == null) ? 0 : path.hashCode());
66             hashCodeCache = result;
67         }
68         return hashCodeCache;
69     }
70
71     @Override
72     public boolean equals(final Object obj) {
73         if (this == obj) {
74             return true;
75         }
76         if (obj == null) {
77             return false;
78         }
79         if (getClass() != obj.getClass()) {
80             return false;
81         }
82         InstanceIdentifier other = (InstanceIdentifier) obj;
83         if (this.hashCode() != obj.hashCode()) {
84             return false;
85         }
86         if (path == null) {
87             if (other.path != null) {
88                 return false;
89             }
90         } else if (!path.equals(other.path)) {
91             return false;
92         }
93         return true;
94     }
95
96     public InstanceIdentifier node(final QName name) {
97         return node(new NodeIdentifier(name));
98     }
99
100     public InstanceIdentifier node(final PathArgument arg) {
101         return new InstanceIdentifier(ImmutableList.<PathArgument>builder().addAll(path).add(arg).build());
102     }
103
104     // Static factories & helpers
105
106     public static InstanceIdentifier of(final QName name) {
107         return new InstanceIdentifier(new NodeIdentifier(name));
108     }
109
110     static public InstanceIdentifierBuilder builder() {
111         return new BuilderImpl();
112     }
113
114     static public InstanceIdentifierBuilder builder(final InstanceIdentifier origin) {
115         return new BuilderImpl(origin.getPath());
116     }
117
118     public static InstanceIdentifierBuilder builder(final QName node) {
119         return builder().node(node);
120     }
121
122     public interface PathArgument extends Immutable, Serializable {
123
124         /**
125          * If applicable returns uniqee QName of data node as defined in YANG
126          * Schema.
127          *
128          * This method may return null, if the corresponding schema node, does
129          * not have QName associated, such as in cases of augmentations.
130          *
131          * @return
132          */
133         QName getNodeType();
134
135     }
136
137     public interface InstanceIdentifierBuilder extends Builder<InstanceIdentifier> {
138         InstanceIdentifierBuilder node(QName nodeType);
139
140         InstanceIdentifierBuilder nodeWithKey(QName nodeType, Map<QName, Object> keyValues);
141
142         InstanceIdentifierBuilder nodeWithKey(QName nodeType, QName key, Object value);
143
144         @Deprecated
145         InstanceIdentifier getIdentifier();
146
147         InstanceIdentifier build();
148     }
149
150     /**
151      * Simple path argument identifying a {@link ContainerNode} or {@link LeafNode} leaf
152      * overal data tree.
153      *
154      */
155     public static final class NodeIdentifier implements PathArgument {
156
157         /**
158          *
159          */
160         private static final long serialVersionUID = -2255888212390871347L;
161
162         private final QName nodeType;
163
164         public NodeIdentifier(final QName node) {
165             this.nodeType = node;
166         }
167
168         @Override
169         public QName getNodeType() {
170             return nodeType;
171         }
172
173         @Override
174         public int hashCode() {
175             final int prime = 31;
176             int result = 1;
177             result = prime * result + ((nodeType == null) ? 0 : nodeType.hashCode());
178             return result;
179         }
180
181         @Override
182         public boolean equals(final Object obj) {
183             if (this == obj) {
184                                 return true;
185                         }
186             if (obj == null) {
187                                 return false;
188                         }
189             if (getClass() != obj.getClass()) {
190                                 return false;
191                         }
192             NodeIdentifier other = (NodeIdentifier) obj;
193             if (nodeType == null) {
194                 if (other.nodeType != null) {
195                                         return false;
196                                 }
197             } else if (!nodeType.equals(other.nodeType)) {
198                                 return false;
199                         }
200             return true;
201         }
202
203         @Override
204         public String toString() {
205             return nodeType.toString();
206         }
207     }
208
209     /**
210      *
211      * Composite path argument identifying a {@link MapEntryNode} leaf
212      * overal data tree.
213      *
214      */
215     public static final class NodeIdentifierWithPredicates implements PathArgument {
216
217         /**
218          *
219          */
220         private static final long serialVersionUID = -4787195606494761540L;
221
222         private final QName nodeType;
223         private final Map<QName, Object> keyValues;
224
225         public NodeIdentifierWithPredicates(final QName node, final Map<QName, Object> keyValues) {
226             this.nodeType = node;
227             this.keyValues = ImmutableMap.copyOf(keyValues);
228         }
229
230         public NodeIdentifierWithPredicates(final QName node, final QName key, final Object value) {
231             this.nodeType = node;
232             this.keyValues = ImmutableMap.of(key, value);
233         }
234
235         @Override
236         public QName getNodeType() {
237             return nodeType;
238         }
239
240         public Map<QName, Object> getKeyValues() {
241             return keyValues;
242         }
243
244         @Override
245         public int hashCode() {
246             final int prime = 31;
247             int result = 1;
248             result = prime * result + ((keyValues == null) ? 0 : keyValues.hashCode());
249             result = prime * result + ((nodeType == null) ? 0 : nodeType.hashCode());
250             return result;
251         }
252
253         @Override
254         public boolean equals(final Object obj) {
255             if (this == obj) {
256                                 return true;
257                         }
258             if (obj == null) {
259                                 return false;
260                         }
261             if (getClass() != obj.getClass()) {
262                                 return false;
263                         }
264             NodeIdentifierWithPredicates other = (NodeIdentifierWithPredicates) obj;
265             if (keyValues == null) {
266                 if (other.keyValues != null) {
267                                         return false;
268                                 }
269             } else if (!keyValues.equals(other.keyValues)) {
270                                 return false;
271                         }
272             if (nodeType == null) {
273                 if (other.nodeType != null) {
274                                         return false;
275                                 }
276             } else if (!nodeType.equals(other.nodeType)) {
277                                 return false;
278                         }
279             return true;
280         }
281
282         @Override
283         public String toString() {
284             return nodeType + "[" + keyValues + "]";
285         }
286     }
287
288     /**
289      * Simple path argument identifying a {@link LeafSetEntryNode} leaf
290      * overal data tree.
291      *
292      */
293     public static final class NodeWithValue implements PathArgument {
294
295        /**
296         *
297         * Composite path argument identifying a {@link AugmentationNode} leaf
298         * overal data tree.
299         *
300         */
301         private static final long serialVersionUID = -3637456085341738431L;
302
303         private final QName nodeType;
304         private final Object value;
305
306         public NodeWithValue(final QName node, final Object value) {
307             this.nodeType = node;
308             this.value = value;
309         }
310
311         @Override
312         public QName getNodeType() {
313             return nodeType;
314         }
315
316         public Object getValue() {
317             return value;
318         }
319
320         @Override
321         public int hashCode() {
322             final int prime = 31;
323             int result = 1;
324             result = prime * result + ((value == null) ? 0 : value.hashCode());
325             result = prime * result + ((nodeType == null) ? 0 : nodeType.hashCode());
326             return result;
327         }
328
329         @Override
330         public boolean equals(final Object obj) {
331             if (this == obj) {
332                                 return true;
333                         }
334             if (obj == null) {
335                                 return false;
336                         }
337             if (getClass() != obj.getClass()) {
338                                 return false;
339                         }
340             NodeWithValue other = (NodeWithValue) obj;
341             if (value == null) {
342                 if (other.value != null) {
343                                         return false;
344                                 }
345             } else if (!value.equals(other.value)) {
346                                 return false;
347                         }
348             if (nodeType == null) {
349                 if (other.nodeType != null) {
350                                         return false;
351                                 }
352             } else if (!nodeType.equals(other.nodeType)) {
353                                 return false;
354                         }
355             return true;
356         }
357
358         @Override
359         public String toString() {
360             return nodeType + "[" + value + "]";
361         }
362
363     }
364
365
366     public static final class AugmentationIdentifier implements PathArgument {
367
368         private static final long serialVersionUID = -8122335594681936939L;
369         private final ImmutableSet<QName> childNames;
370
371         @Override
372         public QName getNodeType() {
373             // This should rather throw exception than return always null
374             throw new UnsupportedOperationException("Augmentation node has no QName");
375         }
376
377         public AugmentationIdentifier(final Set<QName> childNames) {
378             this.childNames = ImmutableSet.copyOf(childNames);
379         }
380
381         /**
382          * Augmentation node has no QName
383          */
384         @Deprecated
385         public AugmentationIdentifier(final QName nodeType, final Set<QName> childNames) {
386             this(childNames);
387         }
388
389         public Set<QName> getPossibleChildNames() {
390             return childNames;
391         }
392
393         @Override
394         public String toString() {
395             final StringBuffer sb = new StringBuffer("AugmentationIdentifier{");
396             sb.append("childNames=").append(childNames);
397             sb.append('}');
398             return sb.toString();
399         }
400
401         @Override
402         public boolean equals(final Object o) {
403             if (this == o) {
404                                 return true;
405                         }
406             if (!(o instanceof AugmentationIdentifier)) {
407                                 return false;
408                         }
409
410             AugmentationIdentifier that = (AugmentationIdentifier) o;
411
412             if (!childNames.equals(that.childNames)) {
413                                 return false;
414                         }
415
416             return true;
417         }
418
419         @Override
420         public int hashCode() {
421             return childNames.hashCode();
422         }
423     }
424
425     private static class BuilderImpl implements InstanceIdentifierBuilder {
426
427         private final ImmutableList.Builder<PathArgument> path;
428
429         public BuilderImpl() {
430             path = ImmutableList.<PathArgument> builder();
431         }
432
433         public BuilderImpl(final List<? extends PathArgument> prefix) {
434             path = ImmutableList.<PathArgument> builder();
435             path.addAll(prefix);
436         }
437
438         @Override
439         public InstanceIdentifierBuilder node(final QName nodeType) {
440             path.add(new NodeIdentifier(nodeType));
441             return this;
442         }
443
444         @Override
445         public InstanceIdentifierBuilder nodeWithKey(final QName nodeType, final QName key, final Object value) {
446             path.add(new NodeIdentifierWithPredicates(nodeType, key, value));
447             return this;
448         }
449
450         @Override
451         public InstanceIdentifierBuilder nodeWithKey(final QName nodeType, final Map<QName, Object> keyValues) {
452             path.add(new NodeIdentifierWithPredicates(nodeType, keyValues));
453             return this;
454         }
455
456         @Override
457         @Deprecated
458         public InstanceIdentifier toInstance() {
459             return build();
460         }
461
462         @Override
463         public InstanceIdentifier build() {
464             return new InstanceIdentifier(path.build());
465         }
466
467         @Override
468         @Deprecated
469         public InstanceIdentifier getIdentifier() {
470             return build();
471         }
472     }
473
474     @Override
475     public boolean contains(final InstanceIdentifier other) {
476         if (other == null) {
477             throw new IllegalArgumentException("other should not be null");
478         }
479         final int localSize = this.path.size();
480         final List<PathArgument> otherPath = other.getPath();
481         if (localSize > other.path.size()) {
482             return false;
483         }
484         for (int i = 0; i < localSize; i++) {
485             if (!path.get(i).equals(otherPath.get(i))) {
486                 return false;
487             }
488         }
489         return true;
490     }
491
492     @Override
493     public String toString() {
494         /*
495          * The toStringCache is safe, since the object contract requires
496          * immutability of the object and all objects referenced from this
497          * object.
498          *
499          * Used lists, maps are immutable. Path Arguments (elements) are also
500          * immutable, since the PathArgument contract requires immutability.
501          *
502          * The cache is thread-safe - if multiple computations occurs at the
503          * same time, cache will be overwritten with same result.
504          */
505         if (toStringCache != null) {
506             return toStringCache;
507         }
508         StringBuilder builder = new StringBuilder();
509         for (PathArgument argument : path) {
510             builder.append("/");
511             builder.append(argument.toString());
512         }
513         toStringCache = builder.toString();
514         return toStringCache;
515     }
516 }