Merge "BUG-582: use shared thread-safe SimpleDateFormat"
[yangtools.git] / yang / yang-model-api / src / main / java / org / opendaylight / yangtools / yang / model / api / SchemaPath.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.model.api;
9
10 import java.util.Arrays;
11 import java.util.Collections;
12 import java.util.List;
13
14 import org.opendaylight.yangtools.yang.common.QName;
15
16 import com.google.common.base.Preconditions;
17 import com.google.common.collect.ImmutableList;
18 import com.google.common.collect.Iterables;
19
20 /**
21  *
22  * Represents unique path to the every node inside the module.
23  *
24  */
25 public class SchemaPath {
26     /**
27      * Shared instance of the conceptual root schema node.
28      */
29     public static final SchemaPath ROOT = SchemaPath.create(Collections.<QName>emptyList(), true);
30
31     /**
32      * Shared instance of the "same" relative schema node.
33      */
34     public static final SchemaPath SAME = SchemaPath.create(Collections.<QName>emptyList(), false);
35
36     /**
37      * List of QName instances which represents complete path to the node.
38      */
39     private final ImmutableList<QName> path;
40
41     /**
42      * Boolean value which represents type of schema path (relative or
43      * absolute).
44      */
45     private final Boolean absolute;
46
47     /**
48      * Constructs new instance of this class with the concrete path.
49      *
50      * @param path
51      *            list of QName instances which specifies exact path to the
52      *            module node
53      * @param absolute
54      *            boolean value which specifies if the path is absolute or
55      *            relative
56      *
57      * @deprecated Use {@link #create(Iterable, boolean)} instead.
58      */
59     @Deprecated
60     public SchemaPath(final List<QName> path, final boolean absolute) {
61         this(ImmutableList.copyOf(path), absolute, null);
62     }
63
64     /**
65      * Returns the complete path to schema node.
66      *
67      * @return list of <code>QName</code> instances which represents complete
68      *         path to schema node
69      *
70      * @deprecated Use {@link #getPathFromRoot()} instead.
71      */
72     @Deprecated
73     public List<QName> getPath() {
74         return path;
75     }
76
77     private SchemaPath(final ImmutableList<QName> path, final boolean absolute, final Void dummy) {
78         this.path = Preconditions.checkNotNull(path);
79         this.absolute = absolute;
80     }
81
82     /**
83      * Constructs new instance of this class with the concrete path.
84      *
85      * @param path
86      *            list of QName instances which specifies exact path to the
87      *            module node
88      * @param absolute
89      *            boolean value which specifies if the path is absolute or
90      *            relative
91      *
92      * @return A SchemaPath instance.
93      */
94     public static SchemaPath create(final Iterable<QName> path, final boolean absolute) {
95         if (Iterables.isEmpty(path)) {
96             return absolute ? ROOT : SAME;
97         } else {
98             return new SchemaPath(ImmutableList.copyOf(path), absolute, null);
99         }
100     }
101
102     /**
103      * Constructs new instance of this class with the concrete path.
104      *
105      * @param absolute
106      *            boolean value which specifies if the path is absolute or
107      *            relative
108      * @param path
109      *            one or more QName instances which specifies exact path to the
110      *            module node
111      *
112      * @return A SchemaPath instance.
113      */
114     public static SchemaPath create(final boolean absolute, final QName... path) {
115         return create(Arrays.asList(path), absolute);
116     }
117
118     /**
119      * Create a child path based on concatenation of this path and a relative path.
120      *
121      * @param relative Relative path
122      * @return A new child path
123      */
124     public SchemaPath createChild(final Iterable<QName> relative) {
125         if (Iterables.isEmpty(relative)) {
126             return this;
127         }
128         return create(Iterables.concat(path, relative), absolute);
129     }
130
131     /**
132      * Create a child path based on concatenation of this path and a relative path.
133      *
134      * @param relative Relative SchemaPath
135      * @return A new child path
136      */
137     public SchemaPath createChild(final SchemaPath relative) {
138         Preconditions.checkArgument(!relative.isAbsolute(), "Child creation requires relative path");
139         return createChild(relative.path);
140     }
141
142     /**
143      * Create a child path based on concatenation of this path and additional
144      * path elements.
145      *
146      * @param elements Relative SchemaPath elements
147      * @return A new child path
148      */
149     public SchemaPath createChild(final QName... elements) {
150         return createChild(Arrays.asList(elements));
151     }
152
153     /**
154      * Returns the list of nodes which need to be traversed to get from the
155      * starting point (root for absolute SchemaPaths) to the node represented
156      * by this object.
157      *
158      * @return list of <code>qname</code> instances which represents
159      *         path from the root to the schema node.
160      */
161     public Iterable<QName> getPathFromRoot() {
162         return path;
163     }
164
165     /**
166      * Returns the list of nodes which need to be traversed to get from this
167      * node to the starting point (root for absolute SchemaPaths).
168      *
169      * @return list of <code>qname</code> instances which represents
170      *         path from the schema node towards the root.
171      */
172     public Iterable<QName> getPathTowardsRoot() {
173         return path.reverse();
174     }
175
176     /**
177      * Describes whether schema path is|isn't absolute.
178      *
179      * @return boolean value which is <code>true</code> if schema path is
180      *         absolute.
181      */
182     public boolean isAbsolute() {
183         return absolute;
184     }
185
186     @Override
187     public int hashCode() {
188         final int prime = 31;
189         int result = 1;
190         result = prime * result + absolute.hashCode();
191         for (Object o : path) {
192             result = prime * result + o.hashCode();
193         }
194         return result;
195     }
196
197     @Override
198     public boolean equals(final Object obj) {
199         if (this == obj) {
200             return true;
201         }
202         if (obj == null) {
203             return false;
204         }
205         if (getClass() != obj.getClass()) {
206             return false;
207         }
208         SchemaPath other = (SchemaPath) obj;
209         if (absolute != other.absolute) {
210             return false;
211         }
212
213         return Iterables.elementsEqual(path, other.path);
214     }
215
216     @Override
217     public String toString() {
218         StringBuilder builder = new StringBuilder();
219         builder.append("SchemaPath [path=");
220         builder.append(path);
221         builder.append(", absolute=");
222         builder.append(absolute);
223         builder.append("]");
224         return builder.toString();
225     }
226 }