Merge "Yang parser refactoring."
[yangtools.git] / yang / yang-data-impl / src / main / java / org / opendaylight / yangtools / yang / data / impl / codec / TypeDefinitionAwareCodec.java
1 package org.opendaylight.yangtools.yang.data.impl.codec;
2
3 import static org.opendaylight.yangtools.yang.model.util.BaseTypes.INT16_QNAME;
4 import static org.opendaylight.yangtools.yang.model.util.BaseTypes.INT32_QNAME;
5 import static org.opendaylight.yangtools.yang.model.util.BaseTypes.INT64_QNAME;
6 import static org.opendaylight.yangtools.yang.model.util.BaseTypes.INT8_QNAME;
7 import static org.opendaylight.yangtools.yang.model.util.BaseTypes.UINT16_QNAME;
8 import static org.opendaylight.yangtools.yang.model.util.BaseTypes.UINT32_QNAME;
9 import static org.opendaylight.yangtools.yang.model.util.BaseTypes.UINT64_QNAME;
10 import static org.opendaylight.yangtools.yang.model.util.BaseTypes.UINT8_QNAME;
11
12 import java.math.BigDecimal;
13 import java.math.BigInteger;
14 import java.util.Set;
15
16 import org.opendaylight.yangtools.yang.data.api.codec.BinaryCodec;
17 import org.opendaylight.yangtools.yang.data.api.codec.BitsCodec;
18 import org.opendaylight.yangtools.yang.data.api.codec.BooleanCodec;
19 import org.opendaylight.yangtools.yang.data.api.codec.DecimalCodec;
20 import org.opendaylight.yangtools.yang.data.api.codec.EmptyCodec;
21 import org.opendaylight.yangtools.yang.data.api.codec.EnumCodec;
22 import org.opendaylight.yangtools.yang.data.api.codec.Int16Codec;
23 import org.opendaylight.yangtools.yang.data.api.codec.Int32Codec;
24 import org.opendaylight.yangtools.yang.data.api.codec.Int64Codec;
25 import org.opendaylight.yangtools.yang.data.api.codec.Int8Codec;
26 import org.opendaylight.yangtools.yang.data.api.codec.StringCodec;
27 import org.opendaylight.yangtools.yang.data.api.codec.Uint16Codec;
28 import org.opendaylight.yangtools.yang.data.api.codec.Uint32Codec;
29 import org.opendaylight.yangtools.yang.data.api.codec.Uint64Codec;
30 import org.opendaylight.yangtools.yang.data.api.codec.Uint8Codec;
31 import org.opendaylight.yangtools.yang.data.api.codec.UnionCodec;
32 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
33 import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition;
34 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
35 import org.opendaylight.yangtools.yang.model.api.type.BooleanTypeDefinition;
36 import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
37 import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
38 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
39 import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
40 import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
41 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
42 import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
43
44 import com.google.common.base.Joiner;
45 import com.google.common.base.Optional;
46 import com.google.common.base.Preconditions;
47 import com.google.common.base.Splitter;
48 import com.google.common.collect.ImmutableSet;
49 import com.google.common.io.BaseEncoding;
50
51 public abstract class TypeDefinitionAwareCodec<J, T extends TypeDefinition<T>> implements DataStringCodec<J> {
52
53     private final Optional<T> typeDefinition;
54     private final Class<J> inputClass;
55
56     public static final BinaryCodecStringImpl BINARY_DEFAULT_CODEC = new BinaryCodecStringImpl(
57             Optional.<BinaryTypeDefinition> absent());
58
59     public static final BitsCodecStringImpl BITS_DEFAULT_CODEC = new BitsCodecStringImpl(
60             Optional.<BitsTypeDefinition> absent());
61
62     public static final BooleanCodecStringImpl BOOLEAN_DEFAULT_CODEC = new BooleanCodecStringImpl(
63             Optional.<BooleanTypeDefinition> absent());
64
65     public static final DecimalCodecStringImpl DECIMAL64_DEFAULT_CODEC = new DecimalCodecStringImpl(
66             Optional.<DecimalTypeDefinition> absent());
67
68     public static final EmptyCodecStringImpl EMPTY_DEFAULT_CODEC = new EmptyCodecStringImpl(
69             Optional.<EmptyTypeDefinition> absent());
70
71     public static final EnumCodecStringImpl ENUMERATION_DEFAULT_CODEC = new EnumCodecStringImpl(
72             Optional.<EnumTypeDefinition> absent());
73
74     public static final Int8CodecStringImpl INT8_DEFAULT_CODEC = new Int8CodecStringImpl(
75             Optional.<IntegerTypeDefinition> absent());
76
77     public static final Int16CodecStringImpl INT16_DEFAULT_CODEC = new Int16CodecStringImpl(
78             Optional.<IntegerTypeDefinition> absent());
79
80     public static final Int32CodecStringImpl INT32_DEFAULT_CODEC = new Int32CodecStringImpl(
81             Optional.<IntegerTypeDefinition> absent());
82
83     public static final Int64CodecStringImpl INT64_DEFAULT_CODEC = new Int64CodecStringImpl(
84             Optional.<IntegerTypeDefinition> absent());
85
86     public static final StringCodecStringImpl STRING_DEFAULT_CODEC = new StringCodecStringImpl(
87             Optional.<StringTypeDefinition> absent());
88
89     public static final Uint8CodecStringImpl UINT8_DEFAULT_CODEC = new Uint8CodecStringImpl(
90             Optional.<UnsignedIntegerTypeDefinition> absent());
91
92     public static final Uint16CodecStringImpl UINT16_DEFAULT_CODEC = new Uint16CodecStringImpl(
93             Optional.<UnsignedIntegerTypeDefinition> absent());
94
95     public static final Uint32CodecStringImpl UINT32_DEFAULT_CODEC = new Uint32CodecStringImpl(
96             Optional.<UnsignedIntegerTypeDefinition> absent());
97
98     public static final Uint64CodecStringImpl UINT64_DEFAULT_CODEC = new Uint64CodecStringImpl(
99             Optional.<UnsignedIntegerTypeDefinition> absent());
100
101     public static final UnionCodecStringImpl UNION_DEFAULT_CODEC = new UnionCodecStringImpl(
102             Optional.<UnionTypeDefinition> absent());
103
104     public Class<J> getInputClass() {
105         return inputClass;
106     }
107
108     protected TypeDefinitionAwareCodec(Optional<T> typeDefinition, Class<J> outputClass) {
109         Preconditions.checkArgument(outputClass != null, "Output class must be specified.");
110         this.typeDefinition = typeDefinition;
111         this.inputClass = outputClass;
112     }
113
114     public Optional<T> getTypeDefinition() {
115         return typeDefinition;
116     }
117
118     @SuppressWarnings({ "rawtypes", "unchecked" })
119     public static final TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>> from(TypeDefinition typeDefinition) {
120         final TypeDefinitionAwareCodec codec = fromType(typeDefinition);
121         return (TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>>) codec;
122     }
123
124     public static final <T extends TypeDefinition<T>> TypeDefinitionAwareCodec<?, T> fromType(T typeDefinition) {
125         T superType = typeDefinition;
126         while (superType.getBaseType() != null) {
127             superType = superType.getBaseType();
128         }
129
130         @SuppressWarnings("rawtypes")
131         TypeDefinitionAwareCodec codec = null;
132
133         if (superType instanceof BinaryTypeDefinition) {
134             codec = BINARY_DEFAULT_CODEC;
135         } else if (superType instanceof BitsTypeDefinition) {
136             codec = BITS_DEFAULT_CODEC;
137         } else if (superType instanceof BooleanTypeDefinition) {
138             codec = BOOLEAN_DEFAULT_CODEC;
139         } else if (superType instanceof DecimalTypeDefinition) {
140             codec = DECIMAL64_DEFAULT_CODEC;
141         } else if (superType instanceof EmptyTypeDefinition) {
142             codec = EMPTY_DEFAULT_CODEC;
143         } else if (superType instanceof EnumTypeDefinition) {
144             codec = ENUMERATION_DEFAULT_CODEC;
145         } else if (superType instanceof IntegerTypeDefinition) {
146             if (INT8_QNAME.equals(superType.getQName())) {
147                 codec = INT8_DEFAULT_CODEC;
148             } else if (INT16_QNAME.equals(superType.getQName())) {
149                 codec = INT16_DEFAULT_CODEC;
150             } else if (INT32_QNAME.equals(superType.getQName())) {
151                 codec = INT32_DEFAULT_CODEC;
152             } else if (INT64_QNAME.equals(superType.getQName())) {
153                 codec = INT64_DEFAULT_CODEC;
154             }
155         } else if (superType instanceof StringTypeDefinition) {
156             codec = STRING_DEFAULT_CODEC;
157         } else if (superType instanceof UnionTypeDefinition) {
158             codec = UNION_DEFAULT_CODEC;
159         } else if (superType instanceof UnsignedIntegerTypeDefinition) {
160             if (UINT8_QNAME.equals(superType.getQName())) {
161                 codec = UINT8_DEFAULT_CODEC;
162             }
163             if (UINT16_QNAME.equals(superType.getQName())) {
164                 codec = UINT16_DEFAULT_CODEC;
165             }
166             if (UINT32_QNAME.equals(superType.getQName())) {
167                 codec = UINT32_DEFAULT_CODEC;
168             }
169             if (UINT64_QNAME.equals(superType.getQName())) {
170                 codec = UINT64_DEFAULT_CODEC;
171             }
172         }
173         return (TypeDefinitionAwareCodec<?, T>) codec;
174     }
175
176     public static class BooleanCodecStringImpl extends TypeDefinitionAwareCodec<Boolean, BooleanTypeDefinition>
177             implements BooleanCodec<String> {
178
179         protected BooleanCodecStringImpl(Optional<BooleanTypeDefinition> typeDef) {
180             super(typeDef, Boolean.class);
181         }
182
183         @Override
184         public String serialize(Boolean data) {
185             return data.toString();
186         }
187
188         @Override
189         public Boolean deserialize(String stringRepresentation) {
190             return Boolean.parseBoolean(stringRepresentation);
191         }
192     };
193
194     public static class Uint8CodecStringImpl extends TypeDefinitionAwareCodec<Short, UnsignedIntegerTypeDefinition>
195             implements Uint8Codec<String> {
196
197         protected Uint8CodecStringImpl(Optional<UnsignedIntegerTypeDefinition> typeDef) {
198             super(typeDef, Short.class);
199         }
200
201         @Override
202         public String serialize(Short data) {
203             return data.toString();
204         }
205
206         @Override
207         public Short deserialize(String stringRepresentation) {
208             return Short.parseShort(stringRepresentation);
209         }
210     };
211
212     public static class Uint16CodecStringImpl extends TypeDefinitionAwareCodec<Integer, UnsignedIntegerTypeDefinition>
213             implements Uint16Codec<String> {
214         protected Uint16CodecStringImpl(Optional<UnsignedIntegerTypeDefinition> typeDef) {
215             super(typeDef, Integer.class);
216         }
217
218         @Override
219         public Integer deserialize(String stringRepresentation) {
220             return Integer.parseInt(stringRepresentation);
221         }
222
223         @Override
224         public String serialize(Integer data) {
225             return data.toString();
226         }
227     };
228
229     public static class Uint32CodecStringImpl extends TypeDefinitionAwareCodec<Long, UnsignedIntegerTypeDefinition>
230             implements Uint32Codec<String> {
231
232         protected Uint32CodecStringImpl(Optional<UnsignedIntegerTypeDefinition> typeDef) {
233             super(typeDef, Long.class);
234         }
235
236         @Override
237         public Long deserialize(String stringRepresentation) {
238             return Long.parseLong(stringRepresentation);
239         }
240
241         @Override
242         public String serialize(Long data) {
243             return data.toString();
244         }
245     };
246
247     public static class Uint64CodecStringImpl extends
248             TypeDefinitionAwareCodec<BigInteger, UnsignedIntegerTypeDefinition> implements Uint64Codec<String> {
249
250         protected Uint64CodecStringImpl(Optional<UnsignedIntegerTypeDefinition> typeDef) {
251             super(typeDef, BigInteger.class);
252         }
253
254         @Override
255         public BigInteger deserialize(String stringRepresentation) {
256             // FIXME: Implement codec correctly
257             return BigInteger.valueOf(Long.valueOf(stringRepresentation));
258         }
259
260         @Override
261         public String serialize(BigInteger data) {
262             return data.toString();
263         }
264     };
265
266     public static class StringCodecStringImpl extends TypeDefinitionAwareCodec<String, StringTypeDefinition> implements
267             StringCodec<String> {
268
269         protected StringCodecStringImpl(Optional<StringTypeDefinition> typeDef) {
270             super(typeDef, String.class);
271         }
272
273         @Override
274         public String deserialize(String stringRepresentation) {
275             return stringRepresentation;
276         }
277
278         @Override
279         public String serialize(String data) {
280             return data.toString();
281         }
282     };
283
284     public static class Int16CodecStringImpl extends TypeDefinitionAwareCodec<Short, IntegerTypeDefinition> implements
285             Int16Codec<String> {
286
287         protected Int16CodecStringImpl(Optional<IntegerTypeDefinition> typeDef) {
288             super(typeDef, Short.class);
289         }
290
291         @Override
292         public Short deserialize(String stringRepresentation) {
293             return Short.valueOf(stringRepresentation);
294         }
295
296         @Override
297         public String serialize(Short data) {
298             return data.toString();
299         }
300     };
301
302     public static class Int32CodecStringImpl extends TypeDefinitionAwareCodec<Integer, IntegerTypeDefinition> implements
303             Int32Codec<String> {
304
305         protected Int32CodecStringImpl(Optional<IntegerTypeDefinition> typeDef) {
306             super(typeDef, Integer.class);
307         }
308
309         @Override
310         public Integer deserialize(String stringRepresentation) {
311             return Integer.valueOf(stringRepresentation);
312         }
313
314         @Override
315         public String serialize(Integer data) {
316             return data.toString();
317         }
318     };
319
320     public static class Int64CodecStringImpl extends TypeDefinitionAwareCodec<Long, IntegerTypeDefinition> implements
321             Int64Codec<String> {
322
323         protected Int64CodecStringImpl(Optional<IntegerTypeDefinition> typeDef) {
324             super(typeDef, Long.class);
325         }
326
327         @Override
328         public Long deserialize(String stringRepresentation) {
329             return Long.parseLong(stringRepresentation);
330         }
331
332         @Override
333         public String serialize(Long data) {
334             return data.toString();
335         }
336     };
337
338     public static class Int8CodecStringImpl extends TypeDefinitionAwareCodec<Byte, IntegerTypeDefinition> implements
339             Int8Codec<String> {
340
341         protected Int8CodecStringImpl(Optional<IntegerTypeDefinition> typeDef) {
342             super(typeDef, Byte.class);
343         }
344
345         @Override
346         public Byte deserialize(String stringRepresentation) {
347             return Byte.parseByte(stringRepresentation);
348         }
349
350         @Override
351         public String serialize(Byte data) {
352             return data.toString();
353         }
354     };
355
356     public static class EmptyCodecStringImpl extends TypeDefinitionAwareCodec<Void, EmptyTypeDefinition> implements
357             EmptyCodec<String> {
358
359         protected EmptyCodecStringImpl(Optional<EmptyTypeDefinition> typeDef) {
360             super(typeDef, Void.class);
361         }
362
363         @Override
364         public String serialize(Void data) {
365             return "";
366         }
367
368         @Override
369         public Void deserialize(String stringRepresentation) {
370             return null;
371         }
372     };
373
374     public static final class BinaryCodecStringImpl extends TypeDefinitionAwareCodec<byte[], BinaryTypeDefinition>
375             implements BinaryCodec<String> {
376
377         protected BinaryCodecStringImpl(Optional<BinaryTypeDefinition> typeDef) {
378             super(typeDef, byte[].class);
379         }
380
381         @Override
382         public String serialize(byte[] data) {
383             return BaseEncoding.base64().encode(data);
384         }
385
386         @Override
387         public byte[] deserialize(String stringRepresentation) {
388             return BaseEncoding.base64().decode(stringRepresentation);
389         }
390     };
391
392     public static final class BitsCodecStringImpl extends TypeDefinitionAwareCodec<Set<String>, BitsTypeDefinition>
393             implements BitsCodec<String> {
394
395         public static final Joiner JOINER = Joiner.on(" ").skipNulls();
396         public static final Splitter SPLITTER = Splitter.on(' ').omitEmptyStrings().trimResults();
397
398         @SuppressWarnings("unchecked")
399         protected BitsCodecStringImpl(Optional<BitsTypeDefinition> typeDef) {
400             super(typeDef, (Class<Set<String>>) ((Class<?>) Set.class));
401         }
402
403         @Override
404         public String serialize(Set<String> data) {
405             return data != null ? JOINER.join(data) : "";
406         }
407
408         @Override
409         public Set<String> deserialize(String stringRepresentation) {
410             if (stringRepresentation == null)
411                 return ImmutableSet.of();
412             Iterable<String> strings = SPLITTER.split(stringRepresentation);
413             return ImmutableSet.copyOf(strings);
414         }
415     };
416
417     public static class EnumCodecStringImpl extends TypeDefinitionAwareCodec<String, EnumTypeDefinition> implements
418             EnumCodec<String> {
419
420         protected EnumCodecStringImpl(Optional<EnumTypeDefinition> typeDef) {
421             super(typeDef, String.class);
422         }
423
424         @Override
425         public String deserialize(String stringRepresentation) {
426             return stringRepresentation;
427         }
428
429         @Override
430         public String serialize(String data) {
431             return data.toString();
432         }
433     };
434
435     public static class DecimalCodecStringImpl extends TypeDefinitionAwareCodec<BigDecimal, DecimalTypeDefinition>
436             implements DecimalCodec<String> {
437
438         protected DecimalCodecStringImpl(Optional<DecimalTypeDefinition> typeDef) {
439             super(typeDef, BigDecimal.class);
440         }
441
442         @Override
443         public String serialize(BigDecimal data) {
444             return data.toString();
445         }
446
447         @Override
448         public BigDecimal deserialize(String stringRepresentation) {
449             return new BigDecimal(stringRepresentation);
450         }
451     };
452
453     public static class UnionCodecStringImpl extends TypeDefinitionAwareCodec<String, UnionTypeDefinition> implements
454             UnionCodec<String> {
455
456         protected UnionCodecStringImpl(Optional<UnionTypeDefinition> typeDef) {
457             super(typeDef, String.class);
458         }
459
460         @Override
461         public String serialize(String data) {
462             return data;
463         }
464
465         @Override
466         public String deserialize(String stringRepresentation) {
467             return stringRepresentation;
468         }
469     };
470 }