Merge "public modifier added"
[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<?>>,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         <N extends DataObject> InstanceIdentifierBuilder<N> node(Class<N> container);
164
165         <N extends Identifiable<K> & DataObject, K extends Identifier<N>> InstanceIdentifierBuilder<N> node(
166                 Class<N> listItem, K listKey);
167
168         <N extends ChildOf<? super T>> InstanceIdentifierBuilder<N> child(Class<N> container);
169         
170         <N extends Identifiable<K> & ChildOf<? super T>, K extends Identifier<N>> InstanceIdentifierBuilder<N> child(
171                 Class<N> listItem, K listKey);
172
173     }
174
175     @SuppressWarnings("rawtypes")
176     public static InstanceIdentifierBuilder<?> builder() {
177         return new BuilderImpl();
178     }
179
180     @SuppressWarnings({ "rawtypes", "unchecked" })
181     public static InstanceIdentifierBuilder<?> builder(InstanceIdentifier<?> basePath) {
182         return new BuilderImpl(basePath.path,basePath.targetType);
183     }
184
185     private static final class BuilderImpl<T extends DataObject> implements InstanceIdentifierBuilder<T> {
186
187         private List<PathArgument> path;
188         private Class<? extends DataObject> target = null;
189
190         public BuilderImpl() {
191             this.path = new ArrayList<>();
192         }
193         
194
195         public BuilderImpl(List<? extends PathArgument> prefix,Class<? extends DataObject> target) {
196             this.path = new ArrayList<>(prefix);
197             this.target = target;
198         }
199
200         @SuppressWarnings({ "unchecked", "rawtypes" })
201         @Override
202         public InstanceIdentifier<T> toInstance() {
203             List<PathArgument> immutablePath = Collections.unmodifiableList(new ArrayList<PathArgument>(path));
204             return new InstanceIdentifier(immutablePath, target);
205         }
206
207         @Override
208         @SuppressWarnings("unchecked")
209         public <N extends DataObject> InstanceIdentifierBuilder<N> node(Class<N> container) {
210             target = container;
211             path.add(new Item<N>(container));
212             return (InstanceIdentifierBuilder<N>) this;
213         }
214
215         @Override
216         @SuppressWarnings("unchecked")
217         public <N extends DataObject & Identifiable<K> , K extends Identifier<N>> InstanceIdentifierBuilder<N> node(
218                 Class<N> listItem, K listKey) {
219             target = listItem;
220             path.add(new IdentifiableItem<N, K>(listItem, listKey));
221             return (InstanceIdentifierBuilder<N>) this;
222         }
223         
224         @Override
225         public <N extends ChildOf<? super T>> InstanceIdentifierBuilder<N> child(Class<N> container) {
226             return node(container);
227         }
228         
229         @Override
230         public <N extends Identifiable<K> & ChildOf<? super T>, K extends Identifier<N>> InstanceIdentifierBuilder<N> child(
231                 Class<N> listItem, K listKey) {
232             return node(listItem,listKey);
233         }
234     }
235
236     @Override
237     public int hashCode() {
238         final int prime = 31;
239         int result = 1;
240         result = prime * result + ((path == null) ? 0 : path.hashCode());
241         return result;
242     }
243
244     @Override
245     public boolean equals(Object obj) {
246         if (this == obj) {
247             return true;
248         }
249         if (obj == null) {
250             return false;
251         }
252         if (getClass() != obj.getClass()) {
253             return false;
254         }
255         InstanceIdentifier<?> other = (InstanceIdentifier<?>) obj;
256         if (path == null) {
257             if (other.path != null) {
258                 return false;
259             }
260         } else if (!path.equals(other.path)) {
261             return false;
262         }
263         return true;
264     }
265
266     @Override
267     public boolean contains(final InstanceIdentifier<?> other) {
268         if(other == null) {
269             throw new IllegalArgumentException("other should not be null");
270         }
271         final int localSize = this.path.size();
272         final List<PathArgument> otherPath = other.getPath();
273         if(localSize > other.path.size()) {
274             return false;
275         }
276         for(int i = 0;i<localSize;i++ ) {
277             if(!path.get(i).equals(otherPath.get(i))) {
278                 return false;
279             }
280         }
281         
282         return true;
283     }
284 }