1    /* ====================================================================
2     * The Apache Software License, Version 1.1
3     *
4     * Copyright (c) 2002 The Apache Software Foundation.  All rights
5     * reserved.
6     *
7     * Redistribution and use in source and binary forms, with or without
8     * modification, are permitted provided that the following conditions
9     * are met:
10    *
11    * 1. Redistributions of source code must retain the above copyright
12    *    notice, this list of conditions and the following disclaimer.
13    *
14    * 2. Redistributions in binary form must reproduce the above copyright
15    *    notice, this list of conditions and the following disclaimer in
16    *    the documentation and/or other materials provided with the
17    *    distribution.
18    *
19    * 3. The end-user documentation included with the redistribution,
20    *    if any, must include the following acknowledgment:
21    *       "This product includes software developed by the
22    *        Apache Software Foundation (http://www.apache.org/)."
23    *    Alternately, this acknowledgment may appear in the software itself,
24    *    if and wherever such third-party acknowledgments normally appear.
25    *
26    * 4. The names "Apache" and "Apache Software Foundation" and
27    *    "Apache POI" must not be used to endorse or promote products
28    *    derived from this software without prior written permission. For
29    *    written permission, please contact apache@apache.org.
30    *
31    * 5. Products derived from this software may not be called "Apache",
32    *    "Apache POI", nor may "Apache" appear in their name, without
33    *    prior written permission of the Apache Software Foundation.
34    *
35    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36    * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37    * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38    * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39    * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40    * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41    * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42    * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43    * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44    * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45    * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46    * SUCH DAMAGE.
47    * ====================================================================
48    *
49    * This software consists of voluntary contributions made by many
50    * individuals on behalf of the Apache Software Foundation.  For more
51    * information on the Apache Software Foundation, please see
52    * <http://www.apache.org/>.
53    */
54   
55   /*
56    * HSSFDataFormat.java
57    *
58    * Created on December 18, 2001, 12:42 PM
59    */
60   package org.apache.poi.hssf.usermodel;
61   
62   import java.util.Vector;
63   import java.util.List;
64   import java.util.ListIterator;
65   import java.util.Iterator;
66   
67   import org.apache.poi.hssf.model.Workbook;
68   import org.apache.poi.hssf.record.Record;
69   import org.apache.poi.hssf.record.FormatRecord;
70   
71   /**
72    * Utility to identify builin formats.  Now can handle user defined data formats also.  The following is a list of the formats as
73    * returned by this class.<P>
74    *<P>
75    *       0, "General"<P>
76    *       1, "0"<P>
77    *       2, "0.00"<P>
78    *       3, "#,##0"<P>
79    *       4, "#,##0.00"<P>
80    *       5, "($#,##0_);($#,##0)"<P>
81    *       6, "($#,##0_);[Red]($#,##0)"<P>
82    *       7, "($#,##0.00);($#,##0.00)"<P>
83    *       8, "($#,##0.00_);[Red]($#,##0.00)"<P>
84    *       9, "0%"<P>
85    *       0xa, "0.00%"<P>
86    *       0xb, "0.00E+00"<P>
87    *       0xc, "# ?/?"<P>
88    *       0xd, "# ??/??"<P>
89    *       0xe, "m/d/yy"<P>
90    *       0xf, "d-mmm-yy"<P>
91    *       0x10, "d-mmm"<P>
92    *       0x11, "mmm-yy"<P>
93    *       0x12, "h:mm AM/PM"<P>
94    *       0x13, "h:mm:ss AM/PM"<P>
95    *       0x14, "h:mm"<P>
96    *       0x15, "h:mm:ss"<P>
97    *       0x16, "m/d/yy h:mm"<P>
98    *<P>
99    *       // 0x17 - 0x24 reserved for international and undocumented
100   *       0x25, "(#,##0_);(#,##0)"<P>
101   *       0x26, "(#,##0_);[Red](#,##0)"<P>
102   *       0x27, "(#,##0.00_);(#,##0.00)"<P>
103   *       0x28, "(#,##0.00_);[Red](#,##0.00)"<P>
104   *       0x29, "_(*#,##0_);_(*(#,##0);_(* \"-\"_);_(@_)"<P>
105   *       0x2a, "_($*#,##0_);_($*(#,##0);_($* \"-\"_);_(@_)"<P>
106   *       0x2b, "_(*#,##0.00_);_(*(#,##0.00);_(*\"-\"??_);_(@_)"<P>
107   *       0x2c, "_($*#,##0.00_);_($*(#,##0.00);_($*\"-\"??_);_(@_)"<P>
108   *       0x2d, "mm:ss"<P>
109   *       0x2e, "[h]:mm:ss"<P>
110   *       0x2f, "mm:ss.0"<P>
111   *       0x30, "##0.0E+0"<P>
112   *       0x31, "@"<P>
113   *
114   *
115   * @author  Andrew C. Oliver (acoliver at apache dot org)
116   */
117  
118  public class HSSFDataFormat
119  {
120      private static Vector builtinFormats;
121  
122      private Vector formats = new Vector();
123      private Workbook workbook;
124      private boolean movedBuiltins = false;  // Flag to see if need to
125  					    // check the built in list
126  					    // or if the regular list
127  					    // has all entries.
128  
129      /** 
130       * Construncts a new data formatter.  It takes a workbook to have
131       * access to the workbooks format records.
132       * @param workbook the workbook the formats are tied to.
133       */
134      public HSSFDataFormat(Workbook workbook) {
135  	this.workbook = workbook;
136  	if (builtinFormats == null) populateBuiltinFormats();
137  	Iterator i = workbook.getFormats().iterator();
138   	while (i.hasNext()) {
139   	    FormatRecord r = (FormatRecord)i.next();
140   	    if (formats.size() < r.getIndexCode() + 1) {
141   		formats.setSize(r.getIndexCode() + 1);
142   	    }
143   	    formats.set(r.getIndexCode(), r.getFormatString());
144   	}
145  
146      }
147  
148      private static synchronized void populateBuiltinFormats()
149      {
150          builtinFormats = new Vector();
151          builtinFormats.add(0, "General");
152          builtinFormats.add(1, "0");
153          builtinFormats.add(2, "0.00");
154          builtinFormats.add(3, "#,##0");
155          builtinFormats.add(4, "#,##0.00");
156          builtinFormats.add(5, "($#,##0_);($#,##0)");
157          builtinFormats.add(6, "($#,##0_);[Red]($#,##0)");
158          builtinFormats.add(7, "($#,##0.00);($#,##0.00)");
159          builtinFormats.add(8, "($#,##0.00_);[Red]($#,##0.00)");
160          builtinFormats.add(9, "0%");
161          builtinFormats.add(0xa, "0.00%");
162          builtinFormats.add(0xb, "0.00E+00");
163          builtinFormats.add(0xc, "# ?/?");
164          builtinFormats.add(0xd, "# ??/??");
165          builtinFormats.add(0xe, "m/d/yy");
166          builtinFormats.add(0xf, "d-mmm-yy");
167          builtinFormats.add(0x10, "d-mmm");
168          builtinFormats.add(0x11, "mmm-yy");
169          builtinFormats.add(0x12, "h:mm AM/PM");
170          builtinFormats.add(0x13, "h:mm:ss AM/PM");
171          builtinFormats.add(0x14, "h:mm");
172          builtinFormats.add(0x15, "h:mm:ss");
173          builtinFormats.add(0x16, "m/d/yy h:mm");
174  
175          // 0x17 - 0x24 reserved for international and undocumented
176          builtinFormats.add(0x17, "0x17");
177          builtinFormats.add(0x18, "0x18");
178          builtinFormats.add(0x19, "0x19");
179          builtinFormats.add(0x1a, "0x1a");
180          builtinFormats.add(0x1b, "0x1b");
181          builtinFormats.add(0x1c, "0x1c");
182          builtinFormats.add(0x1d, "0x1d");
183          builtinFormats.add(0x1e, "0x1e");
184          builtinFormats.add(0x1f, "0x1f");
185          builtinFormats.add(0x20, "0x20");
186          builtinFormats.add(0x21, "0x21");
187          builtinFormats.add(0x22, "0x22");
188          builtinFormats.add(0x23, "0x23");
189          builtinFormats.add(0x24, "0x24");
190  
191          // 0x17 - 0x24 reserved for international and undocumented
192          builtinFormats.add(0x25, "(#,##0_);(#,##0)");
193          builtinFormats.add(0x26, "(#,##0_);[Red](#,##0)");
194          builtinFormats.add(0x27, "(#,##0.00_);(#,##0.00)");
195          builtinFormats.add(0x28, "(#,##0.00_);[Red](#,##0.00)");
196          builtinFormats.add(0x29, "_(*#,##0_);_(*(#,##0);_(* \"-\"_);_(@_)");
197          builtinFormats.add(0x2a, "_($*#,##0_);_($*(#,##0);_($* \"-\"_);_(@_)");
198          builtinFormats.add(0x2b, "_(*#,##0.00_);_(*(#,##0.00);_(*\"-\"??_);_(@_)");
199          builtinFormats.add(0x2c,
200                      "_($*#,##0.00_);_($*(#,##0.00);_($*\"-\"??_);_(@_)");
201          builtinFormats.add(0x2d, "mm:ss");
202          builtinFormats.add(0x2e, "[h]:mm:ss");
203          builtinFormats.add(0x2f, "mm:ss.0");
204          builtinFormats.add(0x30, "##0.0E+0");
205          builtinFormats.add(0x31, "@");
206      }
207  
208      public static List getBuiltinFormats()
209      {
210          if (builtinFormats == null)
211          {
212              populateBuiltinFormats();
213          }
214          return builtinFormats;
215      }
216  
217      /**
218       * get the format index that matches the given format string
219       * @param format string matching a built in format
220       * @return index of format or -1 if undefined.
221       */
222  
223      public static short getBuiltinFormat(String format)
224      {
225          if (builtinFormats == null)
226          {
227              populateBuiltinFormats();
228          }
229          short retval = -1;
230  
231          for (short k = 0; k < 0x31; k++)
232          {
233              String nformat = ( String ) builtinFormats.get(k);
234  
235              if ((nformat != null) && nformat.equals(format))
236              {
237                  retval = k;
238                  break;
239              }
240          }
241          return retval;
242      }
243  
244      /**
245       * get the format index that matches the given format string.
246       * Creates a new format if one is not found.
247       * @param format string matching a built in format
248       * @return index of format.
249       */
250  
251      public short getFormat(String format)
252      {
253  	ListIterator i;
254  	int ind;
255  	if (!movedBuiltins) {
256  	    i = builtinFormats.listIterator();
257  	    while (i.hasNext()) {
258  		ind = i.nextIndex();
259  		formats.add(ind, i.next());
260  	    }
261  	    movedBuiltins = true;
262  	}
263  	i = formats.listIterator();
264  	while (i.hasNext()) {
265  	    ind = i.nextIndex();
266  	    if (format.equals(i.next())) 
267  		return (short)ind;
268  	}
269  	
270  	ind = workbook.getFormat(format, true);
271  	if (formats.size() <= ind) 
272  	    formats.setSize(ind + 1);
273  	formats.add(ind, format);
274  
275          return (short)ind;
276      }
277  
278      /**
279       * get the format string that matches the given format index
280       * @param index of a format
281       * @return string represented at index of format or null if there is not a  format at that index
282       */
283  
284      public String getFormat(short index)
285      {
286  	if (movedBuiltins)
287  	    return ( String ) formats.get(index);
288  	else
289             return (String) (builtinFormats.size() > index && builtinFormats.get(index) != null ? builtinFormats.get(index) : formats.get(index));
290      }
291  
292      /**
293       * get the format string that matches the given format index
294       * @param index of a built in format
295       * @return string represented at index of format or null if there is not a builtin format at that index
296       */
297  
298      public static String getBuiltinFormat(short index)
299      {
300          if (builtinFormats == null)
301          {
302              populateBuiltinFormats();
303          }
304          return ( String ) builtinFormats.get(index);
305      }
306  
307      /**
308       * get the number of builtin and reserved builtinFormats
309       * @return number of builtin and reserved builtinFormats
310       */
311  
312      public static int getNumberOfBuiltinBuiltinFormats()
313      {
314          if (builtinFormats == null)
315          {
316              populateBuiltinFormats();
317          }
318          return builtinFormats.size();
319      }
320  }
321