/* * This program is free software; you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software * Foundation. * * You should have received a copy of the GNU Lesser General Public License along with this * program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html * or from the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * * This program 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 for more details. * * Copyright (c) 2006 - 2013 Pentaho Corporation and Contributors. All rights reserved. */ package org.pentaho.reporting.libraries.formula.function; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.pentaho.reporting.libraries.base.config.Configuration; import org.pentaho.reporting.libraries.base.util.HashNMap; import org.pentaho.reporting.libraries.base.util.ObjectUtilities; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; /** * Creation-Date: 02.11.2006, 12:48:32 * * @author Thomas Morgner */ public class DefaultFunctionRegistry implements FunctionRegistry { private static final Log logger = LogFactory.getLog( DefaultFunctionRegistry.class ); private static final String FUNCTIONS_PREFIX = "org.pentaho.reporting.libraries.formula.functions."; private static final String[] EMPTY_ARRAY = new String[ 0 ]; private static final FunctionCategory[] EMPTY_CATEGORIES = new FunctionCategory[ 0 ]; private FunctionCategory[] categories; private HashNMap<FunctionCategory, String> categoryFunctions; private HashMap<String, String> functions; private HashMap<String, FunctionDescription> functionMetaData; private HashMap<String, Class> cachedFunctions; public DefaultFunctionRegistry() { cachedFunctions = new HashMap<String, Class>(); categoryFunctions = new HashNMap<FunctionCategory, String>(); functionMetaData = new HashMap<String, FunctionDescription>(); functions = new HashMap<String, String>(); categories = EMPTY_CATEGORIES; } public FunctionCategory[] getCategories() { return categories.clone(); } public Function[] getFunctions() { final String[] fnNames = getFunctionNames(); final ArrayList<Function> functions = new ArrayList<Function>( fnNames.length ); for ( int i = 0; i < fnNames.length; i++ ) { final String aName = fnNames[ i ]; final Function function = createFunction( aName ); if ( function == null ) { logger.debug( "There is no such function: " + aName ); } else { functions.add( function ); } } return functions.toArray( new Function[ functions.size() ] ); } public String[] getFunctionNames() { return functions.keySet().toArray( new String[ functions.size() ] ); } public String[] getFunctionNamesByCategory( final FunctionCategory category ) { return categoryFunctions.toArray( category, EMPTY_ARRAY ); } public Function[] getFunctionsByCategory( final FunctionCategory category ) { final String[] fnNames = categoryFunctions.toArray( category, EMPTY_ARRAY ); final ArrayList<Function> functions = new ArrayList<Function>( fnNames.length ); for ( int i = 0; i < fnNames.length; i++ ) { final String aName = fnNames[ i ]; final Function function = createFunction( aName ); if ( function != null ) { functions.add( function ); } } return functions.toArray( new Function[ functions.size() ] ); } public Function createFunction( final String name ) { if ( name == null ) { throw new NullPointerException(); } final String functionClass = functions.get( name.toUpperCase() ); final Class cachedClass = cachedFunctions.get( functionClass ); if ( cachedClass != null ) { try { return (Function) cachedClass.newInstance(); } catch ( Exception e ) { return null; } } final Function function = ObjectUtilities.loadAndInstantiate ( functionClass, DefaultFunctionRegistry.class, Function.class ); if ( function == null ) { logger.debug( "There is no such function: " + name ); } else { cachedFunctions.put( functionClass, function.getClass() ); } return function; } public FunctionDescription getMetaData( final String name ) { if ( name == null ) { throw new NullPointerException(); } return functionMetaData.get( name.toUpperCase() ); } public void initialize( final Configuration configuration ) { final Iterator functionKeys = configuration.findPropertyKeys( FUNCTIONS_PREFIX ); final HashSet<FunctionCategory> categories = new HashSet<FunctionCategory>(); while ( functionKeys.hasNext() ) { final String classKey = (String) functionKeys.next(); if ( classKey.endsWith( ".class" ) == false ) { continue; } final String className = configuration.getConfigProperty( classKey ); if ( className.length() == 0 ) { continue; } final Object fn = ObjectUtilities.loadAndInstantiate ( className, DefaultFunctionRegistry.class, Function.class ); if ( fn instanceof Function == false ) { continue; } final Function function = (Function) fn; final int endIndex = classKey.length() - 6; // 6 = ".class".length(); final String descrKey = classKey.substring( 0, endIndex ) + ".description"; final String descrClassName = configuration.getConfigProperty( descrKey ); final Object descr = ObjectUtilities.loadAndInstantiate ( descrClassName, DefaultFunctionRegistry.class, FunctionDescription.class ); final FunctionDescription description; if ( descr instanceof FunctionDescription == false ) { description = new DefaultFunctionDescription( function.getCanonicalName() ); } else { description = (FunctionDescription) descr; } final FunctionCategory cat = description.getCategory(); categoryFunctions.add( cat, function.getCanonicalName() ); functionMetaData.put( function.getCanonicalName(), description ); functions.put( function.getCanonicalName(), className ); categories.add( cat ); } this.categories = categories.toArray( new FunctionCategory[ categories.size() ] ); } }