package com.cfinkel.reports.wrappers; import com.cfinkel.reports.exceptions.BadReportSyntaxException; import com.cfinkel.reports.exceptions.InvalidInputException; import com.cfinkel.reports.generatedbeans.*; import com.cfinkel.reports.web.ParameterNames; import com.cfinkel.reports.web.WebContext; import com.cfinkel.reports.util.MapToInput; import com.cfinkel.reports.ReportSessionInfo; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import javax.servlet.http.HttpServletRequest; import java.io.Serializable; import java.text.ParseException; import java.util.*; /** * * $Author: charles $ * $Revision: 8817 $ * $Date: 2006-04-26 18:57:49 -0400 (Wed, 26 Apr 2006) $ * * Created by IntelliJ IDEA. * User: charles * Date: Mar 24, 2006 * Time: 8:49:18 PM * To change this template use File | Settings | File Templates. */ public class Report implements Serializable { public Map<String, Query> getQueries() { return queries; } private Map<String, Query> queries; private static final Logger log = Logger.getLogger(Report.class); private ReportElement reportElement; public ReportElement getReportElement() { return reportElement; } public Map<String, Input> getAllInputs() { return allInputs; } private Map<String,Input> allInputs; public Map<String, Input> getBaseInputs() { return baseInputs; } private Map<String,Input> baseInputs; public Map<String, Output> getOutputs() { return outputs; } private Map<String,Output> outputs; private String reportPath = ""; public String getReportURI() { WebContext webContext = WebContext.get(); if (webContext != null) return webContext.getRequest().getContextPath() + "/report" + reportPath; // todo: is there a better thing than to report half the URI? return reportPath; } public String getReportPath() { return reportPath; } private List<String> roles; public Report(ReportElement reportElement, String reportPath) throws BadReportSyntaxException { this.reportPath = reportPath; this.reportElement = reportElement; allInputs = new HashMap<String,Input>(); baseInputs = new LinkedHashMap<String,Input>(); outputs = new LinkedHashMap<String,Output>(); queries = new HashMap<String,Query>(); for (BaseInputElement baseInputElement : reportElement.getInput()) { Input input = new BaseInput(baseInputElement,this); baseInputs.put(baseInputElement.getName(),input); } //get queries before outputs for (QueryElement queryElement : reportElement.getQuery()) { if (queries.get(queryElement.getName()) != null) throw new BadReportSyntaxException("Query named '" + queryElement.getName() + "' already exists."); Query query; if (queryElement instanceof PreparedQueryElement) { query = new PreparedQuery((PreparedQueryElement)queryElement,this); } else { query = new GeneratedQuery((GeneratedQueryElement)queryElement); } queries.put(queryElement.getName(),query); } // get outputs for (OutputElement outputElement : reportElement.getOutput()) { if (outputs.get(outputElement.getName()) != null) { throw new BadReportSyntaxException("There are more than one output named '" + outputElement.getName()); } Output output = new Output(outputElement,this); outputs.put(outputElement.getName(),output); } // get roles: this.roles = new ArrayList<String>(); for (String role : reportElement.getAccess().getRole()) { roles.add(StringUtils.trim(role)); } } /** * Runs the report. Returns a map of output names to lists of data outputed * @return * @throws InvalidInputException * @throws ParseException */ public Map<String,List> runNewSearch(ReportSessionInfo reportSessionInfo) throws InvalidInputException, ParseException { Map<Input, Object> inputMap = MapToInput.convertParameterMapToInputs(reportSessionInfo.getCachedParameterMapOfRunReport(),this); Map<String, Output> theseOutputs = new HashMap<String, Output>(); // only get non-value list outputs: for (String outputName : this.getOutputs().keySet()) { Output output = this.getOutputs().get(outputName); if( ! output.getOutputElement().isValueList()) { theseOutputs.put(outputName,output); } } return getOutputData(inputMap, theseOutputs); } /** * runs only for non-cached data * todo: this should not run for outputs that have adapters: * @return all data * @throws InvalidInputException * @throws ParseException */ public Map<String, List> runOnlyForNonCachedData(ReportSessionInfo reportSessionInfo) throws InvalidInputException, ParseException { Map<Input, Object> inputMap = MapToInput.convertParameterMapToInputs( reportSessionInfo.getCachedParameterMapOfRunReport(),this); Map<String, Output> outputs = getListOfNonCachedNonValueListOutputs( reportSessionInfo); Map<String, List> nonCachedData = getOutputData(inputMap,outputs); Map<String,List> allData = new LinkedHashMap<String,List>(); allData.putAll(reportSessionInfo.getCachedData()); allData.putAll(nonCachedData); return allData; } private Map<String, List> getOutputData( Map<Input, Object> inputMap, Map<String, Output> outputs) throws ParseException { Map<String, Query> queries = getQueriesForOutputs(outputs); // get the data: Map<String,List> queryDatas = new HashMap<String,List>(); for (String queryName : queries.keySet()) { Query query = queries.get(queryName); List data = query.getData(inputMap); queryDatas.put(queryName,data); } Map<String, List> outputData = new LinkedHashMap<String,List>(); // this is really for the post processing: for (String outputName : outputs.keySet()) { Output output = outputs.get(outputName); String queryName = output.getQuery().getQueryElement().getName(); List data = queryDatas.get(queryName); outputData.put(outputName,output.getData(data)); } return outputData; } private Map<String, Output> getListOfNonCachedNonValueListOutputs(ReportSessionInfo reportSessionInfo) throws InvalidInputException, ParseException { Map<String, Output> outputs = new HashMap<String, Output> (); for (String output : this.getOutputs().keySet()) { if (reportSessionInfo.getCachedData().get(output) == null && reportSessionInfo.getValueListAdapters().get(output) == null) { outputs.put(output,this.getOutputs().get(output)); } } return outputs; } private Map<String, Query> getQueriesForOutputs ( Map<String, Output> outputs) { Map<String, Query> queries = new HashMap<String, Query> (); for (String outputName : outputs.keySet()) { Output output = outputs.get(outputName); queries.put(output.getQuery().getQueryElement().getName(),output.getQuery()); } return queries; } /** * returns true if this report should show a submit button * @return true or false */ public boolean isShouldShowSubmitButton() { if (this.getBaseInputs().size() == 0) return false; for (String string : this.getAllInputs().keySet()) { Input input = this.getAllInputs().get(string); if (!input.getControl().equals(Control.HIDDEN)) return true; } return false; } /** * Updates custom classes, for generated queries and post query processors */ public void updateCustomClasses() throws BadReportSyntaxException { for (String queryName : getQueries().keySet()) { Query query = getQueries().get(queryName); if (query instanceof GeneratedQuery) { ((GeneratedQuery)query).updateQueryGeneratorClass(); } } for (String outputName : getOutputs().keySet()) { Output output = getOutputs().get(outputName); output.updatePostProcessClass(); } } public String getWhiteSpaceSeparatedInputs() { StringBuilder string = new StringBuilder(); for (String inputName : this.getAllInputs().keySet()) { string.append(inputName).append(" "); } string.append(ParameterNames.run); return string.toString(); } /** * returns true if user has access * @param request * @return true if user has access */ public boolean hasAccess(HttpServletRequest request) { // if (request.isUserInRole("CN=developers,OU=aliases/lists,DC=cfinkel,DC=com")) return true; if (roles.contains("anon") || roles.contains("anonymous")) return true; for (String role : this.roles) { if (request.isUserInRole(role)) { return true; } } return false; } }