/* * Copyright (c) 2007 BUSINESS OBJECTS SOFTWARE LIMITED * 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 Business Objects 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. */ /* * MonitorApp.java * Created: 15-Mar-2004 * By: Rick Cameron */ package org.openquark.samples.bam; import java.awt.event.ActionEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.util.ArrayList; import java.util.List; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.AbstractAction; import javax.swing.Action; import javax.swing.JOptionPane; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import org.openquark.cal.compiler.CompilerMessage; import org.openquark.cal.compiler.CompilerMessageLogger; import org.openquark.cal.compiler.MessageLogger; import org.openquark.cal.compiler.ModuleName; import org.openquark.cal.compiler.io.EntryPointSpec; import org.openquark.cal.services.BasicCALServices; import org.openquark.cal.services.GemCompilationException; import org.openquark.samples.bam.MessageSource.StatusListener; import org.openquark.samples.bam.model.MonitorDocument; import org.openquark.samples.bam.model.MonitorJobDescription; import org.openquark.samples.bam.ui.MonitorMainFrame; import org.openquark.samples.bam.ui.MonitorSplashScreen; import org.openquark.util.ui.AbstractSelectableAction; /** * This class contains the top level logic for the BAM sample. * */ public class MonitorApp { /** * This class is used to log messages that are received */ private class MonitorMessageLoger implements MessageListener { /** * {@inheritDoc} */ public void messageReceived (Message message) { logMessage(message); } } public static final String DOCUMENT_PROPERTY_NAME = "Document"; public static final String STATE_PROPERTY_NAME = "State"; public static final int IDLE = 0; public static final int RUNNING = 1; private int appState = IDLE; public static final ModuleName TARGET_MODULE = ModuleName.make("Cal.Samples.BusinessActivityMonitor.RunModule"); private static final String WORKSPACE_FILE_PROPERTY = "org.openquark.samples.bam.monitor.workspace"; private static final String DEFAULT_WORKSPACE_FILE = "bam.default.cws"; /** Whether or not to use a nullary workspace. */ private static final boolean USE_NULLARY_WORKSPACE = true; /** The default workspace client id. */ public static final String DEFAULT_WORKSPACE_CLIENT_ID = USE_NULLARY_WORKSPACE ? null : "monitor"; private MonitorDocument document; private MonitorMainFrame mainFrame; private BasicCALServices calServices = null; private TriggerGemManager triggerGemManager = null; private ActionGemManager actionGemManager = null; private AbstractAction runAction = null; private AbstractAction stopAction = null; private AbstractSelectableAction enableMessageLoggingAction = null; private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport (this); private final List<MonitorJob> jobs = new ArrayList<MonitorJob> (); // of MessageJobs private final MonitorMessageLoger messageLogger = new MonitorMessageLoger (); private final Logger logger = Logger.getLogger("BAM"); private boolean loggingMessages = true; static private MonitorApp app= null; static public MonitorApp getInstance() { if (app==null) { app = new MonitorApp (); } return app; } public static void main (String[] args) { MonitorApp app = getInstance(); app.startMonitor (); } private MonitorApp () { document = new MonitorDocument (); } public void addPropertyChangeListener (PropertyChangeListener listener) { propertyChangeSupport.addPropertyChangeListener (listener); } void removePropertyChangeListener (PropertyChangeListener listener) { propertyChangeSupport.removePropertyChangeListener (listener); } private void startMonitor () { try { UIManager.setLookAndFeel (UIManager.getSystemLookAndFeelClassName ()); } catch (ClassNotFoundException e) { e.printStackTrace (); } catch (InstantiationException e) { e.printStackTrace (); } catch (IllegalAccessException e) { e.printStackTrace (); } catch (UnsupportedLookAndFeelException e) { e.printStackTrace (); } mainFrame = new MonitorMainFrame (this); MonitorSplashScreen splashScreen = new MonitorSplashScreen (mainFrame); mainFrame.setEnabled (false); splashScreen.setVisible (true); mainFrame.setVisible (true); getCalServices (); mainFrame.setEnabled (true); splashScreen.dispose (); } /** * Method getDocument * * @return Returns the MonitorDocument */ public MonitorDocument getDocument () { return document; } /** * Method isRunning * * @return Returns true iff any jobs are running */ public boolean isRunning () { return appState == RUNNING; } /** * @return Returns true iff logging messages is enabled */ boolean isLoggingMessages () { return loggingMessages; } /** * @param loggingMessages Sets whether messages should be logged */ void setLoggingMessages (boolean loggingMessages) { this.loggingMessages = loggingMessages; getEnableMessageLoggingAction().setSelected(loggingMessages); } public Action getRunAction () { if (runAction == null) { runAction = new AbstractAction ("Run") { private static final long serialVersionUID = 2750702965541172917L; public void actionPerformed (ActionEvent e) { runApp (); } }; runAction.setEnabled (!isRunning ()); } return runAction; } public Action getStopAction () { if (stopAction == null) { stopAction = new AbstractAction ("Stop") { private static final long serialVersionUID = 4182911199644551389L; /** * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */ public void actionPerformed (ActionEvent e) { stopApp (); } }; stopAction.setEnabled (isRunning ()); } return stopAction; } /** * Method getEnableMessageLoggingAction * * @return Returns an AbstractSelectableAction that controls logging of messages */ public AbstractSelectableAction getEnableMessageLoggingAction () { if (enableMessageLoggingAction == null) { enableMessageLoggingAction = new AbstractSelectableAction ("Log Messages") { private static final long serialVersionUID = 8174005437618776063L; /** * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */ public void actionPerformed (ActionEvent e) { setLoggingMessages(!isLoggingMessages()); } }; enableMessageLoggingAction.setSelected(isLoggingMessages()); } return enableMessageLoggingAction; } /** * Method runApp * * Prepare and run all jobs */ private void runApp () { //ensure a job has been defined if (document.getJobDescriptionCount () == 0) { JOptionPane.showMessageDialog (mainFrame, "You must add a message source before running.", "BAM Sample", JOptionPane.WARNING_MESSAGE); return; } // ensure all jobs are in a ready to run state for (int jobN = 0; jobN < document.getJobDescriptionCount (); ++jobN) { MonitorJobDescription jobDescription = document.getNthJobDescription (jobN); if (!readyToRun (jobDescription)) { JOptionPane.showMessageDialog (mainFrame, "The message source <" + jobDescription.getMessageSourceDescription ().getName () + "> must have triggers and actions set.", "BAM Sample", JOptionPane.WARNING_MESSAGE); return; } } // compile and start each job try { BasicCALServices calServices = getCalServices(); for (int jobN = 0; jobN < document.getJobDescriptionCount (); ++jobN) { MonitorJobDescription jobDescription = document.getNthJobDescription (jobN); GemGraphGenerator generator = new GemGraphGenerator (calServices, jobDescription); //create each new job in separate modules. ModuleName jobModuleName = ModuleName.make(jobDescription.getJobId().toUpperCase()); EntryPointSpec entry = calServices.addNewModuleWithFunction(jobModuleName, generator.getCalSource()); MessageSource messageSource = MessageSourceFactory.createMessageSource (jobDescription); MonitorJob job = new MonitorJob (jobDescription, messageSource, entry); messageSource.addStatusListener (makeStatusListener (job)); messageSource.addMessageListener(messageLogger); messageSource.start(); job.start(); jobs.add (job); } setAppState (RUNNING); } catch (GemCompilationException ex) { stopApp (); JOptionPane.showMessageDialog (mainFrame, "Error compiling job: " + ex.getMessage(), "BAM Sample", JOptionPane.WARNING_MESSAGE); } } /** * Method readyToRun * * @param jobDescription * @return Returns true iff the job description has everything needed to run */ private boolean readyToRun (MonitorJobDescription jobDescription) { return !isEmptyList (jobDescription.getTriggerDescriptions ()) && !isEmptyList (jobDescription.getActionDescriptions ()); } /** * Method emptyList * */ private boolean isEmptyList (List<?> list) { return list == null || list.size () == 0; } /** * Method makeStatusListener * */ private StatusListener makeStatusListener (final MonitorJob job) { return new StatusListener () { public void statusChanged (int newStatus) { String jobName = job.getJobDescription ().getMessageSourceDescription () .getName (); if (newStatus == MessageSource.STATUS_RUNNING) { log ("Job started: " + jobName); } else if (newStatus == MessageSource.STATUS_IDLE) { removeJob (job); log ("Job stopped: " + jobName); } } }; } /** * Method removeJob * */ protected void removeJob (MonitorJob job) { jobs.remove (job); if (jobs.isEmpty ()) { setAppState (IDLE); } } /** * Method stopApp * * */ private void stopApp () { List<MonitorJob> tempJobList = new ArrayList<MonitorJob> (jobs); for (final MonitorJob job : tempJobList) { job.getMessageSource().stop(); //stop the message source - the job will continue to process buffered messages and then finish jobs.remove (job); } } /** * Method setAppState * */ private void setAppState (int newState) { if (appState != newState) { getRunAction ().setEnabled (newState == IDLE); getStopAction ().setEnabled (newState == RUNNING); int oldState = appState; appState = newState; propertyChangeSupport.firePropertyChange (STATE_PROPERTY_NAME, oldState, newState); } } /** * Method getcalServices * * @return Returns the BasicCALServices for the app */ public BasicCALServices getCalServices () { if (calServices == null) { calServices = BasicCALServices.make (WORKSPACE_FILE_PROPERTY, DEFAULT_WORKSPACE_FILE, DEFAULT_WORKSPACE_CLIENT_ID); CompilerMessageLogger logger = new MessageLogger(); calServices.compileWorkspace(null, logger); List<CompilerMessage> compilerMessages = logger.getCompilerMessages(CompilerMessage.Severity.WARNING); if (!compilerMessages.isEmpty()) { int size = compilerMessages.size(); for (int i = 0; i < size; i++) { CompilerMessage message = compilerMessages.get(i); System.err.println(message.toString()); } } } return calServices; } /** * Method getTriggerGemManager * * @return Returns the TriggerGemManager for the app */ public TriggerGemManager getTriggerGemManager () { if (triggerGemManager == null) { triggerGemManager = new TriggerGemManager (getCalServices ()); } return triggerGemManager; } /** * Method getActionGemManager * * @return Returns the ActionGemManager for the app */ public ActionGemManager getActionGemManager () { if (actionGemManager == null) { actionGemManager = new ActionGemManager (getCalServices ()); } return actionGemManager; } /** * Method setDocument * */ public void setDocument (MonitorDocument newDocument) { assert (appState == IDLE); if (appState != IDLE) { throw new IllegalStateException ( "Attempt to set the document while the app is running"); } MonitorDocument oldDocument = document; document = newDocument; propertyChangeSupport.firePropertyChange (DOCUMENT_PROPERTY_NAME, oldDocument, newDocument); } // // Logging // /** * Method addLogHandler * * @param handler */ public void addLogHandler (Handler handler) { logger.addHandler (handler); } /** * Method removeLogHandler * * @param handler */ void removeLogHandler (Handler handler) { logger.removeHandler (handler); } /** * Method enableLogging * * @param enable */ void enableLogging (boolean enable) { if (enable) { logger.setLevel (Level.WARNING); } else { logger.setLevel (Level.OFF); } } /** * Method isLoggingEnabled * * @return Returns true iff logging is enabled */ boolean isLoggingEnabled () { return logger.getLevel ().intValue () <= Level.WARNING.intValue (); } /** * Method log * * @param message */ void log (String message) { logger.info (message); } /** * Method logMessage * * @param message */ void logMessage (Message message) { if (loggingMessages) { log ("Message received: " + message); } } }