
net.customware.confluence.reporting.ReportBuilder Maven / Gradle / Ivy
/*
* Copyright (c) 2007, CustomWare Asia Pacific
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of "CustomWare Asia Pacific" nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package net.customware.confluence.reporting;
import com.atlassian.confluence.core.ContentEntityObject;
import com.atlassian.confluence.renderer.PageContext;
import com.atlassian.renderer.v2.RenderMode;
import com.atlassian.renderer.v2.macro.Macro;
import net.customware.confluence.reporting.macro.AbstractReportMacro;
import net.customware.confluence.reporting.query.Mutatable;
import net.customware.confluence.reporting.query.Query;
import net.customware.confluence.reporting.query.Queryable;
import org.apache.commons.lang.mutable.Mutable;
import java.util.Set;
/**
* Provides utility functions for handling reports.
*/
public final class ReportBuilder {
private static final ReportContext DEFAULT = new DefaultReportContext();
private static ReportContextFinder finder = new ReportContextFinder();
private ReportBuilder() {
}
private static ReportContext getReportContext() throws ReportException {
Set ctxs = finder.getThings();
switch ( ctxs.size() ) {
case 0:
return DEFAULT;
case 1:
return ctxs.iterator().next();
default:
throw new ReportException( "There must be at most one report context available, but there are "
+ ctxs.size() );
}
}
/**
* This method is called by macros which support being top-level macros.
* Typically these are reports (e.g. subclasses of
* {@link AbstractReportMacro}). All report-generation code must take place
* within the context of the supplied executor
's
* {@link Executor#execute()} method - all other attempts to modify the
* report context will throw {@link ContextException}s.
*
* @param pageContext
* The current page context.
* @param executor
* The executor containing report code.
* @return the return value of the {@link Executor#execute()} method.
* @throws ReportException
* if there is a problem while executing.
*/
public static T executeRoot( PageContext pageContext, Executor extends T> executor )
throws ReportException {
return getReportContext().executeRoot( pageContext, executor );
}
/**
* This method is called by macros which support being top-level macros and
* then wish to execute a single context object at that level.
*
* @param
* The type to return.
* @param pageContext
* The current page context.
* @param context
* The context object to execute with
* {@link #executeContext(Object, Executor)}.
* @param executor
* The executor.
* @return The executed value.
* @throws ReportException
* if there is a problem.
*/
public static T executeRoot( PageContext pageContext, final Object context,
final Executor extends T> executor ) throws ReportException {
return executeRoot( pageContext, new Executor() {
public T execute() throws ReportException {
return executeContext( context, executor );
}
} );
}
/**
* This method is called by macros which support being top-level macros and
* then wish to execute a single context object at that level.
*
* @param
* The type to return.
* @param pageContext
* The current page context.
* @param context
* The context object to execute with
* {@link #executeContext(Object, Executor)}.
* @param executor
* The executor.
* @return The executed value.
* @throws ReportException
* if there is a problem.
*/
public static T executeRoot( PageContext pageContext, final Report, ?> report,
final Executor extends T> executor ) throws ReportException {
return executeRoot( pageContext, new Executor() {
public T execute() throws ReportException {
return executeReport( report, executor );
}
} );
}
/**
* Checks if we are currently in the context of a report. Use this to check
* the status before calling methods like {@link #getCurrentContext()},
* {@link #getCurrentReport()} or {@link #getCurrentReportItem()}, which
* will throw {@link ContextException}s if in a bad context.
*
* @return true
if in the context of a report.
*/
public static boolean isReporting() {
try {
return getReportContext().isReporting();
} catch ( ReportException e ) {
return false;
}
}
/**
* This method is called when setting up a report. The current context is
* what other macros access to set values like filters, sorters and other
* configuration values. It must be called from within the context of an
* executeRoot
call.
*
* @param context
* The context object to use.
* @param executor
* The executor to process.
* @return the return value from the {@link Executor#execute()} method.
* @throws ContextException
* if there we are currently not in the context of a call to
* {@link #executeReport(PageContext, ReportBuilder.Executor)}
* @throws ExecutionException
* if there were any errors during execution.
*/
public static T executeContext( Object context, Executor extends T> executor ) throws ReportException {
return getReportContext().executeContext( context, executor );
}
/**
* Executes the specified report. It must be called from within the context
* of an executeRoot
call.
*
* @param report
* The report.
* @param executor
* The executor.
* @return the return value from the {@link Executor#execute()} method.
* @throws ContextException
* if there we are currently not in the context of a call to
* {@link #executeReport(PageContext, ReportBuilder.Executor)}
* @throws ExecutionException
* if there were any errors during execution.
*/
public static T executeReport( Report, ?> report, Executor extends T> executor )
throws ReportException {
return getReportContext().executeReport( report, executor );
}
/**
* Returns the current report.
*
* @return the current report.
* @throws ReportException
* if not in the context of a report.
*/
public static Report, ?> getCurrentReport() throws ReportException {
return getReportContext().getCurrentReport();
}
/**
* Returns the current context, as set via the
* {@link #executeContext(Object, ReportBuilder.Executor)}
* method.
*
* @return the current context.
* @throws ReportException
* if in not in the context of a report.
*/
public static Object getCurrentContext() throws ReportException {
return getReportContext().getCurrentContext();
}
/**
* Returns the current context, first checking that it implements the target
* class. If it does not, null
is returned.
*
* @param targetClass
* The target class of the context object.
* @return The current context, if it is an instance of
* targetClass
.
* @throws ReportException
* If not in the context of a report.
*/
public static C getCurrentContext( Class targetClass ) throws ReportException {
return getReportContext().getCurrentContext( targetClass );
}
/**
* Returns the current context as a {@link Query} object.
*
* @return the query or null
if the current context is not a
* Query.
* @throws ReportException
* if not in the context of a report.
*/
public static Query> getQuery() throws ReportException {
return getCurrentContext( Query.class );
}
/**
* Returns the current context as a {@link Sortable} object.
*
* @return the sortable instance, or null
if the current
* context is not a Sortable.
* @throws ReportException
* if not currently in the context of a report.
*/
public static Sortable> getSortable() throws ReportException {
return getCurrentContext( Sortable.class );
}
/**
* Returns the current context as a {@link Filterable} object.
*
* @return the filterable instance, or null
if the current
* context is not a Filterable.
* @throws ReportException
* if not currently in the context of a report.
*/
public static Filterable getFilterable() throws ReportException {
return getCurrentContext( Filterable.class );
}
/**
* Returns the current context as a {@link Mutable} object.
*
* @return the mutable instance, or null
if the current context
* is not a Mutable.
* @throws ReportException
* if not in the context of a report.
*/
public static Mutatable getMutatable( Class fromType, Class toType ) throws ReportException {
Mutatable, ?> mutatable = getCurrentContext( Mutatable.class );
if ( mutatable != null && fromType.isAssignableFrom( mutatable.getFromType() )
&& toType.isAssignableFrom( mutatable.getToType() ) )
return ( Mutatable ) mutatable;
return null;
}
/**
* Returns the current item being reported on.
*
* @return the current report item.
* @throws ReportException
* if not currently in the context of a report.
*/
public static Object getCurrentReportItem() throws ReportException {
return getReportContext().getCurrentReportItem();
}
/**
* Returns the root content object for the current servlet request. That is,
* the actual page being viewed, as opposed to the one currently being
* reported on.
*
* @return The root content.
* @throws ReportException
* if not currently in the context of a report.
*/
public static PageContext getRootPageContext() throws ReportException {
return getReportContext().getRootPageContext();
}
/**
* Returns the root {@link ContentEntityObject} for the current location.
* May be null
.
*
* @return the root content object.
* @throws ReportException
* if not currently in the context of a report.
*/
public static ContentEntityObject getRootContent() throws ReportException {
PageContext ctx = getRootPageContext();
if ( ctx != null )
return ctx.getEntity();
return null;
}
/**
* Returns the current {@link PageContext}. If the current item is a
* Confluence page or other content, that will be the page context.
* Otherwise, the parent report will be asked for it's page context and so
* on, up until the root context (which is usually the page being reported
* on) if nothing else is available. It is possible this will return
* null
in certain contexts.
*
* @return the current page context.
* @throws ReportException
* if not currently in the context of a report.
*/
public static PageContext getCurrentPageContext() throws ReportException {
Report, ?> report = getCurrentReport();
if ( report != null )
return report.getPageContext();
else
return getRootPageContext();
}
/**
* Returns the current context as a {@link Queryable} object.
*
* @return the queryable instance, or null
if the current
* context is not Queryable.
* @throws ReportException
* if not currently in the context of a report.
*/
public static Queryable getQueryable( Class type ) throws ReportException {
Queryable> queryable = getCurrentContext( Queryable.class );
if ( queryable != null && queryable.getQueryValueType() != null
&& queryable.getQueryValueType().isAssignableFrom( type ) )
return ( Queryable ) queryable;
return null;
}
/**
* Returns the current context as a {@link Outputtable} object.
*
* @return the outputtable instance, or null
if the current
* context is not Outputtable.
* @throws ReportException
* if not currently in the context of a report.
*/
public static Outputable getOutputable( Class outputType )
throws ReportException {
Outputable> outputable = getCurrentContext( Outputable.class );
if ( outputable != null && outputType.isAssignableFrom( outputable.getOutputType() ) )
return ( Outputable ) outputable;
return null;
}
/**
* Returns the current context as a {@link ReportSetup} object.
*
* @return the report setup instance, or null
if the current
* context is not ReportSetup.
* @throws ReportException
* if not currently in the context of a report.
*/
public static ReportSetup getReportSetup( Class outputType )
throws ReportException {
ReportSetup> setup = getCurrentContext( ReportSetup.class );
if ( setup != null && outputType.isAssignableFrom( setup.getOutputType() ) )
return ( ReportSetup ) setup;
return null;
}
public static String renderWiki( String wiki, RenderMode renderMode, Macro macro )
throws ReportException {
return getReportContext().renderWiki( wiki, renderMode, macro );
}
/**
* Returns the current report item context, or the
* defaultContext
if none is available. It will process in the
* following order, returning the first non-null value:
*
*
* - The current report item, if present.
* - The each ancestor's current report item, from parent to granparent, etc., if present
* - The root context
* - The default context provided
*
*
* @param defaultSource
* The default context.
* @return The result.
*/
public static Object getCurrentSource( Object defaultSource) {
Object context = null;
if ( isReporting() ) {
try {
Report, ?> report = ReportBuilder.getCurrentReport();
if ( report != null )
context = getTopReportItem( report );
if ( context == null )
context = ReportBuilder.getRootContent();
} catch ( ReportException e ) {
// Shouldn't happen, but ignore anyway.
}
}
if ( context == null )
context = defaultSource;
return context;
}
public static Object getTopReportItem( Report, ?> report ) {
Object item = report.getCurrentItem();
if ( item == null && report.getParent() != null ) {
item = getTopReportItem( report.getParent() );
}
return item;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy