1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements.  See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership.  The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License.  You may obtain a copy of the License at
10 *
11 *   http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied.  See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21 
22 package org.apache.openoffice.ooxml.parser.type;
23 
24 import java.util.HashSet;
25 import java.util.Set;
26 
27 import org.apache.openoffice.ooxml.parser.NameMap;
28 
29 public class NumberParser implements ISimpleTypeParser
30 {
NumberParser(final String[] aLine)31     public NumberParser (final String[] aLine)
32     {
33         switch(aLine[5])
34         {
35             case "u1":
36                 meNumberType = NumberType.Boolean;
37                 meJavaNumberType = JavaNumberType.Boolean;
38                 break;
39             case "s8":
40                 meNumberType = NumberType.Byte;
41                 meJavaNumberType = JavaNumberType.Byte;
42                 break;
43             case "u8":
44                 meNumberType = NumberType.UnsignedByte;
45                 meJavaNumberType = JavaNumberType.Short;
46                 break;
47             case "s16":
48                 meNumberType = NumberType.Short;
49                 meJavaNumberType = JavaNumberType.Short;
50                 break;
51             case "u16":
52                 meNumberType = NumberType.UnsignedShort;
53                 meJavaNumberType = JavaNumberType.Integer;
54                 break;
55             case "s32":
56                 meNumberType = NumberType.Int;
57                 meJavaNumberType = JavaNumberType.Integer;
58                 break;
59             case "u32":
60                 meNumberType = NumberType.UnsignedInt;
61                 meJavaNumberType = JavaNumberType.Long;
62                 break;
63             case "s64":
64                 meNumberType = NumberType.Long;
65                 meJavaNumberType = JavaNumberType.Long;
66                 break;
67             case "u64":
68                 meNumberType = NumberType.UnsignedLong;
69                 meJavaNumberType = JavaNumberType.Long;
70                 break;
71             case "s*":
72                 meNumberType = NumberType.Integer;
73                 meJavaNumberType = JavaNumberType.Long;
74                 break;
75             case "f":
76                 meNumberType = NumberType.Float;
77                 meJavaNumberType = JavaNumberType.Float;
78                 break;
79             case "d":
80                 meNumberType = NumberType.Double;
81                 meJavaNumberType = JavaNumberType.Double;
82                 break;
83             default:
84                 throw new RuntimeException("unsupported numerical type "+aLine[5]);
85         }
86 
87         switch(aLine[6])
88         {
89             case "E":
90                 meRestrictionType = RestrictionType.Enumeration;
91                 maEnumeration = new HashSet<>();
92                 for (int nIndex=7; nIndex<aLine.length; ++nIndex)
93                     maEnumeration.add(ParseNumber(aLine[nIndex]));
94                 break;
95 
96             case "S":
97                 meRestrictionType = RestrictionType.Size;
98                 for (int nIndex=7; nIndex<=9; nIndex+=2)
99                     if (nIndex<aLine.length)
100                         switch (aLine[nIndex])
101                         {
102                             case "<=":
103                                 maMaximumValue = ParseNumber(aLine[nIndex+1]);
104                                 mbIsMaximumInclusive = true;
105                                 break;
106                             case "<":
107                                 maMaximumValue = ParseNumber(aLine[nIndex+1]);
108                                 mbIsMaximumInclusive = false;
109                                 break;
110                             case ">=":
111                                 maMinimumValue = ParseNumber(aLine[nIndex+1]);
112                                 mbIsMinimumInclusive = true;
113                                 break;
114                             case ">":
115                                 maMinimumValue = ParseNumber(aLine[nIndex+1]);
116                                 mbIsMinimumInclusive = false;
117                                 break;
118                         }
119                 break;
120 
121             case "N":
122                 meRestrictionType = RestrictionType.None;
123                 break;
124 
125             default:
126                 throw new RuntimeException("unsupported numerical restriction "+aLine[6]);
127         }
128     }
129 
130 
131 
132 
133     @Override
Parse( final String sRawValue, final NameMap aAttributeValueMap)134     public Object Parse(
135         final String sRawValue,
136         final NameMap aAttributeValueMap)
137     {
138         final Object aNumber = ParseNumber(sRawValue);
139         switch(meRestrictionType)
140         {
141             case Enumeration:
142                 if (maEnumeration.contains(aNumber))
143                     return aNumber;
144                 else
145                     return null;
146 
147             case Size:
148                 if (maMinimumValue != null)
149                     if (mbIsMinimumInclusive)
150                     {
151                         if (CompareTo(aNumber, maMinimumValue, meJavaNumberType) < 0)
152                             return null;
153                     }
154                     else
155                     {
156                         if (CompareTo(aNumber, maMinimumValue, meJavaNumberType) <= 0)
157                             return null;
158                     }
159                 if (maMaximumValue != null)
160                     if (mbIsMaximumInclusive)
161                     {
162                         if (CompareTo(aNumber, maMaximumValue, meJavaNumberType) > 0)
163                             return null;
164                     }
165                     else
166                     {
167                         if (CompareTo(aNumber, maMaximumValue, meJavaNumberType) >= 0)
168                             return null;
169                     }
170                 return aNumber;
171 
172             case None:
173                 return aNumber;
174 
175             default:
176                 throw new RuntimeException();
177         }
178     }
179 
180 
181 
182 
ParseNumber(final String sNumber)183     Object ParseNumber (final String sNumber)
184     {
185         switch(meJavaNumberType)
186         {
187             case Boolean: return Boolean.parseBoolean(sNumber);
188             case Byte: return Byte.parseByte(sNumber);
189             case Short: return Short.parseShort(sNumber);
190             case Integer: return Integer.parseInt(sNumber);
191             case Long: return Long.parseLong(sNumber);
192             case Float: return Float.parseFloat(sNumber);
193             case Double: return Double.parseDouble(sNumber);
194             default:
195                 throw new RuntimeException();
196         }
197     }
198 
199 
200 
201 
CompareTo( final Object aLeft, final Object aRight, final JavaNumberType eType)202     private static int CompareTo (
203         final Object aLeft,
204         final Object aRight,
205         final JavaNumberType eType)
206     {
207         switch(eType)
208         {
209             case Boolean:
210                 return ((Boolean)aLeft).compareTo((Boolean)aRight);
211             case Byte:
212                 return ((Byte)aLeft).compareTo((Byte)aRight);
213             case Short:
214                 return ((Short)aLeft).compareTo((Short)aRight);
215             case Integer:
216                 return ((Integer)aLeft).compareTo((Integer)aRight);
217             case Long:
218                 return ((Long)aLeft).compareTo((Long)aRight);
219             case Float:
220                 return ((Float)aLeft).compareTo((Float)aRight);
221             case Double:
222                 return ((Double)aLeft).compareTo((Double)aRight);
223             default:
224                 throw new RuntimeException();
225         }
226     }
227 
228 
229 
230 
231     enum NumberType
232     {
233         Boolean,
234         Byte,
235         UnsignedByte,
236         Short,
237         UnsignedShort,
238         Int,
239         UnsignedInt,
240         Long,
241         UnsignedLong,
242         Integer,
243         Float,
244         Double
245     }
246     enum JavaNumberType
247     {
248         Boolean,
249         Byte,
250         Short,
251         Integer,
252         Long,
253         Float,
254         Double
255     }
256     enum RestrictionType
257     {
258         Enumeration,
259         Size,
260         None
261     }
262     private final NumberType meNumberType;
263     private final JavaNumberType meJavaNumberType;
264     private final RestrictionType meRestrictionType;
265     private Set<Object> maEnumeration;
266     private Object maMinimumValue;
267     private boolean mbIsMinimumInclusive;
268     private Object maMaximumValue;
269     private boolean mbIsMaximumInclusive;
270 }
271