Updated Concepts & YANG Binding
[mdsal.git] / yang / yang-binding / src / main / java / org / opendaylight / yangtools / yang / binding / InstanceIdentifier.java
1 /*\r
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
3  *\r
4  * This program and the accompanying materials are made available under the\r
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
6  * and is available at http://www.eclipse.org/legal/epl-v10.html\r
7  */\r
8 package org.opendaylight.yangtools.yang.binding;\r
9 \r
10 import java.util.ArrayList;\r
11 import java.util.Collections;\r
12 import java.util.List;\r
13 \r
14 import org.opendaylight.yangtools.concepts.Builder;\r
15 import org.opendaylight.yangtools.concepts.Immutable;\r
16 import org.opendaylight.yangtools.concepts.Path;\r
17 \r
18 /**\r
19  * Uniquely identifies data location in the overall of data tree \r
20  * modeled by YANG.\r
21  * \r
22  * \r
23  */\r
24 public final class InstanceIdentifier<T extends DataObject> implements Path<InstanceIdentifier<?>>,Immutable {\r
25 \r
26     private final List<PathArgument> path;\r
27     private final Class<T> targetType;\r
28     \r
29     public InstanceIdentifier(Class<T> type) {\r
30         path = Collections.<PathArgument> singletonList(new Item<>(type));\r
31         this.targetType = type;\r
32     }\r
33 \r
34     public InstanceIdentifier(List<PathArgument> path, Class<T> type) {\r
35         this.path = Collections.<PathArgument> unmodifiableList(new ArrayList<>(path));\r
36         this.targetType = type;\r
37     }\r
38 \r
39     /**\r
40      * \r
41      * @return path\r
42      */\r
43     public List<PathArgument> getPath() {\r
44         return this.path;\r
45     }\r
46 \r
47     public Class<T> getTargetType() {\r
48         return this.targetType;\r
49     }\r
50 \r
51     @Override\r
52     public String toString() {\r
53         return "InstanceIdentifier [path=" + path + "]";\r
54     }\r
55 \r
56     /**\r
57      * Path argument of {@link InstanceIdentifier}.\r
58      * <p>\r
59      * Interface which implementations are used as path components of the\r
60      * path in overall data tree.\r
61      *\r
62      */\r
63     public interface PathArgument {\r
64 \r
65         Class<? extends DataObject> getType();\r
66 \r
67     }\r
68 \r
69     public static final class Item<T extends DataObject> implements PathArgument {\r
70         private final Class<T> type;\r
71 \r
72         public Item(Class<T> type) {\r
73             this.type = type;\r
74         }\r
75 \r
76         public Class<T> getType() {\r
77             return type;\r
78         }\r
79 \r
80         @Override\r
81         public int hashCode() {\r
82             final int prime = 31;\r
83             int result = 1;\r
84             result = prime * result + ((type == null) ? 0 : type.hashCode());\r
85             return result;\r
86         }\r
87 \r
88         @Override\r
89         public boolean equals(Object obj) {\r
90             if (this == obj)\r
91                 return true;\r
92             if (obj == null)\r
93                 return false;\r
94             if (getClass() != obj.getClass())\r
95                 return false;\r
96             Item<?> other = (Item<?>) obj;\r
97             if (type == null) {\r
98                 if (other.type != null)\r
99                     return false;\r
100             } else if (!type.equals(other.type))\r
101                 return false;\r
102             return true;\r
103         }\r
104         \r
105         @Override\r
106         public String toString() {\r
107             return type.getName();\r
108         }\r
109     }\r
110 \r
111     public static final class IdentifiableItem<I extends Identifiable<T> & DataObject, T extends Identifier<I>> implements\r
112             PathArgument {\r
113 \r
114         private final T key;\r
115         private final Class<I> type;\r
116 \r
117         public IdentifiableItem(Class<I> type, T key) {\r
118             if (type == null)\r
119                 throw new IllegalArgumentException("Type must not be null.");\r
120             if (key == null)\r
121                 throw new IllegalArgumentException("Key must not be null.");\r
122             this.type = type;\r
123             this.key = key;\r
124         }\r
125 \r
126         T getKey() {\r
127             return this.key;\r
128         }\r
129 \r
130         @Override\r
131         public Class<I> getType() {\r
132             return this.type;\r
133         }\r
134 \r
135         @Override\r
136         public boolean equals(Object obj) {\r
137             if (obj == null) {\r
138                 return false;\r
139             }\r
140             if (obj.hashCode() != hashCode()) {\r
141                 return false;\r
142             }\r
143             if (!(obj instanceof IdentifiableItem<?, ?>)) {\r
144                 return false;\r
145             }\r
146             IdentifiableItem<?, ?> foreign = (IdentifiableItem<?, ?>) obj;\r
147             return key.equals(foreign.getKey());\r
148         }\r
149 \r
150         @Override\r
151         public int hashCode() {\r
152             return key.hashCode();\r
153         }\r
154 \r
155         @Override\r
156         public String toString() {\r
157             return type.getName() + "[key=" + key + "]";\r
158         }\r
159     }\r
160 \r
161     public interface InstanceIdentifierBuilder<T extends DataObject> extends Builder<InstanceIdentifier<T>> {\r
162 \r
163         <N extends DataObject> InstanceIdentifierBuilder<N> node(Class<N> container);\r
164 \r
165         <N extends Identifiable<K> & DataObject, K extends Identifier<N>> InstanceIdentifierBuilder<N> node(\r
166                 Class<N> listItem, K listKey);\r
167 \r
168         <N extends ChildOf<? super T>> InstanceIdentifierBuilder<N> child(Class<N> container);\r
169         \r
170         <N extends Identifiable<K> & ChildOf<? super T>, K extends Identifier<N>> InstanceIdentifierBuilder<N> child(\r
171                 Class<N> listItem, K listKey);\r
172 \r
173     }\r
174 \r
175     @SuppressWarnings("rawtypes")\r
176     public static InstanceIdentifierBuilder<?> builder() {\r
177         return new BuilderImpl();\r
178     }\r
179 \r
180     @SuppressWarnings({ "rawtypes", "unchecked" })\r
181     public static InstanceIdentifierBuilder<?> builder(InstanceIdentifier<?> basePath) {\r
182         return new BuilderImpl(basePath.path,basePath.targetType);\r
183     }\r
184 \r
185     private static final class BuilderImpl<T extends DataObject> implements InstanceIdentifierBuilder<T> {\r
186 \r
187         private List<PathArgument> path;\r
188         private Class<? extends DataObject> target = null;\r
189 \r
190         public BuilderImpl() {\r
191             this.path = new ArrayList<>();\r
192         }\r
193         \r
194 \r
195         public BuilderImpl(List<? extends PathArgument> prefix,Class<? extends DataObject> target) {\r
196             this.path = new ArrayList<>(prefix);\r
197             this.target = target;\r
198         }\r
199 \r
200         @SuppressWarnings({ "unchecked", "rawtypes" })\r
201         @Override\r
202         public InstanceIdentifier<T> toInstance() {\r
203             List<PathArgument> immutablePath = Collections.unmodifiableList(new ArrayList<PathArgument>(path));\r
204             return new InstanceIdentifier(immutablePath, target);\r
205         }\r
206 \r
207         @Override\r
208         @SuppressWarnings("unchecked")\r
209         public <N extends DataObject> InstanceIdentifierBuilder<N> node(Class<N> container) {\r
210             target = container;\r
211             path.add(new Item<N>(container));\r
212             return (InstanceIdentifierBuilder<N>) this;\r
213         }\r
214 \r
215         @Override\r
216         @SuppressWarnings("unchecked")\r
217         public <N extends DataObject & Identifiable<K> , K extends Identifier<N>> InstanceIdentifierBuilder<N> node(\r
218                 Class<N> listItem, K listKey) {\r
219             target = listItem;\r
220             path.add(new IdentifiableItem<N, K>(listItem, listKey));\r
221             return (InstanceIdentifierBuilder<N>) this;\r
222         }\r
223         \r
224         @Override\r
225         public <N extends ChildOf<? super T>> InstanceIdentifierBuilder<N> child(Class<N> container) {\r
226             return node(container);\r
227         }\r
228         \r
229         @Override\r
230         public <N extends Identifiable<K> & ChildOf<? super T>, K extends Identifier<N>> InstanceIdentifierBuilder<N> child(\r
231                 Class<N> listItem, K listKey) {\r
232             return node(listItem,listKey);\r
233         }\r
234     }\r
235 \r
236     @Override\r
237     public int hashCode() {\r
238         final int prime = 31;\r
239         int result = 1;\r
240         result = prime * result + ((path == null) ? 0 : path.hashCode());\r
241         return result;\r
242     }\r
243 \r
244     @Override\r
245     public boolean equals(Object obj) {\r
246         if (this == obj) {\r
247             return true;\r
248         }\r
249         if (obj == null) {\r
250             return false;\r
251         }\r
252         if (getClass() != obj.getClass()) {\r
253             return false;\r
254         }\r
255         InstanceIdentifier<?> other = (InstanceIdentifier<?>) obj;\r
256         if (path == null) {\r
257             if (other.path != null) {\r
258                 return false;\r
259             }\r
260         } else if (!path.equals(other.path)) {\r
261             return false;\r
262         }\r
263         return true;\r
264     }\r
265 \r
266     @Override\r
267     public boolean contains(final InstanceIdentifier<?> other) {\r
268         if(other == null) {\r
269             throw new IllegalArgumentException("other should not be null");\r
270         }\r
271         final int localSize = this.path.size();\r
272         final List<PathArgument> otherPath = other.getPath();\r
273         if(localSize > other.path.size()) {\r
274             return false;\r
275         }\r
276         for(int i = 0;i<localSize;i++ ) {\r
277             if(!path.get(i).equals(otherPath.get(i))) {\r
278                 return false;\r
279             }\r
280         }\r
281         \r
282         return true;\r
283     }\r
284 }\r