001 /** 002 * ========================================= 003 * LibFormula : a free Java formula library 004 * ========================================= 005 * 006 * Project Info: http://reporting.pentaho.org/libformula/ 007 * 008 * (C) Copyright 2006-2007, by Pentaho Corporation and Contributors. 009 * 010 * This library is free software; you can redistribute it and/or modify it under the terms 011 * of the GNU Lesser General Public License as published by the Free Software Foundation; 012 * either version 2.1 of the License, or (at your option) any later version. 013 * 014 * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 015 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 016 * See the GNU Lesser General Public License for more details. 017 * 018 * You should have received a copy of the GNU Lesser General Public License along with this 019 * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, 020 * Boston, MA 02111-1307, USA. 021 * 022 * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 023 * in the United States and other countries.] 024 * 025 * 026 * ------------ 027 * $Id: DefaultFunctionRegistry.java 3325 2007-09-12 23:57:55Z tmorgner $ 028 * ------------ 029 * (C) Copyright 2006-2007, by Pentaho Corporation. 030 */ 031 package org.jfree.formula.function; 032 033 import java.util.ArrayList; 034 import java.util.HashMap; 035 import java.util.HashSet; 036 import java.util.Iterator; 037 038 import org.jfree.util.Configuration; 039 import org.jfree.util.HashNMap; 040 import org.jfree.util.Log; 041 import org.jfree.util.ObjectUtilities; 042 043 /** 044 * Creation-Date: 02.11.2006, 12:48:32 045 * 046 * @author Thomas Morgner 047 */ 048 public class DefaultFunctionRegistry implements FunctionRegistry 049 { 050 private static final String FUNCTIONS_PREFIX = "org.jfree.formula.functions."; 051 private static final String[] EMPTY_ARRAY = new String[0]; 052 private static final FunctionCategory[] EMPTY_CATEGORIES = new FunctionCategory[0]; 053 054 private FunctionCategory[] categories; 055 private HashNMap categoryFunctions; 056 private HashMap functions; 057 private HashMap functionMetaData; 058 private HashMap cachedFunctions; 059 060 public DefaultFunctionRegistry() 061 { 062 cachedFunctions = new HashMap(); 063 categoryFunctions = new HashNMap(); 064 functionMetaData = new HashMap(); 065 functions = new HashMap(); 066 categories = EMPTY_CATEGORIES; 067 } 068 069 public FunctionCategory[] getCategories() 070 { 071 return (FunctionCategory[]) categories.clone(); 072 } 073 074 public Function[] getFunctions() 075 { 076 final String[] fnNames = getFunctionNames(); 077 final ArrayList functions = new ArrayList(fnNames.length); 078 for (int i = 0; i < fnNames.length; i++) 079 { 080 final String aName = fnNames[i]; 081 final Function function = createFunction(aName); 082 if (function == null) 083 { 084 Log.debug ("There is no such function: " + aName); 085 } 086 else 087 { 088 functions.add(function); 089 } 090 } 091 return (Function[]) functions.toArray(new Function[functions.size()]); 092 } 093 094 public String[] getFunctionNames() 095 { 096 return (String[]) functions.keySet().toArray(new String[functions.size()]); 097 } 098 099 public String[] getFunctionNamesByCategory(final FunctionCategory category) 100 { 101 return (String[]) categoryFunctions.toArray(category, EMPTY_ARRAY); 102 } 103 104 public Function[] getFunctionsByCategory(final FunctionCategory category) 105 { 106 final String[] fnNames = (String[]) categoryFunctions.toArray(category, EMPTY_ARRAY); 107 final ArrayList functions = new ArrayList(fnNames.length); 108 for (int i = 0; i < fnNames.length; i++) 109 { 110 final String aName = fnNames[i]; 111 final Function function = createFunction(aName); 112 if (function != null) 113 { 114 functions.add(function); 115 } 116 } 117 return (Function[]) functions.toArray(new Function[functions.size()]); 118 } 119 120 public Function createFunction(final String name) 121 { 122 if (name == null) 123 { 124 throw new NullPointerException(); 125 } 126 final String functionClass = (String) functions.get(name.toUpperCase()); 127 final Class cachedClass = (Class) cachedFunctions.get(functionClass); 128 if (cachedClass != null) 129 { 130 try 131 { 132 return (Function) cachedClass.newInstance(); 133 } 134 catch (Exception e) 135 { 136 return null; 137 } 138 } 139 140 final Function function = (Function) ObjectUtilities.loadAndInstantiate 141 (functionClass, DefaultFunctionRegistry.class, Function.class); 142 if (function == null) 143 { 144 Log.debug ("There is no such function: " + name); 145 } 146 else 147 { 148 cachedFunctions.put(functionClass, function.getClass()); 149 } 150 return function; 151 } 152 153 public FunctionDescription getMetaData(final String name) 154 { 155 if (name == null) 156 { 157 throw new NullPointerException(); 158 } 159 return (FunctionDescription) functionMetaData.get(name.toUpperCase()); 160 } 161 162 public void initialize(final Configuration configuration) 163 { 164 final Iterator functionKeys = 165 configuration.findPropertyKeys(FUNCTIONS_PREFIX); 166 final HashSet categories = new HashSet(); 167 168 169 while (functionKeys.hasNext()) 170 { 171 final String classKey = (String) functionKeys.next(); 172 if (classKey.endsWith(".class") == false) 173 { 174 continue; 175 } 176 177 final String className = configuration.getConfigProperty(classKey); 178 if (className.length() == 0) 179 { 180 continue; 181 } 182 final Object fn = ObjectUtilities.loadAndInstantiate 183 (className, DefaultFunctionRegistry.class, Function.class); 184 if (fn instanceof Function == false) 185 { 186 continue; 187 } 188 189 final Function function = (Function) fn; 190 191 final int endIndex = classKey.length() - ".class".length(); 192 final String descrKey = classKey.substring(0, endIndex) + ".description"; 193 final String descrClassName = configuration.getConfigProperty(descrKey); 194 final Object descr = ObjectUtilities.loadAndInstantiate 195 (descrClassName, DefaultFunctionRegistry.class, FunctionDescription.class); 196 197 final FunctionDescription description; 198 if (descr instanceof FunctionDescription == false) 199 { 200 description = new DefaultFunctionDescription(function.getCanonicalName()); 201 } 202 else 203 { 204 description = (FunctionDescription) descr; 205 } 206 207 final FunctionCategory cat = description.getCategory(); 208 categoryFunctions.add(cat, function.getCanonicalName()); 209 functionMetaData.put (function.getCanonicalName(), description); 210 functions.put(function.getCanonicalName(), className); 211 categories.add(cat); 212 } 213 214 this.categories = (FunctionCategory[]) categories.toArray(new FunctionCategory[categories.size()]); 215 } 216 217 }