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 */
021 package csheets.core.formula.compiler;
022
023 import java.io.IOException;
024 import java.io.InputStream;
025 import java.util.ArrayList;
026 import java.util.List;
027 import java.util.Properties;
028
029 import csheets.CleanSheets;
030 import csheets.core.Cell;
031 import csheets.core.formula.Expression;
032 import csheets.core.formula.Formula;
033
034 /**
035 * A compiler that generates formulas from strings.
036 * @author Einar Pehrson
037 */
038 public 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 }