diff options
Diffstat (limited to 'xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/MinicalcEncoder.java')
-rw-r--r-- | xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/MinicalcEncoder.java | 585 |
1 files changed, 585 insertions, 0 deletions
diff --git a/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/MinicalcEncoder.java b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/MinicalcEncoder.java new file mode 100644 index 000000000000..60f68474554d --- /dev/null +++ b/xmerge/java/org/openoffice/xmerge/converter/xml/sxc/minicalc/MinicalcEncoder.java @@ -0,0 +1,585 @@ +/************************************************************************ + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: MinicalcEncoder.java,v $ + * $Revision: 1.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +package org.openoffice.xmerge.converter.xml.sxc.minicalc; + +import jmc.Workbook; +import jmc.Worksheet; +import jmc.CellAttributes; +import jmc.CellDescriptor; +import jmc.JMCconstants; +import jmc.JMCException; + +import java.awt.Color; + +import java.io.ByteArrayOutputStream; +import java.io.ByteArrayInputStream; +import java.io.DataOutputStream; +import java.io.IOException; + +import org.openoffice.xmerge.converter.palm.Record; +import org.openoffice.xmerge.util.Debug; +import org.openoffice.xmerge.util.IntArrayList; + +import org.openoffice.xmerge.converter.xml.sxc.SpreadsheetEncoder; +import org.openoffice.xmerge.converter.xml.sxc.Format; +import org.openoffice.xmerge.converter.xml.OfficeConstants; + +/** + * This class is used by {@link + * org.openoffice.xmerge.converter.xml.sxc.SxcDocumentSerializerImpl + * SxcDocumentSerializerImpl} to encode the MiniCalc format. + * + * @author Paul Rank + */ +final class MinicalcEncoder extends SpreadsheetEncoder { + + /** MiniCalc WorkBook to store sheets. */ + private Workbook wb; + + /** MiniCalc sheet - only one sheet can be open at a time. */ + private Worksheet ws; + + /** + * Estimate of the number of Palm pixels per character. Used for + * estimating the width of a cell on a Palm device. + */ + private final static int pixelsPerChar = 6; + + /** + * The minimum width (in pixels) that we allow a column to be set to + * on a Palm device. + */ + private final static int minWidth = 10; + + /** + * The maximum width (in pixels) that we allow a column to be set to + * on a Palm device. + */ + private final static int maxWidth = 80; + + + /** + * Constructor creates a MiniCalc WorkBook. + * + * @param log Log object for logging. + * @param name The name of the WorkBook. + * @param password The password for the WorkBook. + * + * @throws IOException If any I/O error occurs. + */ + MinicalcEncoder(String name, String password) throws IOException { + + super(name, password); + + try { + wb = new Workbook(name, password); + } + catch (JMCException e) { + Debug.log(Debug.ERROR, "new Workbook threw exception:" + e.getMessage()); + throw new IOException(e.getMessage()); + } + } + + + /** + * This method creates a WorkSheet belonging to the + * WorkBook. + * + * @param sheetName The name of the WorkSheet. + * + * @throws IOException If any I/O error occurs. + */ + public void createWorksheet(String sheetName) throws IOException { + + try { + ws = wb.createWorksheet(sheetName); + } + catch (JMCException e) { + Debug.log(Debug.ERROR, "wb.createWorksheet threw exception:" + e.getMessage()); + throw new IOException(e.getMessage()); + } + } + + + /** + * This method gets the number of sheets in the WorkBook. + * + * @return The number of sheets in the WorkBook. + */ + public int getNumberOfSheets() { + + int numSheets = wb.getNumberOfSheets(); + return numSheets; + } + + + /** + * This method encodes the MiniCalc WorkBook information + * into an palm <code>Record</code> array in MiniCalc + * database format. + * + * @return Array of <code>Record</code> holding MiniCalc + * contents. + * + * @throws IOException If any I/O error occurs. + */ + public Record[] getRecords(int sheetID) throws IOException { + + // Get the WorkSheet for the input sheetID + ws = wb.getWorksheet(sheetID); + + // Need to call ws.initWrite() before we start querying the WorkSheet + try { + ws.initWrite(); + } + catch (JMCException e) { + Debug.log(Debug.ERROR, "ws.initWrite in getRecords:" + e.getMessage()); + throw new IOException(e.getMessage()); + } + + // Get the number of records in the WorkSheet + int numRecords = ws.getNumberOfRecords(); + + // Create the Record array + Record[] allRecords = new Record[numRecords]; + + + // Get each record from the WorkSheet and store in allRecords[] + try { + for (int i = 0; i < allRecords.length; i++) { + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + int length = ws.writeNextRecord(bos); + + byte cBytes[] = bos.toByteArray(); + + allRecords[i] = new Record(cBytes); + } + } + catch (Exception e) { + Debug.log(Debug.ERROR, "ws.writeNextRecord in getRecords:" + e.getMessage()); + throw new IOException(e.getMessage()); + } + + return allRecords; + } + + + /** + * A cell reference in a StarOffice formula looks like + * [.C2] (for cell C2). MiniCalc is expecting cell references + * to look like C2. This method strips out the braces and + * the period. + * + * @param formula A StarOffice formula <code>String</code>. + * + * @return A MiniCalc formula <code>String</code>. + */ + protected String parseFormula(String formula) { + + StringBuffer inFormula = new StringBuffer(formula); + StringBuffer outFormula = new StringBuffer(); + + boolean inBrace = false; + boolean firstCharAfterBrace = false; + boolean firstCharAfterColon = false; + + int len = inFormula.length(); + + for (int in = 0; in < len; in++) { + switch (inFormula.charAt(in)) { + case '[': + // We are now inside a StarOffice cell reference. + // We also need to strip out the '[' + inBrace = true; + + // If the next character is a '.', we want to strip it out + firstCharAfterBrace = true; + break; + + case ']': + // We are exiting a StarOffice cell reference + // We are stripping out the ']' + inBrace = false; + break; + + case ':': + // We have a cell range reference. + // May need to strip out the leading '.' + if (inBrace) + firstCharAfterColon = true; + outFormula.append(inFormula.charAt(in)); + break; + + case '.': + if (inBrace == true) { + if (firstCharAfterBrace == false && + firstCharAfterColon == false) { + // Not the first character after the open brace. + // We have hit a separator between a sheet reference + // and a cell reference. MiniCalc uses a ! as + // this type of separator. + outFormula.append('!'); + } + else { + firstCharAfterBrace = false; + firstCharAfterColon = false; + // Since we are in a StarOffice cell reference, + // and we are the first character, we need to + // strip out the '.' + } + break; + } else { + // We hit valid data, lets add it to the formula string + outFormula.append(inFormula.charAt(in)); + break; + } + + case ';': + // StarOffice XML format uses ';' as a separator. MiniCalc (and + // many spreadsheets) use ',' as a separator instead. + outFormula.append(','); + break; + + default: + // We hit valid data, lets add it to the formula string + outFormula.append(inFormula.charAt(in)); + + // Need to make sure that firstCharAfterBrace is not true. + firstCharAfterBrace = false; + break; + } + } + + return outFormula.toString(); + } + + /** + * Add a cell to the current WorkSheet. + * + * @param row The row number of the cell. + * @param column The column number of the cell. + * @param fmt The <code>Format</code> object describing + * the appearance of this cell. + * @param cellContents The text or formula of the cell's contents. + * + * @throws IOException If any I/O error occurs. + */ + public void addCell(int row, int column, Format fmt, String cellContents) throws IOException { + + CellAttributes ca = new CellAttributes(getFormat(fmt), + fmt.getForeground(), + fmt.getBackground()); + if (cellContents.startsWith("=")) { + cellContents = parseFormula(cellContents); + Debug.log(Debug.INFO, "YAHOO Found Formula" + cellContents); + } + + CellDescriptor cellDes = new CellDescriptor(row, column, ca, cellContents); + + try { + ws.putCell(cellDes); + } + catch (JMCException jmce) { + Debug.log(Debug.ERROR, "ws.putCell threw exception: " + jmce.getMessage()); + throw new IOException(jmce.getMessage()); + } + } + + + /** + * Set the width of the columns in the WorkBook. + * + * @param columnWidths An <code>IntArrayList</code> of column + * widths. + */ + public void setColumnWidths(IntArrayList columnWidths) throws IOException { + // Get the number of columns + int numColumns = columnWidths.size(); + + // Return if there are no columns in the listr + if (numColumns == 0) { + return; + } + + // Need to set the FORM_FLAGS_NONDEFAULT flag for the column widths + // to be used in MiniCalc + long format = JMCconstants.FORM_FLAGS_NONDEFAULT; + + CellAttributes ca = new CellAttributes(format); + + try { + for (int i = 0; i < numColumns; i++) { + // Get the column width in Palm pixels + int width = columnWidths.get(i) * pixelsPerChar; + + // Check limits on column width + if (width < minWidth) { + width = minWidth; + } else if (width > maxWidth) { + width = maxWidth; + } + + // Add the column descriptor to the WorkSheet + ws.putColumn(i + 1, width, ca); + } + } + catch (JMCException jmce) { + Debug.log(Debug.ERROR, "ws.putColumn threw exception: " + jmce.getMessage()); + throw new IOException(jmce.getMessage()); + } + } + + + /** + * This method sets the format of a cell to <i>string</i>. + * + * @param format The cell format-may already contain display info, + * such as alignment or font type. + * + * @return The updated format of the cell. + */ + private long setFormatString(long format) { + + format = clearCellFormatType(format); + + // Set format to generic, since MiniCalc does not have a string type. + format = format | JMCconstants.FF_FORMAT_GENERIC; + + return format; + } + + + /** + * This method sets the format of a cell to <i>floating point</i>. + * + * @param format The cell format. May already contain + * display info, such as alignment or + * font type. + * @param decimalPlaces The number of decimal places to + * set in the floating point number. + * + * @return The updated format of the cell. + */ + private long setFormatFloat(long format, int decimalPlaces) { + + format = clearCellFormatType(format); + + // Set format to floating point with correct number of decimal places + format = format | JMCconstants.FF_FORMAT_DECIMAL | decimalPlaces; + + return format; + } + + + /** + * This method sets the format of a cell to <i>time</i>. + * + * @param format The cell format-may already contain display info, + * such as alignment or font type. + * + * @return The updated format of the cell. + */ + private long setFormatTime(long format) { + + format = clearCellFormatType(format); + + // Set format to time. + format = format | JMCconstants.FF_FORMAT_TIME; + + return format; + } + + + /** + * This method sets the format of a cell to <i>date</i>. + * + * @param format The cell format-may already contain display info, + * such as alignment or font type. + * + * @return The updated format of the cell. + */ + private long setFormatDate(long format) { + + format = clearCellFormatType(format); + + // Set format to date. + format = format | JMCconstants.FF_FORMAT_DATE; + + return format; + } + + + /** + * This method sets the format of a cell to <i>currency</i>. + * + * @param format The cell format-may already contain + * display info, such as alignment or + * font type. + * @param decimalPlaces The number of decimal places to set. + * + * @return The updated format of the cell. + */ + private long setFormatCurrency(long format, int decimalPlaces) { + + format = clearCellFormatType(format); + + // Set format to Currency with correct number of decimal places + format = format | JMCconstants.FF_FORMAT_CURRENCY | decimalPlaces; + + return format; + } + + + /** + * This method sets the format of a cell to <i>boolean</i>. + * + * @param format The cell format-may already contain display info, + * such as alignment or font type. + * + * @return The updated format of the cell. + */ + private long setFormatBoolean(long format) { + + format = clearCellFormatType(format); + + // Set format to generic, since MiniCalc does not have a Boolean type. + format = format | JMCconstants.FF_FORMAT_GENERIC; + + return format; + } + + + /** + * This method sets the format of a cell to <i>percent</i>. + * + * @param format The cell format-may already contain + * display info, such as alignment or + * font type. + * @param decimalPlaces The number of decimal places to set. + * + * @return The updated format of the cell. + */ + private long setFormatPercent(long format, int decimalPlaces) { + + format = clearCellFormatType(format); + + // Set format to Percent with correct number of decimal places + format = format | JMCconstants.FF_FORMAT_PERCENT | decimalPlaces; + + return format; + } + + + /** + * This method clears out the format bits associated with + * the type of data (<i>float</i>, <i>time</i>, etc...) in + * a cell. + * + * @param format The original format for the cell. + * + * @return The updated cell format with the bits associated + * with the type of data (float, time, etc...) + * zeroed out. + */ + private long clearCellFormatType(long format) { + + // First 4 bits are for the number of decimal places + // bits 5-8 are for the data format (float, time, etc...) + + // Clear out first 8 bits + format = format & 0xFFFFFFFFFFFFFF00L; + + return format; + } + + + /** + * Set a cell's formatting options via a separately create + * <code>Format</code> object. + * + * @param row The row number of the cell to be changed. + * @param column The column number of the cell to be changed. + * @param fmt Object containing formatting settings for + * this cell. + */ + public void setCellFormat(int row, int column, Format fmt) { + } + + + /** + * Get the names of the sheets in the WorkBook. + * + * @param sheet The required sheet. + */ + public String getSheetName(int sheet) { + return wb.getWorksheet(sheet).getName(); + } + + + /* + * This method returns a MiniCalc style format from the + * <code>Format</code> object. + */ + private long getFormat(Format fmt) + { + String category = fmt.getCategory(); + + if (category.equalsIgnoreCase(OfficeConstants.CELLTYPE_BOOLEAN)) { + return setFormatBoolean(0); + } + else if (category.equalsIgnoreCase(OfficeConstants.CELLTYPE_CURRENCY)) { + return setFormatCurrency(0, fmt.getDecimalPlaces()); + } + else if (category.equalsIgnoreCase(OfficeConstants.CELLTYPE_DATE)) { + return setFormatDate(0); + } + else if (category.equalsIgnoreCase(OfficeConstants.CELLTYPE_FLOAT)) { + return setFormatFloat(0, fmt.getDecimalPlaces()); + } + else if (category.equalsIgnoreCase(OfficeConstants.CELLTYPE_PERCENT)) { + return setFormatPercent(0, fmt.getDecimalPlaces()); + } + else if (category.equalsIgnoreCase(OfficeConstants.CELLTYPE_STRING)) { + return setFormatString(0); + } + else if (category.equalsIgnoreCase(OfficeConstants.CELLTYPE_TIME)) { + return setFormatTime(0); + } + else { + // Should never get here, but just in case + System.out.println("XXXXX Formatting information not found"); + return 0; + } + } +} + |