/*
 * Copyright (C) 2005 - 2011 Jaspersoft Corporation. All rights reserved.
 * http://www.jaspersoft.com.
 *
 * Unless you have purchased  a commercial license agreement from Jaspersoft,
 * the following license terms  apply:
 *
 * This program is free software: you can redistribute it and/or  modify
 * it under the terms of the GNU Affero General Public License  as
 * published by the Free Software Foundation, either version 3 of  the
 * License, or (at your option) any later version.
 *
 * 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 Affero  General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public  License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
package com.jaspersoft.jasperserver.war.action;


import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import net.sf.jasperreports.engine.JRParameter;
import net.sf.jasperreports.engine.JRPrintAnchorIndex;
import net.sf.jasperreports.engine.JasperPrint;

import net.sf.jasperreports.engine.fill.JRFillInterruptedException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.binding.convert.ConversionExecutionException;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.validation.DataBinder;
import org.springframework.web.multipart.support.ByteArrayMultipartFileEditor;
import org.springframework.webflow.context.servlet.ServletExternalContext;
import org.springframework.webflow.core.collection.MutableAttributeMap;
import org.springframework.webflow.execution.Event;
import org.springframework.webflow.execution.RequestContext;

import com.jaspersoft.jasperserver.api.common.domain.ExecutionContext;
import com.jaspersoft.jasperserver.api.common.util.LocaleHelper;
import com.jaspersoft.jasperserver.api.engine.common.service.VirtualizerFactory;
import com.jaspersoft.jasperserver.api.engine.jasperreports.domain.impl.ReportUnitRequest;
import com.jaspersoft.jasperserver.api.engine.jasperreports.domain.impl.ReportUnitResult;
import com.jaspersoft.jasperserver.api.logging.audit.context.AuditContext;
import com.jaspersoft.jasperserver.api.logging.audit.domain.AuditEvent;
import com.jaspersoft.jasperserver.api.metadata.jasperreports.domain.ReportUnit;
import com.jaspersoft.jasperserver.war.action.hyperlinks.HyperlinkProducerFactoryFlowFactory;
import com.jaspersoft.jasperserver.war.common.JasperServerUtil;
import com.jaspersoft.jasperserver.war.dto.RuntimeInputControlWrapper;
import com.jaspersoft.jasperserver.war.util.SessionObjectSerieAccessor;

/**
 * @author Ionut Nedelcu (ionutned@users.sourceforge.net)
 * @version $Id: ViewReportAction.java 20428 2011-05-02 14:12:26Z igadzhega $
 */
public class ViewReportAction extends ReportParametersAction
{
	protected final static Log log = LogFactory.getLog(ViewReportAction.class);

	public static final String REPORTUNIT_URI = "reportUnit";

	private String flowAttributeInhibitRequestParsing;
	private String requestParameterPageIndex;
	private String flowAttributePageIndex;
	private String requestAttributeHtmlLinkHandlerFactory;
	private String flowAttributeDepth;//TODO remove?
	private String flowAttributeJasperPrintName;
	private HyperlinkProducerFactoryFlowFactory hyperlinkProducerFactory;
	private String flowAttributeIsSubflow;
	private String requestParameterReportOutput;
	private String flowAttributeReportOutput;
	private String flowAttributeUseClientTimezone;
	private SessionObjectSerieAccessor jasperPrintAccessor;
	private VirtualizerFactory virtualizerFactory;
	private Map configuredExporters;
	private String attributeReportControlsLayout;
	private String attributeReportForceControls;
	private String attributeSavedInputsState;
	private String attributeControlsHidden;
    private String attributeDashboardParametersHasError;
//	private boolean reportLevelConfigurable;
	private String attributeReportLocale;
	private String attributeNeedsInput;
	private String parameterReportLocale;
    private AuditContext auditContext;
	private String requestParameterAnchor;
    private String flowAttributeInitialPageIndex;
    private String flowAttributeInitialAnchor;

//	/**
//	 * @return Returns the reportLevelConfigurable.
//	 */
//	public boolean isReportLevelConfigurable() {
//		return reportLevelConfigurable;
//	}
//
//	/**
//	 * @param reportLevelConfigurable The reportLevelConfigurable to set.
//	 */
//	public void setReportLevelConfigurable(boolean reportLevelConfigurable) {
//		this.reportLevelConfigurable = reportLevelConfigurable;
//	}

    protected void createInputControlsAuditEvent() {
        auditContext.doInAuditContext(new AuditContext.AuditContextCallback() {
            public void execute() {
                auditContext.createAuditEvent("inputControlsQuery");
            }
        });
    }

    protected void setResourceUriToInputControlsAuditEvent(final String resourceUri) {
        auditContext.doInAuditContext("inputControlsQuery", new AuditContext.AuditContextCallbackWithEvent() {
            public void execute(AuditEvent auditEvent) {
                if (auditEvent.getResourceUri() == null) {
                    auditEvent.setResourceUri(resourceUri);
                }
            }
        });
    }

    protected void closeInputControlsAuditEvent() {
        auditContext.doInAuditContext("inputControlsQuery", new AuditContext.AuditContextCallbackWithEvent() {
            public void execute(AuditEvent auditEvent) {
                auditContext.closeAuditEvent(auditEvent);
            }
        });
    }

	public Event checkForParams(RequestContext context) throws Exception
	{
        createInputControlsAuditEvent();
		MutableAttributeMap flowScope = context.getFlowScope();

		Integer depth = flowScope.getInteger(getFlowAttributeDepth());
		if (depth == null) {
			depth = new Integer(0);
			flowScope.put(getFlowAttributeDepth(), depth);
		}

		boolean isSubflow = !context.getFlowExecutionContext().getActiveSession().isRoot();
		flowScope.put(getFlowAttributeIsSubflow(), Boolean.valueOf(isSubflow));
		
		// remember return Parent folder
		
		String folderURI = (String)context.getRequestParameters().get("ParentFolderUri");
		if (folderURI != null) {
		   flowScope.put("ParentFolderUri", folderURI);
		}
		
		String standAlone = (String)context.getRequestParameters().get("standAlone");
	    if (standAlone != null) {
		   flowScope.put("standAlone", standAlone);
	    }

		String reportOutput = context.getRequestParameters().get(getRequestParameterReportOutput());
		if (reportOutput != null) {
			flowScope.put(getFlowAttributeReportOutput(), reportOutput);
		}
		
		try {
			Integer initialPageIndex = context.getRequestParameters().getInteger(requestParameterPageIndex);

			if (initialPageIndex != null) {
				if (log.isDebugEnabled()) {
					log.debug("Setting initial page index to " + initialPageIndex);
				}

				flowScope.put(flowAttributeInitialPageIndex, initialPageIndex);
			}
		} catch (ConversionExecutionException e) {
			log.debug("Unable to parse page index parameter with value "
					+ context.getRequestParameters().get(requestParameterPageIndex));
		}

		String initialAnchor = context.getRequestParameters().get(requestParameterAnchor);
		if (initialAnchor != null) {
			if (log.isDebugEnabled()) {
				log.debug("Setting initial anchor to " + initialAnchor);
			}

			flowScope.put(flowAttributeInitialAnchor, initialAnchor);
		}

		setReportLocale(context);
		
		boolean parseRequest = toParseRequest(context);
		flowScope.put(getFlowAttributeUseClientTimezone(), Boolean.valueOf(!parseRequest));
//		flowScope.put("reportLevelConfigurable", Boolean.valueOf(isReportLevelConfigurable()));

        try {
            createWrappers(context);
            flowScope.put(getAttributeNeedsInput(), needsInput(context, (List)flowScope.get(INPUTWRAPPERS_ATTR)));
            saveInputsState(context);
        } catch (Exception e) {
            if ("true".equals(context.getRequestParameters().get(VIEW_AS_DASHBOARD_FRAME))) {
                //Then we run report as dashboard frame there is no input control validation
                //so only one validation is here - if we get exception just do not show this frame
                //this is not the best solution, so we need to think about better one.
                context.getFlashScope().put(getAttributeDashboardParametersHasError(), "true");
            } else {
                throw e;
            }
        }

        
        closeInputControlsAuditEvent();
        return success();
	}

	protected void setReportLocale(RequestContext context) {
		Locale locale = (Locale) context.getFlowScope().get(getAttributeReportLocale(), Locale.class);
		if (locale == null) {
			String localeCode = context.getRequestParameters().get(getParameterReportLocale());
			if (localeCode == null) {
				locale = LocaleContextHolder.getLocale();
			} else {
				locale = LocaleHelper.getInstance().getLocale(localeCode);
			}
			context.getFlowScope().put(getAttributeReportLocale(), locale);
		}
	}

	protected void setReportUnitAttributes(RequestContext context, ReportUnit reportUnit) {
		super.setReportUnitAttributes(context, reportUnit);
		
		MutableAttributeMap flowScope = context.getFlowScope();
		flowScope.put(getAttributeReportControlsLayout(), new Byte(reportUnit.getControlsLayout()));
		flowScope.put(getAttributeReportForceControls(), Boolean.valueOf(reportUnit.isAlwaysPromptControls()));
	}

	protected boolean isForceControls(RequestContext context) {
		Boolean force = context.getFlowScope().getBoolean(getAttributeReportForceControls());
		return force != null && force.booleanValue();
	}

	protected boolean isControlsDialog(RequestContext context) {
		Byte layoutType = (Byte) context.getFlowScope().get(getAttributeReportControlsLayout(), Byte.class);
		return layoutType != null && layoutType.byteValue() == ReportUnit.LAYOUT_POPUP_SCREEN;
	}
	
	protected boolean toParseRequest(RequestContext context) {
		Boolean inhibitRequestParsingAttr = context.getFlowScope().getBoolean(getFlowAttributeInhibitRequestParsing());
		boolean parseRequest = inhibitRequestParsingAttr == null || !inhibitRequestParsingAttr.booleanValue();
		return parseRequest;
	}
	
	protected boolean needsInput(RequestContext context, List wrappers) {
		boolean needsInput = super.needsInput(context, wrappers);
		if (needsInput) {
			if (toParseRequest(context)) {
				boolean ok = parseRequest(context, wrappers, false);
				if (ok && !isForceControls(context)) {
					needsInput = false;
				}
			} else {
				if (validateValues(wrappers, false) && !isForceControls(context)) {
					needsInput = false;
				}
			}
		}
		return needsInput;
	}

	protected void addReportExecutionParameters(RequestContext context, Map parameterValues) {
		if (virtualizerFactory != null) {
			parameterValues.put(JRParameter.REPORT_VIRTUALIZER, virtualizerFactory.getVirtualizer());
		}
		
		setReportLocaleParameter(context, parameterValues);
	}

	protected void setReportLocaleParameter(RequestContext context, Map parameterValues) {
		Locale locale = (Locale) context.getFlowScope().get(getAttributeReportLocale(), Locale.class);
		if (locale != null) {
			parameterValues.put(JRParameter.REPORT_LOCALE, locale);
		}
	}

	public Event parseRequestParameters(RequestContext context) {
        List wrappers = getInputControlWrappers(context);
    	if (!parseRequest(context, wrappers, true)) {
			return error();
    	}
    	return success();
	}
	
	public Event runReport(RequestContext context)
	{
		ReportUnitResult result = executeReport(context);
		setJasperPrint(context, result);

		Integer pageIndex = getInitialPageIndex(result, context);
		if (pageIndex == null) {
			context.getFlowScope().remove(getFlowAttributePageIndex());
		} else {
			context.getFlowScope().put(getFlowAttributePageIndex(), pageIndex);
		}

		saveInputsState(context);
		
		return success();
	}

	protected Integer getInitialPageIndex(ReportUnitResult result, RequestContext context) {
		JasperPrint jasperPrint = result.getJasperPrint();
		// first check whether there's an initial page index attribute
		Integer pageIndex = context.getFlowScope().getInteger(flowAttributeInitialPageIndex);
		if (pageIndex == null) {
			// then check whether there's an anchor attribute
			String anchor = context.getFlowScope().getString(flowAttributeInitialAnchor);
			if (anchor != null) {
				Map anchorIndexes = jasperPrint.getAnchorIndexes();
				JRPrintAnchorIndex anchorIndex = (JRPrintAnchorIndex) anchorIndexes.get(anchor);
				if (anchorIndex != null) {
					pageIndex = anchorIndex.getPageIndex();

					if (log.isDebugEnabled()) {
						log.debug("Resolved anchor " + anchor + " to page " + pageIndex);
					}
				} else {
					if (log.isDebugEnabled()) {
						log.debug("Anchor " + anchor + " not found in report");
					}
				}
			}
		} else if (pageIndex < 1 || pageIndex > jasperPrint.getPages().size()) {
			if (log.isDebugEnabled()) {
				log.debug("Page index " + pageIndex + " out of range for report with "
						+ jasperPrint.getPages().size() + " pages");
			}

			// resetting page index because the page doesn't exist
			pageIndex = null;
		} else {
			if (log.isDebugEnabled()) {
				log.debug("Using initial page index " + pageIndex);
			}

			--pageIndex;
		}
		return pageIndex;
	}


	protected static class InputsState implements Serializable
	{
		private static final long serialVersionUID = 1L;

		private final Map values;
		
		public InputsState(Map values)
		{
			this.values = values;
		}
		
		public Map getValues()
		{
			return values;
		}
	}
	
	protected void saveInputsState(RequestContext context) {
		if (hasInputs(context)) {
			InputsState state = createInputsState(context);
			context.getFlowScope().put(getAttributeSavedInputsState(), state);
		}
	}

	protected InputsState createInputsState(RequestContext context) {
		return new InputsState(collectInputValues(context));
	}

	protected Map collectInputValues(RequestContext context) {
		Map values = new HashMap();
		List wrappers = getInputControlWrappers(context);
		for (Iterator it = wrappers.iterator(); it.hasNext();) {
			RuntimeInputControlWrapper wrapper = (RuntimeInputControlWrapper) it.next();
            List wrapperInfo = new ArrayList();
            wrapperInfo.add(wrapper.getValue());
            wrapperInfo.add(wrapper.getQueryResults());
			values.put(wrapper.getInputControl().getName(), wrapperInfo);
		}
		return values;
	}
	
	public Event revertToSavedInputs(RequestContext context) {
		revertInputsState(context);
		return success();
	}

	protected void revertInputsState(RequestContext context) {
		if (hasInputs(context)) {
			InputsState state = retrieveSavedInputsState(context);
			if (state != null) {
				applyInputsState(context, state);
			}
		}
	}
	
	public Event toggleTopControls(RequestContext context) {
		Boolean controlsHidden = context.getFlowScope().getBoolean(getAttributeControlsHidden(), Boolean.FALSE);
		if (!controlsHidden.booleanValue()) {
			revertInputsState(context);
		}
		context.getFlowScope().put(getAttributeControlsHidden(), Boolean.valueOf(!controlsHidden.booleanValue()));
		return success();
	}

	protected InputsState retrieveSavedInputsState(RequestContext context) {
		return (InputsState) context.getFlowScope().get(getAttributeSavedInputsState(), InputsState.class);
	}
	
	protected void applyInputsState(RequestContext context, InputsState state) {
		Map values = state.getValues();
		List wrappers = getInputControlWrappers(context);
		for (Iterator it = wrappers.iterator(); it.hasNext();) {
			RuntimeInputControlWrapper wrapper = (RuntimeInputControlWrapper) it.next();
			String name = wrapper.getInputControl().getName();
			if (values.containsKey(name)) {
				wrapper.setErrorMessage(null);
				wrapper.setValue(((List) values.get(name)).get(0));
				wrapper.setQueryResults((Map) ((List) values.get(name)).get(1));
			}
		}
	}

    protected void createAuditEvent() {
        getAuditContext().doInAuditContext(
                new AuditContext.AuditContextCallback() {
                    public void execute() {
                        getAuditContext().createAuditEvent("runReport");
                    }
                });
    }

    protected void addParamsAndCloseAuditEvent(final long startTime) {
        getAuditContext().doInAuditContext("runReport",
                new AuditContext.AuditContextCallbackWithEvent() {
                    public void execute(AuditEvent auditEvent) {
                        getAuditContext().addPropertyToAuditEvent("reportExecutionStartTime", new Date(startTime), auditEvent);
                        getAuditContext().addPropertyToAuditEvent("reportExecutionTime", System.currentTimeMillis() - startTime, auditEvent);
                        getAuditContext().closeAuditEvent(auditEvent);
                    }
                });
    }

    protected ReportUnitResult executeReport(RequestContext context) {
        long currentTime = System.currentTimeMillis();
        createAuditEvent();
		
		Map parameterValues = getParameterValues(context);
		addReportExecutionParameters(context, parameterValues);
		
		String reportUnitUri = getReportURI(context);
		ReportUnitRequest request = new ReportUnitRequest(reportUnitUri, parameterValues);
		ReportUnitResult result = executeReport(context, request);
		//TODO set virtualizer readonly

        addParamsAndCloseAuditEvent(currentTime);
		return result;
	}

	protected ReportUnitResult executeReport(RequestContext context,
			ReportUnitRequest request) {
		try {
            return (ReportUnitResult) getEngine().execute(getExecutionContext(context), request);
        } catch (JRFillInterruptedException e) {
            throw new ReportCanceledException(e);
        }
	}

	protected void setJasperPrint(RequestContext context, ReportUnitResult result) {
		ServletExternalContext externalContext = (ServletExternalContext) context.getExternalContext();
		String name = getJasperPrintAccessor().putObject((HttpServletRequest) externalContext.getNativeRequest(), result);

        setJasperPrintId(context, name);
	}


	protected void removeCurrentJasperPrint(RequestContext context) {
		String jasperPrintName = getJasperPrintId(context);
		if (jasperPrintName != null) {
			ServletExternalContext externalContext = (ServletExternalContext) context.getExternalContext();
			
			ReportUnitResult result = (ReportUnitResult)getJasperPrintAccessor().getObject(
                    (HttpServletRequest) externalContext.getNativeRequest(), jasperPrintName);
			if (result != null && virtualizerFactory != null)
			{
				virtualizerFactory.disposeVirtualizer(result.getVirtualizer());
			}
			getJasperPrintAccessor().removeObject((HttpServletRequest) externalContext.getNativeRequest(), jasperPrintName);
		}
	}

	protected String getJasperPrintId(RequestContext context) {
		return context.getFlowScope().getString(getFlowAttributeJasperPrintName());
	}
	
	protected void setJasperPrintId(RequestContext context, String jasperPrintId) {
        context.getFlowScope().put(getFlowAttributeJasperPrintName(), jasperPrintId);
	}
	
	public Event navigate(RequestContext context) {
		Integer pageIndex = (Integer) context.getRequestParameters().getNumber(getRequestParameterPageIndex(), Integer.class);
		if (pageIndex == null) {
			context.getFlowScope().remove(getFlowAttributePageIndex());
		} else {
			context.getFlowScope().put(getFlowAttributePageIndex(), pageIndex);
		}
		return success();
	}


	public Event prepareReportView(RequestContext context) {
		if (getHyperlinkProducerFactory() != null) {
			context.getRequestScope().put(getRequestAttributeHtmlLinkHandlerFactory(), getHyperlinkProducerFactory());
		}
		context.getRequestScope().put("configuredExporters", getConfiguredExporters());

		return success();
	}


	public Event cleanSession(RequestContext context) {
        removeCurrentJasperPrint(context);

		return success();
	}

	protected void initBinder(RequestContext context, DataBinder binder) {
		binder.registerCustomEditor(byte[].class, new ByteArrayMultipartFileEditor());
	}

	public Event resetInputsToDefaults(RequestContext context) {
		resetValuesToDefaults(context);
		return success();
	}

	public String getFlowAttributeInhibitRequestParsing() {
		return flowAttributeInhibitRequestParsing;
	}

	public void setFlowAttributeInhibitRequestParsing(
			String flowAttributeInhibitRequestParsing) {
		this.flowAttributeInhibitRequestParsing = flowAttributeInhibitRequestParsing;
	}

	public String getFlowAttributePageIndex() {
		return flowAttributePageIndex;
	}

	public void setFlowAttributePageIndex(String flowAttributePageIndex) {
		this.flowAttributePageIndex = flowAttributePageIndex;
	}

	public String getRequestParameterPageIndex() {
		return requestParameterPageIndex;
	}

	public void setRequestParameterPageIndex(String requestParameterPageIndex) {
		this.requestParameterPageIndex = requestParameterPageIndex;
	}

	public String getRequestAttributeHtmlLinkHandlerFactory() {
		return requestAttributeHtmlLinkHandlerFactory;
	}

	public void setRequestAttributeHtmlLinkHandlerFactory(
			String requestAttributeHtmlLinkHandlerFactory) {
		this.requestAttributeHtmlLinkHandlerFactory = requestAttributeHtmlLinkHandlerFactory;
	}

	public String getFlowAttributeDepth() {
		return flowAttributeDepth;
	}

	public void setFlowAttributeDepth(String flowAttributeDepth) {
		this.flowAttributeDepth = flowAttributeDepth;
	}

	public String getFlowAttributeJasperPrintName() {
		return flowAttributeJasperPrintName;
	}

	public void setFlowAttributeJasperPrintName(
			String flowAttributeJasperPrintName) {
		this.flowAttributeJasperPrintName = flowAttributeJasperPrintName;
	}

	public HyperlinkProducerFactoryFlowFactory getHyperlinkProducerFactory() {
		return hyperlinkProducerFactory;
	}

	public void setHyperlinkProducerFactory(
			HyperlinkProducerFactoryFlowFactory hyperlinkProducerFactory) {
		this.hyperlinkProducerFactory = hyperlinkProducerFactory;
	}

	public String getFlowAttributeIsSubflow() {
		return flowAttributeIsSubflow;
	}

	public void setFlowAttributeIsSubflow(String requestAttributeIsSubflow) {
		this.flowAttributeIsSubflow = requestAttributeIsSubflow;
	}

	public String getFlowAttributeReportOutput() {
		return flowAttributeReportOutput;
	}

	public void setFlowAttributeReportOutput(String flowAttributeReportOutput) {
		this.flowAttributeReportOutput = flowAttributeReportOutput;
	}

	public String getRequestParameterReportOutput() {
		return requestParameterReportOutput;
	}

	public void setRequestParameterReportOutput(String requestParameterReportOutput) {
		this.requestParameterReportOutput = requestParameterReportOutput;
	}

	public String getFlowAttributeUseClientTimezone() {
		return flowAttributeUseClientTimezone;
	}

	public void setFlowAttributeUseClientTimezone(
			String flowAttributeUseClientTimezone) {
		this.flowAttributeUseClientTimezone = flowAttributeUseClientTimezone;
	}

	public SessionObjectSerieAccessor getJasperPrintAccessor() {
		return jasperPrintAccessor;
	}

	public void setJasperPrintAccessor(
			SessionObjectSerieAccessor jasperPrintAccessor) {
		this.jasperPrintAccessor = jasperPrintAccessor;
	}

	/**
	 *
	 */
	public VirtualizerFactory getVirtualizerFactory() {
		return virtualizerFactory;
	}

	/**
	 *
	 */
	public void setVirtualizerFactory(VirtualizerFactory virtualizerFactory) {
		this.virtualizerFactory = virtualizerFactory;
	}

	/**
	 * @return Returns the configuredExporters.
	 */
	public Map getConfiguredExporters() {
		return configuredExporters;
	}

	/**
	 * @param configuredExporters The configuredExporters to set.
	 */
	public void setConfiguredExporters(Map configuredExporters) {
		this.configuredExporters = configuredExporters;
	}

	public String getAttributeReportControlsLayout() {
		return attributeReportControlsLayout;
	}

	public void setAttributeReportControlsLayout(
			String attributeReportControlsLayout) {
		this.attributeReportControlsLayout = attributeReportControlsLayout;
	}

	public String getAttributeReportForceControls() {
		return attributeReportForceControls;
	}

	public void setAttributeReportForceControls(String attributeReportForceControls) {
		this.attributeReportForceControls = attributeReportForceControls;
	}

	public String getAttributeSavedInputsState() {
		return attributeSavedInputsState;
	}

	public void setAttributeSavedInputsState(String attributeLastInputsState) {
		this.attributeSavedInputsState = attributeLastInputsState;
	}

	public String getAttributeControlsHidden() {
		return attributeControlsHidden;
	}

	public void setAttributeControlsHidden(String attributeControlsHidden) {
		this.attributeControlsHidden = attributeControlsHidden;
	}

	public String getAttributeReportLocale() {
		return attributeReportLocale;
	}

	public void setAttributeReportLocale(String attributeReportLocale) {
		this.attributeReportLocale = attributeReportLocale;
	}

    public String getAttributeNeedsInput() {
        return attributeNeedsInput;
    }

    public void setAttributeNeedsInput(String attributeNeedsInput) {
        this.attributeNeedsInput = attributeNeedsInput;
    }

    public String getAttributeDashboardParametersHasError() {
        return attributeDashboardParametersHasError;
    }

    public void setAttributeDashboardParametersHasError(String attributeDashboardParametersHasError) {
        this.attributeDashboardParametersHasError = attributeDashboardParametersHasError;
    }

    public String getParameterReportLocale() {
		return parameterReportLocale;
	}

	public void setParameterReportLocale(String parameterReportLocale) {
		this.parameterReportLocale = parameterReportLocale;
	}

    public AuditContext getAuditContext() {
        return auditContext;
    }

    public void setAuditContext(AuditContext auditContext) {
        this.auditContext = auditContext;
    }

	public String getRequestParameterAnchor() {
		return requestParameterAnchor;
	}

	public void setRequestParameterAnchor(String requestParameterAnchor) {
		this.requestParameterAnchor = requestParameterAnchor;
	}

	public String getFlowAttributeInitialPageIndex() {
		return flowAttributeInitialPageIndex;
	}

	public void setFlowAttributeInitialPageIndex(
			String flowAttributeInitialPageIndex) {
		this.flowAttributeInitialPageIndex = flowAttributeInitialPageIndex;
	}

	public String getFlowAttributeInitialAnchor() {
		return flowAttributeInitialAnchor;
	}

	public void setFlowAttributeInitialAnchor(String flowAttributeInitialAnchor) {
		this.flowAttributeInitialAnchor = flowAttributeInitialAnchor;
	}
}
