package com.onaro.sanscreen.client.job; import java.lang.reflect.InvocationTargetException; import java.util.Date; import java.util.EventListener; import java.util.HashMap; import java.util.Map; import javax.swing.event.EventListenerList; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.eclipse.core.runtime.IProgressMonitor; import com.onaro.client.leekui.jface.operation.IUIRunnableWithProgress; import com.onaro.sanscreen.client.ejb.SessionsManager; import com.onaro.sanscreen.client.view.tabular.NavigationInfo; import com.onaro.sanscreen.server.dataobject.Context; import com.onaro.sanscreen.server.dataobject.Response; import com.onaro.sanscreen.server.sessions.ServerQuerySession; /** * Encapsulates a job for performing a query to be perfomed by the server. A query job encapsulate the query name and * modifiers. */ public final class QueryJob implements IUIRunnableWithProgress { private final EventListenerList eventListeners = new EventListenerList(); /** * The name of the query requested by the job. */ String queryType; /** * Sub query name. */ String subQuery; /** * The job's query modifiers. */ Map modifiers; private Response response; private String name = "Query"; //$NON-NLS-1$ /** * The query being run should run in the background. */ private boolean backgroundQuery = true; /** * The requested time context for this query, may be null to specify "latest". */ Date requestedContext; /** * The context for this query of a response that is already known to the caller, may be null to * specify "no response is known". */ Context currentContext; /** * The ID the query refers to. Optional. */ String id; /** * defines how the query should flag rows. if not null, an additional parameter is passed to the query. Each query * implements it's own logic in using this parameter. It is then used to set true to the relevant rows in the query. * e.g. in the tasks view, the queryflag may contain the paramter 'violation' with the violation id as the value. * The query then checks which of the tasks is related to the violation and mark the row with true in the flag * column If this field is not null, the filter is automatically enabled in the 'flag' column after loading the data * from the server */ NavigationInfo flag; /** * Collection of query params, added later to modifiers. */ Map queryParams; /** * The logger to use for the runner. */ static final Logger logger = LogManager.getLogger(QueryJob.class); /** * The parameter name used for specifying object id. */ public static final String OBJECT_ID = "ID"; //$NON-NLS-1$ /** * The parameter name used for specifying sub query. */ public static final String TYPE = "TYPE"; //$NON-NLS-1$ /** * Yes, interruptible is the correct spelling. */ private static ServerQuerySession querySession; private IProgressMonitor progressMonitor; /** * Constructs a job. * * @param queryType * the job's query name * @param subQuery * sub query name * @param requestedContext * the job's requestedContext, may be null * @param currentContext * the context of the response that is already known to the caller, may be null */ public QueryJob(String queryType, String subQuery, Object id, Date requestedContext, Context currentContext, NavigationInfo navigationInfo) { this.queryType = queryType; this.subQuery = subQuery; this.id = id == null ? null : id.toString(); this.flag = navigationInfo; this.requestedContext = requestedContext; this.currentContext = currentContext; } /** * Constructs a job. * * @param queryType * the job's query name * @param subQuery * sub query name * @param requestedContext * the job's requestedContext, may be null * @param currentContext * the context of the response that is already known to the caller, may be null * @param navigationInfo */ public QueryJob(String queryType, String subQuery, Date requestedContext, Context currentContext, NavigationInfo navigationInfo) { this.queryType = queryType; this.subQuery = subQuery; this.requestedContext = requestedContext; this.currentContext = currentContext; this.flag = navigationInfo; } /** * Get an interruptible query session. */ public static final ServerQuerySession getQuerySession() throws Exception { if (querySession == null) { querySession = SessionsManager.getInstance().getInterruptibleSession(ServerQuerySession.class); } return querySession; } /** * Constructs a job. * * @param queryType * the job's query name * @param subQuery * sub query name * @param requestedContext * the job's requested context, may be null * @param currentContext * the time of the response that is already known to the caller, may be null */ public QueryJob(String queryType, String subQuery, Date requestedContext, Context currentContext) { this(queryType, subQuery, requestedContext, currentContext, null); } /** * Gets the name of the query requested by this job. * * @return the query name */ public String getQueryType() { return queryType; } /** * Gets the sub query name . * * @return the sub query name */ public String getSubQuery() { return subQuery; } /** * Gets the query modifiers. * * @return the query modifiers */ public Map getModifiers() { Map modifiers = new HashMap(); modifiers.put(TYPE, subQuery); modifiers.put(OBJECT_ID, id); if (flag != null) { modifiers.putAll(flag.getParameters()); } if (queryParams != null) { modifiers.putAll(queryParams); } return modifiers; } /** * Gets the requested time context of this job * * @return the requested time context of this job, may be null */ public Date getRequestedContext() { return requestedContext; } public final Map getQueryParams() { if (this.queryParams == null) { this.queryParams = new HashMap(); } return queryParams; } public final void addQueryParams(Map queryParams) { getQueryParams().putAll(queryParams); } public final void addQueryParam(String key, String value) { getQueryParams().put(key, value); } public static class Listener implements EventListener { public void beforeQuery(IProgressMonitor progressMonitor) throws Exception { // do nothing } public void afterQuery(IProgressMonitor progressMonitor, Response queryResponse) throws Exception { // do nothing } } public final boolean isCanceled() { if (progressMonitor == null) return false; return progressMonitor.isCanceled(); } public final void addListener(Listener listener) { this.eventListeners.add(Listener.class, listener); } public final Response getResponse() { return response; } /** * Create a composite processor. */ public static Listener createListener(final Listener... processors) { Listener compositeProcessor = new Listener() { @Override public void beforeQuery(IProgressMonitor progressMonitor) throws Exception { for (Listener processor : processors) { // be nice if (progressMonitor.isCanceled()) return; processor.beforeQuery(progressMonitor); } } @Override public void afterQuery(IProgressMonitor progressMonitor, Response queryResponse) throws Exception { for (Listener processor : processors) { // be nice if (progressMonitor.isCanceled()) return; processor.afterQuery(progressMonitor, queryResponse); } } }; return compositeProcessor; } public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { monitor.beginTask(getName(), IProgressMonitor.UNKNOWN); try { this.progressMonitor = monitor; ServerQuerySession querySession = getQuerySession(); Listener[] listeners = eventListeners.getListeners(Listener.class); for (Listener listener : listeners) { listener.beforeQuery(progressMonitor); } if (progressMonitor.isCanceled()) return; response = querySession.query(queryType, requestedContext, currentContext, getModifiers()); if (progressMonitor.isCanceled()) return; for (Listener listener : listeners) { listener.afterQuery(progressMonitor, response); } } catch (InterruptedException ie) { throw ie; } catch (Exception e) { logger.error("Failed to query data " + getName() + " - " + e.getMessage(), e); //$NON-NLS-1$ //$NON-NLS-2$ throw new InvocationTargetException(e); } finally { monitor.done(); } } public final String getName() { return name; } public final void setName(String name) { this.name = name; } public boolean isBackground() { return backgroundQuery; } public void setBackground(boolean background) { this.backgroundQuery = background; } }