fr.opensagres.xdocreport.document.Generator Maven / Gradle / Ivy
/**
* Copyright (C) 2011-2015 The XDocReport Team
*
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package fr.opensagres.xdocreport.document;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import fr.opensagres.xdocreport.converter.IConverter;
import fr.opensagres.xdocreport.converter.MimeMapping;
import fr.opensagres.xdocreport.converter.Options;
import fr.opensagres.xdocreport.converter.XDocConverterException;
import fr.opensagres.xdocreport.core.XDocReportException;
import fr.opensagres.xdocreport.core.utils.StringUtils;
import fr.opensagres.xdocreport.document.registry.TemplateEngineInitializerRegistry;
import fr.opensagres.xdocreport.document.registry.XDocReportRegistry;
import fr.opensagres.xdocreport.template.IContext;
import fr.opensagres.xdocreport.template.ITemplateEngine;
import fr.opensagres.xdocreport.template.formatter.FieldsMetadata;
import fr.opensagres.xdocreport.template.registry.TemplateEngineRegistry;
public abstract class Generator
{
// Dispatch values
public static final String REMOVE_DISPATCH = "remove";
public static final String DOWNLOAD_DISPATCH = "download";
public static final String VIEW_DISPATCH = "view";
// HTTP parameters name
public static final String REPORT_ID_HTTP_PARAM = "reportId";
public static final String TEMPLATE_ENGINE_KIND_HTTP_PARAM = "templateEngineKind";
public static final String TEMPLATE_ENGINE_ID_HTTP_PARAM = "templateEngineId";
public static final String ENTRY_NAME_HTTP_PARAM = "entryName";
public static final String PROCESS_STATE_HTTP_PARAM = "processState";
public static final String DISPATCH_HTTP_PARAM = "dispatch";
public static final String CONVERTER_ID_HTTP_PARAM = "converter";
private boolean cacheOriginalDocument;
/**
* Handles all requests (by default).
*
* @param request In object containing client request
* @param response Out object for the response
*/
public void processRequest( In request, Out response )
throws Exception
{
String dispatch = getDispatchParameter( request );
if ( REMOVE_DISPATCH.equals( dispatch ) )
{
doRemoveReport( request, response );
}
else
{
String entryName = getEntryName( request );
ProcessState processState = getProcessState( request );
if ( processState == null )
{
processState =
( StringUtils.isNotEmpty( entryName ) ) ? ProcessState.PREPROCESSED : ProcessState.GENERATED;
}
switch ( processState )
{
case ORIGINAL:
case PREPROCESSED:
doDocumentArchive( processState, entryName, request, response );
break;
case GENERATED:
doGenerateReport( entryName, request, response );
break;
}
}
}
/**
* Remove report from the registry.
*
* @param request
* @param response
* @throws IOException
*/
protected void doRemoveReport( In request, Out response )
throws IOException
{
String reportId = getReportId( request );
if ( StringUtils.isNotEmpty( reportId ) )
{
getRegistry( request ).unregisterReport( reportId );
}
doRedirectAfterRemoveReport( request, response );
}
protected void doRedirectAfterRemoveReport( In request, Out response )
throws IOException
{
// response.sendRedirect(ADMIN_JSP);
}
protected void doDocumentArchive( ProcessState state, String entryName, In request, Out response )
throws Exception
{
if ( StringUtils.isEmpty( entryName ) )
{
doSaveReport( state, request, response );
}
else
{
doSaveEntry( state, entryName, request, response );
}
}
/**
* Save document archive of the report.
*
* @param processState
* @param request
* @param response
* @throws IOException
* @throws Exception
*/
protected void doSaveReport( ProcessState processState, In request, Out response )
throws Exception
{
IXDocReport report = getReport( request );
if ( report != null )
{
// 2) Prepare HTTP response content type
prepareHTTPResponse( report.getId(), report.getMimeMapping(), request, response );
report.save( processState, getOutputStream( response ) );
}
}
/**
* Extract entry from a report.
*
* @param processState
* @param request
* @param response
* @throws IOException
* @throws Exception
*/
protected void doSaveEntry( ProcessState processState, String entryName, In request, Out response )
throws IOException, Exception
{
IXDocReport report = getReport( request );
if ( report != null )
{
// 2) Prepare HTTP response content type
prepareHTTPResponse( report.getId(), entryName, request, response );
report.saveEntry( entryName, processState, getOutputStream( response ) );
}
}
protected boolean doGenerateReport( String entryName, In request, Out response )
throws Exception, IOException
{
try
{
// 1) Get XDoc report
IXDocReport report = getReport( request );
if ( report == null )
{
throw new XDocReportException( "Cannot get XDoc Report for the HTTP request" );
}
Options options = getOptionsConverter( report, request );
if ( options == null )
{
doProcessReport( report, entryName, request, response );
}
else
{
doProcessReportWithConverter( report, options, request, response );
}
return true;
}
catch ( Exception e )
{
/*
* call the error handler to let the derived class do something useful with this failure.
*/
error( request, response, e );
return false;
}
}
/**
* Generate report with process.
*
* @param report
* @param entryName
* @param request
* @param response
* @throws XDocReportException
* @throws IOException
*/
private void doProcessReport( IXDocReport report, String entryName, In request, Out response )
throws XDocReportException, IOException
{
// 1) Prepare Java model context
IContext context = report.createContext();
populateContext( context, report.getId(), request );
if ( StringUtils.isEmpty( entryName ) )
{
// 2) Prepare HTTP response content type
prepareHTTPResponse( report.getId(), report.getMimeMapping(), request, response );
// 3) Generate report
report.process( context, getOutputStream( response ) );
}
else
{
// 2) Prepare HTTP response content type
prepareHTTPResponse( report.getId(), entryName, request, response );
// 3) Generate report
report.process( context, entryName, getOutputStream( response ) );
}
}
/**
* Generate report with conversion.
*
* @param report
* @param options
* @param request
* @param response
* @throws XDocReportException
* @throws IOException
* @throws XDocConverterException
*/
private void doProcessReportWithConverter( IXDocReport report, Options options, In request, Out response )
throws XDocReportException, IOException, XDocConverterException
{
IContext context = null;
ITemplateEngine templateEngine = report.getTemplateEngine();
if ( templateEngine != null )
{
// 1) Prepare Java model context
context = report.createContext();
populateContext( context, report.getId(), request );
}
// 2) Get converter
IConverter converter = report.getConverter( options );
// 3) Prepare HTTP response content type
prepareHTTPResponse( report.getId(), converter.getMimeMapping(), request, response );
// 4) Generate report with conversion
report.convert( context, options, getOutputStream( response ) );
}
// ----------------- Get Report
/**
* @param request
* @return
* @throws IOException
* @throws XDocReportException
*/
protected IXDocReport getReport( In request )
throws IOException, XDocReportException
{
XDocReportRegistry registry = getRegistry( request );
// 1) Get report id
String reportId = getReportId( request );
if ( StringUtils.isNotEmpty( reportId ) )
{
// Search if report is cached in the registry
IXDocReport report = registry.getReport( reportId );
if ( report != null )
{
return report;
}
}
return loadReport( reportId, registry, request );
}
/**
* Load report.
*
* @param reportId
* @param registry
* @param request
* @return
* @throws IOException
* @throws XDocReportException
*/
protected IXDocReport loadReport( String reportId, XDocReportRegistry registry, In request )
throws IOException, XDocReportException
{
// 2) Get sourceStream
InputStream sourceStream = getSourceStream( reportId, request );
if ( sourceStream == null )
{
throw new XDocReportException( "Input stream is null with reportId=" + reportId );
}
IXDocReport report = null;
// 3) Get template engine to use for the report
ITemplateEngine templateEngine = null;
String templateEngineKind = getTemplateEngineKind( reportId, request );
if ( StringUtils.isNotEmpty( templateEngineKind ) )
{
// 3.1) Load report with template engine kind
report = registry.loadReport( sourceStream, reportId, templateEngineKind );
}
else
{
// 3.1) Load report with template engine
templateEngine = getTemplateEngine( reportId, request );
report = registry.loadReport( sourceStream, reportId, templateEngine );
}
// 6) Set FieldsMetaData
FieldsMetadata fieldsMetadata = getFieldsMetadata( reportId, request );
report.setFieldsMetadata( fieldsMetadata );
// 7) Set cache
report.setCacheOriginalDocument( isCacheOriginalDocument( reportId, request ) );
return report;
}
protected boolean isCacheOriginalDocument( String reportId, In request )
{
return cacheOriginalDocument;
}
protected FieldsMetadata getFieldsMetadata( String reportId, In request )
{
return null;
}
/**
* Invoked when there is an error thrown in any part of doRequest() processing.
*
* Default will send a simple HTML response indicating there was a problem.
*
* @param request original In from servlet container.
* @param response Out object from servlet container.
* @param cause Exception that was thrown by some other part of process.
*/
protected abstract void error( In request, Out response, Exception cause );
/**
* Returns the converter id.
*
* @param request
* @return
*/
protected String getConverterId( IXDocReport report, In request )
{
return getParameter( request, CONVERTER_ID_HTTP_PARAM );
}
protected Options getOptionsConverter( IXDocReport report, In request )
{
final String converterId = getConverterId( report, request );
if ( StringUtils.isEmpty( converterId ) )
{
return null;
}
Options options = null;
int index = converterId.lastIndexOf( '_' );
if ( index != -1 )
{
String to = converterId.substring( 0, index );
String via = converterId.substring( index + 1, converterId.length() );
options = Options.getTo( to ).via( via );
}
else
{
options = Options.getTo( converterId );
}
prepareOptions( options, report, converterId, request );
return options;
}
protected void prepareOptions( Options options, IXDocReport report, String converterId, In request )
{
}
protected boolean isGenerateContentDisposition( String reportId, MimeMapping mimeMapping, In request )
{
return !VIEW_DISPATCH.equals( getDispatchParameter( request ) );
}
/**
* Returns dispatch parameter value.
*
* @param request
* @return
*/
protected String getDispatchParameter( In request )
{
return getParameter( request, DISPATCH_HTTP_PARAM );
}
/**
* Returns the id of the report.
*
* @param request
* @return
*/
protected String getReportId( In request )
{
return getParameter( request, REPORT_ID_HTTP_PARAM );
}
/**
* Returns process state (original|preprocessed|generated).
*
* @param request
* @return
*/
protected ProcessState getProcessState( In request )
{
String state = getParameter( request, PROCESS_STATE_HTTP_PARAM );
if ( ProcessState.ORIGINAL.name().equalsIgnoreCase( state ) )
{
return ProcessState.ORIGINAL;
}
if ( ProcessState.PREPROCESSED.name().equalsIgnoreCase( state ) )
{
return ProcessState.PREPROCESSED;
}
if ( ProcessState.GENERATED.name().equalsIgnoreCase( state ) )
{
return ProcessState.GENERATED;
}
return null;
}
/**
* Returns the entry name of the report.
*
* @param request
* @return
*/
protected String getEntryName( In request )
{
return getParameter( request, ENTRY_NAME_HTTP_PARAM );
}
protected String getTemplateEngineKind( String reportId, In request )
{
return getTemplateEngineKind( request );
}
protected String getTemplateEngineKind( In request )
{
return getParameter( request, TEMPLATE_ENGINE_KIND_HTTP_PARAM );
}
/**
* Returns the template engine id from request.
*
* @param request
* @return
*/
protected String getTemplateEngineId( In request )
{
return getParameter( request, TEMPLATE_ENGINE_ID_HTTP_PARAM );
}
/**
* Returns the template engine to use for the report. By default, it search if there is template id from request and
* otherwise returns the default template engine.
*
* @param reportId
* @param request
* @return
*/
protected ITemplateEngine getTemplateEngine( String reportId, In request )
{
return getTemplateEngine( request );
}
protected ITemplateEngine getTemplateEngine( IXDocReport report, In request )
{
String documentKind = report.getKind();
String templateEngineKind = getTemplateEngineKind( request );
ITemplateEngine templateEngine =
TemplateEngineInitializerRegistry.getRegistry().getTemplateEngine( templateEngineKind, documentKind );
if ( templateEngine == null )
{
templateEngine =
TemplateEngineInitializerRegistry.getRegistry().getTemplateEngine( templateEngineKind, null );
}
return templateEngine;
}
/**
* Returns the template engine from request and otherwise returns the default template engine.
*
* @param request
* @return
*/
protected ITemplateEngine getTemplateEngine( In request )
{
String templateEngineId = getTemplateEngineId( request );
if ( StringUtils.isNotEmpty( templateEngineId ) )
{
return TemplateEngineInitializerRegistry.getRegistry().getTemplateEngine( templateEngineId );
}
return TemplateEngineRegistry.getRegistry().getDefaultTemplateEngine();
}
/**
* Returns the XDocReport registry which load and cache document. By default the registry is a singleton. If you
* wish manage registry per HTTP session, override this method, create an instance per session and returns the
* registry instance linked to the HTTP session.
*
* @param request
* @return
*/
protected XDocReportRegistry getRegistry( In request )
{
return XDocReportRegistry.getRegistry();
}
/**
* Returns input stream of the report to load identified with reportId
.
*
* @param reportId report id.
* @param request Http servlet request context.
* @return
* @throws IOException
* @throws XDocReportException
*/
protected abstract InputStream getSourceStream( String reportId, In request )
throws IOException, XDocReportException;
/**
* Put the Java model in the context for the report reportId
.
*
* @param context XDocReport context to register Java data model.
* @param reportId report id.
* @param request Http servlet request context.
* @throws IOException
* @throws XDocReportException
*/
protected abstract void populateContext( IContext context, String reportId, In request )
throws IOException, XDocReportException;
protected abstract OutputStream getOutputStream( Out response )
throws IOException;
protected abstract String getParameter( In request, String name );
protected abstract void prepareHTTPResponse( String id, MimeMapping mimeMapping, In request, Out response );
protected abstract void prepareHTTPResponse( String reportId, String entryName, In request, Out response );
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy