Fixed bug with Key generation with fields added from grouping
[yangtools.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.Mutable;\r
17 \r
18 /**\r
19  * Uniquely identifies instance of data tree.\r
20  * \r
21  */\r
22 public final class InstanceIdentifier implements Immutable {\r
23 \r
24     private final List<PathArgument> path;\r
25     private final Class<? extends DataObject> targetType;\r
26 \r
27     public InstanceIdentifier(Class<? extends DataObject> type) {\r
28         path = Collections.<PathArgument> singletonList(new Item<>(type));\r
29         this.targetType = type;\r
30     }\r
31 \r
32     public InstanceIdentifier(List<PathArgument> path, Class<? extends DataObject> type) {\r
33         this.path = Collections.<PathArgument> unmodifiableList(new ArrayList<>(path));\r
34         this.targetType = type;\r
35     }\r
36 \r
37     /**\r
38      * \r
39      * @return path\r
40      */\r
41     public List<PathArgument> getPath() {\r
42         return this.path;\r
43     }\r
44 \r
45     public Class<?> getTargetType() {\r
46         return this.targetType;\r
47     }\r
48 \r
49     @Override\r
50     public String toString() {\r
51         return "InstanceIdentifier [path=" + path + "]";\r
52     }\r
53 \r
54     /**\r
55      * Path argument of instance identifier.\r
56      * \r
57      * Interface which implementations are used as path components of the\r
58      * instance path.\r
59      * \r
60      * @author ttkacik\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 \r
106     public static final class IdentifiableItem<I extends Identifiable<T> & DataObject, T extends Identifier<I>> implements\r
107             PathArgument {\r
108 \r
109         private final T key;\r
110         private final Class<I> type;\r
111 \r
112         public IdentifiableItem(Class<I> type, T key) {\r
113             if (type == null)\r
114                 throw new IllegalArgumentException("Type must not be null.");\r
115             if (key == null)\r
116                 throw new IllegalArgumentException("Key must not be null.");\r
117             this.type = type;\r
118             this.key = key;\r
119         }\r
120 \r
121         T getKey() {\r
122             return this.key;\r
123         }\r
124 \r
125         @Override\r
126         public Class<I> getType() {\r
127             return this.type;\r
128         }\r
129 \r
130         @Override\r
131         public boolean equals(Object obj) {\r
132             if (obj == null) {\r
133                 return false;\r
134             }\r
135             if (obj.hashCode() != hashCode()) {\r
136                 return false;\r
137             }\r
138             if (!(obj instanceof IdentifiableItem<?, ?>)) {\r
139                 return false;\r
140             }\r
141             IdentifiableItem<?, ?> foreign = (IdentifiableItem<?, ?>) obj;\r
142             return key.equals(foreign.getKey());\r
143         }\r
144 \r
145         @Override\r
146         public int hashCode() {\r
147             return key.hashCode();\r
148         }\r
149 \r
150         @Override\r
151         public String toString() {\r
152             return type.getName() + "[key=" + key + "]";\r
153         }\r
154     }\r
155 \r
156     public interface InstanceIdentifierBuilder extends Builder<InstanceIdentifier> {\r
157 \r
158         <T extends DataObject> InstanceIdentifierBuilder node(Class<T> container);\r
159 \r
160         <I extends Identifiable<T> & DataObject, T extends Identifier<I>> InstanceIdentifierBuilder node(\r
161                 Class<I> listItem, T listKey);\r
162 \r
163     }\r
164 \r
165     public static InstanceIdentifierBuilder builder() {\r
166         return new BuilderImpl();\r
167     }\r
168 \r
169     private static class BuilderImpl implements InstanceIdentifierBuilder {\r
170 \r
171         private List<PathArgument> path;\r
172         private Class<? extends DataObject> target = null;\r
173 \r
174         @Override\r
175         public InstanceIdentifier toInstance() {\r
176             List<PathArgument> immutablePath = Collections.unmodifiableList(new ArrayList<PathArgument>(path));\r
177             return new InstanceIdentifier(immutablePath, target);\r
178         }\r
179 \r
180         @Override\r
181         public <T extends DataObject> InstanceIdentifierBuilder node(Class<T> container) {\r
182             target = container;\r
183             path.add(new Item<T>(container));\r
184             return this;\r
185         }\r
186 \r
187         @Override\r
188         public <I extends Identifiable<T> & DataObject, T extends Identifier<I>> InstanceIdentifierBuilder node(\r
189                 Class<I> listItem, T listKey) {\r
190             target = listItem;\r
191             path.add(new IdentifiableItem<I, T>(listItem, listKey));\r
192             return this;\r
193         }\r
194     }\r
195 \r
196     @Override\r
197     public int hashCode() {\r
198         final int prime = 31;\r
199         int result = 1;\r
200         result = prime * result + ((path == null) ? 0 : path.hashCode());\r
201         return result;\r
202     }\r
203 \r
204     @Override\r
205     public boolean equals(Object obj) {\r
206         if (this == obj) {\r
207             return true;\r
208         }\r
209         if (obj == null) {\r
210             return false;\r
211         }\r
212         if (getClass() != obj.getClass()) {\r
213             return false;\r
214         }\r
215         InstanceIdentifier other = (InstanceIdentifier) obj;\r
216         if (path == null) {\r
217             if (other.path != null) {\r
218                 return false;\r
219             }\r
220         } else if (!path.equals(other.path)) {\r
221             return false;\r
222         }\r
223         return true;\r
224     }\r
225 }\r