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