a96815fa0b9245d11ca4662690e50c8710b233d5
[yangtools.git] / model / yang-model-ri / src / main / java / org / opendaylight / yangtools / yang / model / ri / type / NumberUtil.java
1 /*
2  * Copyright (c) 2015 Pantheon Technologies s.r.o. 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.model.ri.type;
9
10 import static com.google.common.base.Preconditions.checkArgument;
11
12 import com.google.common.collect.ImmutableMap;
13 import java.util.Comparator;
14 import java.util.function.Function;
15 import org.opendaylight.yangtools.yang.common.Decimal64;
16 import org.opendaylight.yangtools.yang.common.Uint16;
17 import org.opendaylight.yangtools.yang.common.Uint32;
18 import org.opendaylight.yangtools.yang.common.Uint64;
19 import org.opendaylight.yangtools.yang.common.Uint8;
20
21 final class NumberUtil {
22     private static final Comparator<Number> NUMBER_COMPARATOR = (o1, o2) -> {
23         checkArgument(o1.getClass().equals(o2.getClass()), "Incompatible Number classes %s and %s",
24             o1.getClass(), o2.getClass());
25
26         if (o1 instanceof Byte) {
27             return ((Byte)o1).compareTo((Byte) o2);
28         } else if (o1 instanceof Short) {
29             return ((Short)o1).compareTo((Short) o2);
30         } else if (o1 instanceof Integer) {
31             return ((Integer)o1).compareTo((Integer) o2);
32         } else if (o1 instanceof Long) {
33             return ((Long)o1).compareTo((Long) o2);
34         } else if (o1 instanceof Uint8) {
35             return ((Uint8)o1).compareTo((Uint8) o2);
36         } else if (o1 instanceof Uint16) {
37             return ((Uint16)o1).compareTo((Uint16) o2);
38         } else if (o1 instanceof Uint32) {
39             return ((Uint32)o1).compareTo((Uint32) o2);
40         } else if (o1 instanceof Uint64) {
41             return ((Uint64)o1).compareTo((Uint64) o2);
42         } else if (o1 instanceof Decimal64) {
43             return ((Decimal64)o1).compareTo((Decimal64) o2);
44         } else {
45             throw new IllegalArgumentException("Unsupported Number class " + o1.getClass());
46         }
47     };
48
49     private static final ImmutableMap<Class<? extends Number>, Function<Number, Number>> CONVERTERS;
50
51     static {
52         final ImmutableMap.Builder<Class<? extends Number>, Function<Number, Number>> b = ImmutableMap.builder();
53         b.put(Byte.class, input -> {
54             if (input instanceof Byte) {
55                 return input;
56             }
57
58             return Byte.valueOf(input.toString());
59         });
60         b.put(Short.class, input -> {
61             if (input instanceof Short) {
62                 return input;
63             }
64             if (input instanceof Byte) {
65                 return input.shortValue();
66             }
67
68             return Short.valueOf(input.toString());
69         });
70         b.put(Integer.class, input -> {
71             if (input instanceof Integer) {
72                 return input;
73             }
74             if (input instanceof Byte || input instanceof Short) {
75                 return input.intValue();
76             }
77
78             return Integer.valueOf(input.toString());
79         });
80         b.put(Long.class, input ->  {
81             if (input instanceof Long) {
82                 return input;
83             }
84             if (input instanceof Byte || input instanceof Short || input instanceof Integer) {
85                 return input.longValue();
86             }
87
88             return Long.valueOf(input.toString());
89         });
90         b.put(Decimal64.class, input -> {
91             if (input instanceof Decimal64) {
92                 return input;
93             }
94             if (input instanceof Byte || input instanceof Short || input instanceof Integer || input instanceof Long) {
95                 return Decimal64.valueOf(input.longValue());
96             }
97
98             return Decimal64.valueOf(input.toString());
99         });
100         b.put(Uint8.class, input -> {
101             if (input instanceof Uint8) {
102                 return input;
103             }
104             // FIXME: revise this
105             if (input instanceof Byte || input instanceof Short || input instanceof Integer || input instanceof Long
106                     || input instanceof Uint16 || input instanceof Uint32 || input instanceof Uint64) {
107                 return Uint8.valueOf(input.longValue());
108             }
109
110             return Uint8.valueOf(input.toString());
111         });
112         b.put(Uint16.class, input -> {
113             if (input instanceof Uint16) {
114                 return input;
115             }
116             // FIXME: revise this
117             if (input instanceof Byte || input instanceof Short || input instanceof Integer || input instanceof Long
118                     || input instanceof Uint8 || input instanceof Uint32 || input instanceof Uint64) {
119                 return Uint16.valueOf(input.longValue());
120             }
121
122             return Uint16.valueOf(input.toString());
123         });
124         b.put(Uint32.class, input -> {
125             if (input instanceof Uint32) {
126                 return input;
127             }
128             // FIXME: revise this
129             if (input instanceof Byte || input instanceof Short || input instanceof Integer || input instanceof Long
130                     || input instanceof Uint8 || input instanceof Uint16 || input instanceof Uint64) {
131                 return Uint32.valueOf(input.longValue());
132             }
133
134             return Uint32.valueOf(input.toString());
135         });
136         b.put(Uint64.class, input -> {
137             if (input instanceof Uint64) {
138                 return input;
139             }
140             // FIXME: revise this
141             if (input instanceof Byte || input instanceof Short || input instanceof Integer || input instanceof Long
142                     || input instanceof Uint8 || input instanceof Uint16 || input instanceof Uint32) {
143                 return Uint64.valueOf(input.longValue());
144             }
145
146             return Uint64.valueOf(input.toString());
147         });
148         CONVERTERS = b.build();
149     }
150
151     private NumberUtil() {
152         // Hidden on purpose
153     }
154
155     @SuppressWarnings("unchecked")
156     static <T extends Number> Function<Number, T> converterTo(final Class<T> clazz) {
157         return (Function<Number, T>) CONVERTERS.get(clazz);
158     }
159
160     static boolean isRangeCovered(final Number min, final Number max, final Number superMin, final Number superMax) {
161         return NumberUtil.NUMBER_COMPARATOR.compare(min, superMin) >= 0
162             && NumberUtil.NUMBER_COMPARATOR.compare(max, superMax) <= 0;
163     }
164 }