/*! * 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) 2002-2013 Pentaho Corporation.. All rights reserved. */ package org.pentaho.reporting.engine.classic.extensions.datasources.cda; import org.pentaho.reporting.engine.classic.core.DataFactoryContext; import org.pentaho.reporting.engine.classic.core.DataRow; import org.pentaho.reporting.engine.classic.core.ParameterMapping; import org.pentaho.reporting.engine.classic.core.ReportDataFactoryException; import org.pentaho.reporting.engine.classic.core.ResourceBundleFactory; import org.pentaho.reporting.engine.classic.core.util.TypedTableModel; import org.pentaho.reporting.libraries.base.config.Configuration; import org.pentaho.reporting.libraries.base.util.CSVQuoter; import org.pentaho.reporting.libraries.base.util.StringUtils; import org.pentaho.reporting.libraries.base.util.URLEncoder; import javax.swing.table.TableModel; import java.io.UnsupportedEncodingException; import java.lang.reflect.Array; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; /** * Abstract Class that will be extended by each implementation of CDA invocation LOCAL or HTTP * * @author dduque */ public abstract class CdaQueryBackend implements Cloneable { public static final String METHOD_LIST_PARAMETERS = "listParameters"; public static final String DATA_ACCESS_ID = "dataAccessId"; public static final String METHOD_DO_QUERY = "doQuery"; public static final String PARAM_NAME = "name"; public static final String PARAM_TYPE = "type"; public static final String PARAM_DEFAULT_VALUE = "defaultValue"; public static final String PARAM_PATTERN = "pattern"; public static final String TYPE_DATE = "Date"; public static final String TYPE_INTEGER = "Integer"; public static final String TYPE_NUMERIC = "Numeric"; public static final String TYPE_STRING = "String"; public static final String TYPE_ARRAY_SUFFIX = "Array"; private String username; private String password; private String solution; private String path; private String file; private boolean sugarMode; private transient String baseUrl; private DataFactoryContext context; public CdaQueryBackend() { } public void initialize( final DataFactoryContext context ) { this.context = context; } protected DataFactoryContext getContext() { return context; } protected String parameterToString( final String name, final String type, final String pattern, final Object raw ) throws ReportDataFactoryException { if ( raw == null ) { return ""; } if ( TYPE_DATE.equals( type ) ) { if ( raw instanceof Date == false && raw instanceof Number == false ) { throw new ReportDataFactoryException( "For parameter " + name + " Expected date, but got " + raw.getClass() ); } final ResourceBundleFactory resourceBundleFactory = context.getResourceBundleFactory(); final SimpleDateFormat dateFormat = new SimpleDateFormat( pattern, resourceBundleFactory.getLocale() ); dateFormat.setTimeZone( resourceBundleFactory.getTimeZone() ); return dateFormat.format( raw ); } if ( TYPE_INTEGER.equals( type ) || TYPE_NUMERIC.equals( type ) ) { if ( raw instanceof Number == false ) { throw new ReportDataFactoryException( "For parameter " + name + " Expected number, but got " + raw.getClass() ); } return String.valueOf( raw ); } if ( TYPE_STRING.equals( type ) ) { return String.valueOf( raw ); } if ( type.endsWith( TYPE_ARRAY_SUFFIX ) ) { if ( raw.getClass().isArray() == false ) { if ( raw instanceof String ) { return raw.toString(); } else { throw new ReportDataFactoryException( "For parameter " + name + " Expected array, but got " + raw.getClass() ); } } final CSVQuoter quoter = new CSVQuoter( ';' ); final String arrayType = type.substring( 0, type.length() - 5 ); final StringBuilder b = new StringBuilder(); final int length = Array.getLength( raw ); for ( int i = 0; i < length; i++ ) { final Object o = Array.get( raw, i ); if ( i > 0 ) { b.append( ";" ); } final String str = parameterToString( name + "[" + i + "]", arrayType, pattern, o ); b.append( quoter.doQuoting( str ) ); } return b.toString(); } throw new ReportDataFactoryException( "Unknown type " + type + " for parameter " + name ); } private String getURLEncoding() { final Configuration configuration = context.getConfiguration(); return configuration.getConfigProperty( "org.pentaho.reporting.engine.classic.core.URLEncoding" ); } protected String encodeParameter( final String value ) { if ( StringUtils.isEmpty( value ) ) { return ""; } try { return URLEncoder.encode( value, getURLEncoding() ); } catch ( UnsupportedEncodingException e ) { throw new IllegalStateException( e ); } } public String createURL( final String method, final Map<String, String> extraParameter ) { final String baseURL = getBaseUrl(); final String basePath = isSugarMode() ? "/plugin/cda/api/" : "/content/cda/"; final StringBuilder url = new StringBuilder(); url.append( baseURL ); url.append( basePath ); url.append( method ); url.append( "?" ); url.append( "outputType=xml" ); url.append( "&path=" ); url.append( encodeParameter( getPath() ) ); if ( !isSugarMode() ) { url.append( "&solution=" ); url.append( encodeParameter( getSolution() ) ); url.append( "&file=" ); url.append( encodeParameter( getFile() ) ); } for ( final Map.Entry<String, String> entry : extraParameter.entrySet() ) { final String key = encodeParameter( entry.getKey() ); if ( StringUtils.isEmpty( key ) ) { continue; } url.append( "&" ); url.append( key ); url.append( "=" ); url.append( encodeParameter( entry.getValue() ) ); } return url.toString(); } protected TypedTableModel fetchParameter( final DataRow dataRow, final CdaQueryEntry realQuery ) throws ReportDataFactoryException { final HashMap<String, String> extras = new HashMap<String, String>(); extras.put( DATA_ACCESS_ID, realQuery.getId() ); return fetchData( dataRow, METHOD_LIST_PARAMETERS, extras ); } public synchronized TableModel queryData( final CdaQueryEntry realQuery, final DataRow parameters ) throws ReportDataFactoryException { if ( realQuery == null ) { throw new NullPointerException( "Query is null." ); //$NON-NLS-1$ } final TypedTableModel parameterModel = fetchParameter( parameters, realQuery ); // name = 0 // type = 1 // defaultValue = 2 // pattern = 3 final HashMap<String, String> extraParams = new HashMap<String, String>(); extraParams.put( DATA_ACCESS_ID, realQuery.getId() ); final int nameIdx = parameterModel.findColumn( PARAM_NAME ); final int typeIdx = parameterModel.findColumn( PARAM_TYPE ); final int defaultValueIdx = parameterModel.findColumn( PARAM_DEFAULT_VALUE ); final int patternIdx = parameterModel.findColumn( PARAM_PATTERN ); for ( int p = 0; p < parameterModel.getRowCount(); p++ ) { final String name = (String) parameterModel.getValueAt( p, nameIdx ); final String type = (String) parameterModel.getValueAt( p, typeIdx ); final String pattern = (String) parameterModel.getValueAt( p, patternIdx ); final String aliasName = findParameterAlias( realQuery, name ); final Object rawValue = parameters.get( aliasName ); final String param; if ( rawValue == null ) { param = (String) parameterModel.getValueAt( p, defaultValueIdx ); } else { param = parameterToString( name, type, pattern, rawValue ); } extraParams.put( "param" + name, param ); } return fetchData( parameters, METHOD_DO_QUERY, extraParams ); } private String findParameterAlias( final CdaQueryEntry query, final String name ) { final ParameterMapping[] parameterMapping = query.getParameters(); for ( int i = 0; i < parameterMapping.length; i++ ) { final ParameterMapping mapping = parameterMapping[ i ]; if ( name.equals( mapping.getAlias() ) ) { return mapping.getName(); } } return name; } /** * Fetch the data, has to be implemented in each sub class * * @param dataRow * @param method * @param extraParameter * @return * @throws ReportDataFactoryException */ public abstract TypedTableModel fetchData( final DataRow dataRow, final String method, final Map<String, String> extraParameter ) throws ReportDataFactoryException; public Object clone() { try { return super.clone(); } catch ( CloneNotSupportedException cne ) { throw new IllegalStateException( cne ); } } public String getUsername() { return username; } public void setUsername( final String username ) { this.username = username; } public String getPassword() { return password; } public void setPassword( final String password ) { this.password = password; } public String getSolution() { return solution; } public void setSolution( final String solution ) { this.solution = solution; } public String getPath() { return path; } public void setPath( final String path ) { this.path = path; } public String getFile() { return file; } public void setFile( final String file ) { this.file = file; } public String getBaseUrl() { return baseUrl; } public void setBaseUrl( final String baseUrl ) { this.baseUrl = baseUrl; } public boolean isSugarMode() { return sugarMode; } public void setSugarMode( boolean sugarMode ) { this.sugarMode = sugarMode; } public void cancelRunningQuery() { } }