001/* 002 * Copyright (c) 2005 Einar Pehrson <einar@pehrson.nu>. 003 * 004 * This file is part of 005 * CleanSheets - a spreadsheet application for the Java platform. 006 * 007 * CleanSheets is free software; you can redistribute it and/or modify 008 * it under the terms of the GNU General Public License as published by 009 * the Free Software Foundation; either version 2 of the License, or 010 * (at your option) any later version. 011 * 012 * CleanSheets is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 015 * GNU General Public License for more details. 016 * 017 * You should have received a copy of the GNU General Public License 018 * along with CleanSheets; if not, write to the Free Software 019 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 020 */ 021package csheets.core.formula.compiler; 022 023import java.io.IOException; 024import java.io.InputStream; 025import java.util.ArrayList; 026import java.util.List; 027import java.util.Properties; 028 029import csheets.CleanSheets; 030import csheets.core.Cell; 031import csheets.core.formula.Expression; 032import csheets.core.formula.Formula; 033 034/** 035 * A compiler that generates formulas from strings. 036 * @author Einar Pehrson 037 */ 038public class FormulaCompiler { 039 040 /** The singleton instance */ 041 private static final FormulaCompiler instance = new FormulaCompiler(); 042 043 /** The name of the file in which compiler properties are stored */ 044 private static final String PROPERTIES_FILENAME = "res/compilers.props"; 045 046 /** The expression compilers used to compile formulas */ 047 private List<ExpressionCompiler> compilers = new ArrayList<ExpressionCompiler>(); 048 049 /** 050 * Creates the formula compiler. 051 */ 052 private FormulaCompiler() { 053 // Loads properties 054 Properties compilerProps = new Properties(); 055 InputStream stream = CleanSheets.class.getResourceAsStream(PROPERTIES_FILENAME); 056 if (stream != null) { 057 try { 058 compilerProps.load(stream); 059 } catch (IOException e) { 060 System.err.println("An I/O error occurred when loading compiler" 061 + " properties file (" + PROPERTIES_FILENAME + ")."); 062 return; 063 } finally { 064 try { 065 if (stream != null) 066 stream.close(); 067 } catch (IOException e) {} 068 } 069 070 // Loads elements 071 for (Object className : compilerProps.keySet()) { 072 // Loads class and instantiates element 073 Class elementClass; 074 Object element; 075 try { 076 elementClass = Class.forName(getClass().getPackage() 077 .getName() + "." + (String)className); 078 element = elementClass.newInstance(); 079 } catch (Exception e) { 080 // Skip this element, regardless of what went wrong 081 e.printStackTrace(); 082 continue; 083 } 084 085 // Stores element 086 if (ExpressionCompiler.class.isAssignableFrom(elementClass)) 087 compilers.add(ExpressionCompiler.class.cast(element)); 088 } 089 } else 090 System.err.println("Could not find compiler properties file (" 091 + PROPERTIES_FILENAME + ")."); 092 } 093 094 /** 095 * Returns the singleton instance. 096 * @return the singleton instance 097 */ 098 public static FormulaCompiler getInstance() { 099 return instance; 100 } 101 102 /** 103 * Compiles a formula for the given cell from the given string. 104 * @param cell the cell for which a formula is to be generated 105 * @param source a string representing the formula to be compiled 106 * @return a list of lexical tokens 107 * @throws FormulaCompilationException if the formula could not be compiled 108 */ 109 public Formula compile(Cell cell, String source) throws FormulaCompilationException { 110 for (ExpressionCompiler compiler : compilers) 111 if (source.charAt(0) == compiler.getStarter()) { 112 Expression expression = compiler.compile(cell, source); 113 return new Formula(cell, expression); 114 } 115 return null; 116 } 117}