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 
23 
24 package org.openoffice.xmerge.converter.xml.sxc.minicalc;
25 
26 /**
27  *  This class is used by <code>MinicalcDecoder</code> to manipulate a
28  *  <code>String</code> containing MiniCalc cell data.
29  *
30  *  @author   Paul Rank
31  */
32 public class MinicalcDataString {
33 
34     /** The String representation of the MiniCalc data. */
35     private String data = null;
36 
37 
38     /**
39      * Constructor stores the MiniCalc data <code>String</code>.
40      *
41      *  @param  data  A <code>String</code> containing MiniCalc
42      *                cell data.
43      */
MinicalcDataString(String data)44     public MinicalcDataString(String data) {
45         this.data = data;
46     }
47 
48 
49     /**
50      *  Checks if the MiniCalc data <code>String</code> is a <i>formula</i>.
51      *
52      *  @return  true if the MiniCalc data <code>String</code> is a
53      *           <i>formula</i>, false if the MiniCalc data <code>String</code>
54      *           is not a <i>formula</i>.
55      */
isFormula()56     public boolean isFormula() {
57 
58         if (data.startsWith("=")) {
59             return true;
60         }
61 
62         return false;
63     }
64 
65 
66     /**
67      *  Checks if the MiniCalc data <code>String</code> is a <i>percentage</i>.
68      *
69      *  @return  true if the MiniCalc data <code>String</code> is a
70      *           <i>percentage</i>, false if the MiniCalc data
71      *           <code>String</code> is not a <i>percentage</i>.
72      */
isPercent()73     public boolean isPercent() {
74 
75         if (data.endsWith("%")) {
76             return true;
77         }
78 
79         return false;
80     }
81 
82 
83     /**
84      *  Checks if the MiniCalc data <code>String</code> is a
85      *  <i>boolean</i> value.
86      *
87      *  @return  true if the MiniCalc data <code>String</code> is
88      *           a <i>boolean</i>, false if the MiniCalc data
89      *           <code>String</code> is not a <i>boolean</i>.
90      */
isBoolean()91     public boolean isBoolean() {
92 
93         if (data.equalsIgnoreCase("false") ||
94             data.equalsIgnoreCase("true")) {
95             return true;
96         }
97 
98         return false;
99     }
100 
101 
102     /**
103      *  Checks if the MiniCalc data <code>String</code> is a <i>date</i>.
104      *
105      *  @return  true if the MiniCalc data <code>String</code> is
106      *           a <i>date</i>, false if the MiniCalc data <code>String</code>
107      *           is not a <i>date</i>.
108      */
isDate()109     public boolean isDate() {
110 
111         // Starting index into the date string - month
112         int start = 0;
113 
114         // Search for "/", which separates month from day
115         int end = data.indexOf("/");
116 
117         // Separator was found
118         if (end > 0) {
119 
120             String monthString = data.substring(start, end);
121 
122             try {
123                 Float f = Float.valueOf(monthString);
124                 if ((f.intValue() < 0) || (f.intValue() > 12)) {
125                     return false;
126                 }
127             }
128             catch (NumberFormatException e) {
129 
130                 // no, it is not a currency type
131                 return false;
132             }
133 
134             // start is now the starting index of day
135             start = end+1;
136 
137             // Search for "/", which separates day from year
138             end = data.indexOf("/", start);
139 
140             // Separator was found
141             if (end > 0) {
142 
143                 String dayString = data.substring(start, end);
144 
145                 try {
146                     Float f = Float.valueOf(dayString);
147                     if ((f.intValue() < 0) || (f.intValue() > 31))
148                         return false;
149                 }
150                 catch (NumberFormatException e) {
151                     // no, it is not a currency type
152                     return false;
153                 }
154             } else {
155                 return false;
156             }
157 
158             // start is now at the starting index of the year
159             start = end + 1;
160 
161             String yearString = data.substring(start);
162             try {
163                 Float f = Float.valueOf(yearString);
164                 if (f.intValue() < 0) {
165                     return false;
166                 }
167             }
168             catch (NumberFormatException e) {
169                 // no, it is not a currency type
170                 return false;
171             }
172 
173         } else {
174             return false;
175         }
176 
177         return true;
178     }
179 
180 
181     /**
182      *  Checks if the MiniCalc data <code>String</code> is a <i>time</i>.
183      *
184      *  @return  true if the MiniCalc data <code>String</code>
185      *           is a <i>time</i>, false if the MiniCalc data
186      *           <code>String</code> is not a <i>time</i>.
187      */
isTime()188     public boolean isTime() {
189 
190         // Starting index into the time string - hour
191         int start = 0;
192 
193         // Search for ":", which separates hour from minute
194         int end = data.indexOf(":");
195 
196 
197         // Separator was found
198         if (end > 0) {
199 
200             String hourString = data.substring(start, end);
201             try {
202                 Float f = Float.valueOf(hourString);
203                 if ((f.intValue() < 0) || (f.intValue() > 24))
204                     return false;
205             }
206             catch (NumberFormatException e) {
207                 // no, it is not a time type
208                 return false;
209             }
210 
211             // start is now the starting index of minute
212             start = end+1;
213 
214             // Search for ":", which separates minute from second
215             end = data.indexOf(":", start);
216 
217             // Separator was found
218             if (end > 0) {
219 
220                 String minuteString = data.substring(start, end);
221 
222                 try {
223                     Float f = Float.valueOf(minuteString);
224                     if ((f.intValue() < 0) || (f.intValue() > 60))
225                         return false;
226                 }
227                 catch (NumberFormatException e) {
228                     // no, it is not a time type
229                     return false;
230                 }
231 
232                 // start is now at the starting index of the seconds
233                 start = end+1;
234 
235                 // The seconds are in the string
236                 if (data.length() > start) {
237 
238                     String secondString = data.substring(start);
239 
240 
241                     try {
242                         Float f = Float.valueOf(secondString);
243                         if ((f.intValue() < 0) || (f.intValue() > 60))
244                             return false;
245                     }
246                     catch (NumberFormatException e) {
247                         // no, it is not a time type
248                         return false;
249                     }
250                 }
251 
252             }
253 
254             return true;
255 
256         }
257 
258         return false;
259     }
260 
261 
262     /**
263      *  Checks if the MiniCalc data <code>String</code> is a <i>currency</i>
264      *  value.
265      *
266      *  @return  true if the MiniCalc data <code>String</code> is
267      *           a <i>currency</i>, false if the MiniCalc data
268      *           <code>String</code> is not a <i>currency</i>.
269      */
isCurrency()270     public boolean isCurrency() {
271 
272         boolean result = false;
273 
274         // TODO - we currently only check for US currencies
275 
276         if (data.endsWith("$")) {
277             String number = data.substring(0, data.length()-1);
278             try {
279                 Float f = Float.valueOf(number);
280                 result = true;
281             }
282             catch (NumberFormatException e) {
283                 // no, it is not a currency type
284                 result = false;
285             }
286         }
287 
288         else if (data.startsWith("$")) {
289             String number = data.substring(1, data.length());
290             try {
291                 Float f = Float.valueOf(number);
292                 result = true;
293             }
294             catch (NumberFormatException e) {
295                 // no, it is not a currency type
296                 result = false;
297             }
298         }
299 
300         return result;
301 
302     }
303 
304 
305     /**
306      *  This method removes the percent sign from the MiniCalc data
307      *  <code>String</code>.  If the percent sign is not the last
308      *  character of the MiniCalc data <code>String</code>, the
309      *  MiniCalc data <code>String</code> is returned.
310      *
311      *  @return  The MiniCalc data <code>String</code> minus the
312      *           percent sign.  If the MiniCalc data <code>String</code>
313      *           does not begin with a percent sign, the MiniCalc data
314      *           <code>String</code> is returned.
315      */
percentRemoveSign()316     public String percentRemoveSign() {
317 
318         String number = data;
319 
320         if (data.endsWith("%")) {
321             // "%" is the last character, so remove
322             number = data.substring(0, data.length()-1);
323 
324             try {
325                 Float f = Float.valueOf(number);
326                 float f1 = f.floatValue()/100f;
327                 Float f2 = new Float(f1);
328                 number =  f2.toString();
329             }
330             catch (NumberFormatException e) {
331                 // no, it is not a float type
332             }
333         }
334 
335         return number;
336     }
337 
338 
339     /**
340      *  This method removes the currency sign from the MiniCalc data
341      *  <code>String</code>.  If the currency sign is not the first or
342      *  last character of the MiniCalc data <code>String</code>, the
343      *  MiniCalc data <code>String</code> is returned.
344      *
345      *  @return  The MiniCalc data <code>String</code> minus the currency
346      *           sign.  If the MiniCalc data <code>String</code> does not
347      *           begin or end with a currency sign, the MiniCalc
348      *           data <code>String</code> is returned.
349      */
currencyRemoveSign()350     public String currencyRemoveSign() {
351 
352         String number = data;
353 
354         // TODO - only works with US currencies
355 
356         if (data.endsWith("$")) {
357 
358             number = data.substring(0, data.length()-1);
359 
360         } else if (data.startsWith("$")) {
361 
362             number = data.substring(1, data.length());
363         }
364 
365         return number;
366 
367     }
368 
369 
370     /**
371      *  <p>This method converts a MiniCalc date from MiniCalc
372      *  format to StarOffice XML format.</p>
373      *
374      *  <p>MiniCalc format:</p>
375      *
376      *  <p><blockquote>
377      *  MM/DD/YY or MM/DD/YYYY
378      *  </blockquote></p>
379      *
380      *  <p>StarOffice XML format:</p>
381      *
382      *  <p><blockquote>
383      *  YYYY-MM-DD
384      *  </blockquote></p>
385      *
386      *  @return  The MiniCalc date converted to StarOffice XML
387      *           format.
388      */
convertToStarDate()389     public String convertToStarDate() {
390 
391         // The output date string
392         String out;
393 
394         String monthString = "01";
395         String dayString = "01";
396         String yearString = "1900";
397 
398         // Starting index into the date string - month
399         int start = 0;
400 
401         // Search for "/", which separates month from day
402         int end = data.indexOf("/");
403 
404         // Separator was found
405         if (end > 0) {
406 
407             monthString = data.substring(start, end);
408 
409             Integer monthInt = new Integer(monthString);
410 
411             // Make sure month is 2 digits
412             if (monthInt.intValue() < 10) {
413                 monthString = "0" + monthString;
414             }
415 
416             // start is now the starting index of day
417             start = end+1;
418 
419             // Search for "/", which separates day from year
420             end = data.indexOf("/", start);
421 
422             // Separator was found
423             if (end > 0) {
424 
425                 dayString = data.substring(start, end);
426 
427                 Integer dayInt = new Integer(dayString);
428 
429                 // Make sure day is 2 digits
430                 if (dayInt.intValue() < 10) {
431                     dayString = "0" + dayString;
432                 }
433 
434                 // start is now at the starting index of the year
435                 start = end + 1;
436 
437                 // The year is in the string
438                 if (data.length() > start) {
439 
440                     yearString = data.substring(start);
441 
442                     Integer yearInt = new Integer(yearString);
443                     int year = yearInt.intValue();
444 
445                     if (year < 31) {
446 
447                         // MiniCalc years between 0 and 30 correspond to
448                         // 2000 - 2030
449                         year += 2000;
450 
451                     } else if (year < 100) {
452 
453                         // MiniCalc years between 31 and 99 correspond
454                         // to 1931 - 1999
455                         year += 1900;
456                     }
457 
458                     yearString = Integer.toString(year);
459                 }
460             }
461         }
462 
463         // Set out to StarOffice XML date format
464         out = yearString + "-" + monthString + "-" + dayString;
465 
466         return out;
467     }
468 
469 
470     /**
471      *  This method converts the MiniCalc time from MiniCalc
472      *  format to StarOffice XML format.
473      *
474      *  <p>MiniCalc format:</p>
475      *
476      *  <p><blockquote>
477      *  hh:mm:ss
478      *  </blockquote></p>
479      *
480      *  <p>StarOffice XML format:</p>
481      *
482      *  <p><blockquote>
483      *  PThhHmmMssS
484      *  </blockquote></p>
485      *
486      *  @return   The MiniCalc time converted to StarOffice XML
487      *            format.
488      */
convertToStarTime()489     public String convertToStarTime() {
490 
491         // The output time string
492         String out;
493 
494         String hourString = "00";
495         String minuteString = "00";
496         String secondString = "00";
497 
498         // Starting index into the time string - hour
499         int start = 0;
500 
501         // Search for ":", which separates hour from minute
502         int end = data.indexOf(":");
503 
504         // Separator was found
505         if (end > 0) {
506 
507             hourString = data.substring(start, end);
508 
509             // start is now the starting index of minute
510             start = end+1;
511 
512             // Search for ":", which separates minute from second
513             end = data.indexOf(":", start);
514 
515             // Separator was found
516             if (end > 0) {
517 
518                 minuteString = data.substring(start, end);
519 
520                 // start is now at the starting index of the seconds
521                 start = end+1;
522 
523                 // The seconds are in the string
524                 if (data.length() > start) {
525 
526                     secondString = data.substring(start);
527                 }
528 
529             }
530         }
531 
532         // TODO -  PT is for pacific time, where can we get the
533         // localized value from?
534 
535         // Set to StarOffice XML time format
536         out = "PT"+hourString+"H"+minuteString+"M"+secondString+"S";
537 
538         return out;
539     }
540 }
541 
542