package com.ibm.able.examples.ablebean;

//====================================================================
//
// Licensed Materials - Property of IBM
//
// "Restricted Materials of IBM"
//
// Product: com.ibm.able.examples.ablebean
//
// (C) Copyright IBM Corp. 2000 All Rights Reserved.
//
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with
// IBM Corp.
//
//
//                             DISCLAIMER
//                             ----------
//
// This material contains programming source code for your consideration.
// These examples have not been thoroughly tested under all conditions.
// IBM, therefore, cannot guarantee or imply reliability, serviceability,
// performance or function of these programs.  All programs contained
// herein are provided to you "AS IS".  THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
// DISCLAIMED.
//
//====================================================================

//====================================================================
// Imports
//====================================================================
import java.awt.Dialog;
import java.io.File;
 

import javax.swing.JOptionPane;

import com.ibm.able.Able;
import com.ibm.able.AbleEvent;
import com.ibm.able.AbleException;
import com.ibm.able.AbleObject;

/**
 *  This class is an example of a simple AbleBean created by extending
 *  AbleObject.  It monitors specific files for any changes
 *  and also answers queries regarding file attributes.
 *
 * @version  $Revision: 1.12 $, $Date: 2001/11/13 22:42:10 $
 *
 * @author   Joe Bigus
 */
 public class AbleFileWatcher extends AbleObject {

   //==================================================================
   //
   // Class Variables
   //
   //==================================================================

  /**
   * Serialized version identifier in form       YYYYMMDDVerRelModxx
   */
  protected static final long serialVersionUID = 2001100500100300000L;

  /**
   * This condition indicates the file is to be watched for changes.
   */
   static public final int FILE_MODIFIED  = 0;
  /**
   * This condition indicates the file is to be watched for deletion.
   */
   static public final int FILE_DELETED   = 1;
  /**
   * This condition indicates the file is to be watched for a size threshold.
   */
   static public final int FILE_THRESHOLD = 2;

  /**
   * Take no action regardless of file condition.
   */
   static public final int ACTION_NONE    = 0;
  /**
   * Display a dialog when any condition is true.
   */
   static public final int ACTION_ALERT   = 1;
  /**
   * Start a process when any condition is true.
   */
   static public final int ACTION_EXECUTE = 2;
  /**
   * Send an event to a registered agent or bean when any condition is true.
   */
   static public final int ACTION_EVENT   = 3;

   //==================================================================
   //
   // Instance Variables
   //
   //==================================================================

   private int    action           = ACTION_EVENT;    // default action is to send an event
   private String command          = "";    // command to execute
   private int    condition        = FILE_MODIFIED;  // type of file change
   private Dialog dialog           = null;  // dialog to display for alert
   private File   watchFile             = null;  // no default file
   private String watchFileName         = null;  // no default file name
   private long   lastModified     = 0;     // last file modification
   private long   threshold        = Long.MAX_VALUE;    // file size threshold


  //==================================================================
  //
  // Constructors
  //
  //==================================================================
  /**
   * Construct an AbleFileWatcher with a name of FileWatcher.
   */
   public AbleFileWatcher() throws AbleException {
       this("FileWatcher");
   }

  /**
   * Construct an AbleFileWatcher with the provided bean name.
   *
   * @param     theBeanName A String containing the name of the object.
   */
   public AbleFileWatcher(String theBeanName) throws AbleException {
       super(theBeanName);
       reset();
       init();
   }

  /**
   * Construct an AbleFileWatcher with the provided bean name
   * and on the specified file.
   *
   * @param     theBeanName A String containing the name of the object.
   * @param     theFileName A String containing the name of the file to watch.
   */
   public AbleFileWatcher(String theBeanName, String theFileName) throws AbleException {
       super(theBeanName);
       setWatchFileName(theFileName, false);
       reset();
       init();
   }

  //==================================================================
  //
  // Accessor methods for instance variables
  //
  //==================================================================

 /**
  * Set the type of action to take when the condition watched is true.
  * @param theAction An integer representing the action to take.
  * @see AbleFileWatcher#getAction
  */
  public void setAction(int theAction) throws AbleException {
    firePropertyChange("fileWatcherAction", new Integer(action), new Integer(theAction));
    action = theAction;
  }
 /**
  * Set the type of action to take when the condition watched is true.
  * @see AbleFileWatcher#ACTION_NONE
  * @see AbleFileWatcher#ACTION_ALERT
  * @see AbleFileWatcher#ACTION_EXECUTE
  * @see AbleFileWatcher#ACTION_EVENT
  * @return An integer representing the file condition.
  */
  public int getAction() { return action ; }

 /**
  * Set the command to execute when the condition is true and
  * the action selected is ACTION_EXECUTE.
  * @param theCommand A String containing the command to execute.
  */
  public void setCommand(String theCommand) throws AbleException {
    firePropertyChange("fileWatcherCommand", command, theCommand);
    theCommand = command;
  }
 /**
  * Get the command executed when the condition is true and
  * the action selected is ACTION_EXECUTE.
  * @return A String containing the command to execute.
  */
  public String getCommand() { return command; }

 /**
  * Set the file watch condition.  Generally this value is
  * expected to be calculated.
  * @param theCondition An int representing the watch condition.
  * @see AbleFileWatcher#getCondition
  */
  public void setCondition(int theCondition) throws AbleException {
    firePropertyChange("fileWatcherCondition", new Integer(condition), new Integer(theCondition));
    condition = theCondition;
  }
 /**
  * Get the file change condition.
  * @see AbleFileWatcher#FILE_DELETED
  * @see AbleFileWatcher#FILE_MODIFIED
  * @see AbleFileWatcher#FILE_THRESHOLD
  * @return An integer representing the file condition.
  */
  public int getCondition() { return condition ; }

 /**
  * Set the Dialog to display when the condition is true and
  * the action selected is ACTION_ALERT.
  * @param theDialog A Dialog to display.
  */
  public void setDialog(Dialog theDialog) throws AbleException {
    firePropertyChange("fileWatcherDialog", dialog, theDialog);
    dialog = theDialog;
  }
 /**
  * Get the Dialog to display when the condition is true and
  * the action selected is ACTION_ALERT.
  * @return A Dialog to display.
  */
  public Dialog getDialog() {return dialog;}

 /**
  * Set the file name and get a reference to the file.
  *
  * @param theName A String containing the path and name of the file to watch.
  */
  public void setWatchFileName(String theName) throws AbleException {
    setWatchFileName(theName, true);
  }

 /**
  * Set the file name and get a reference to the file.
  *
  * @param theName A String containing the path and name of the file to watch.
  * @param sendChange A boolean indicating whether to fire a property change.
  */
  private void setWatchFileName(String theName, boolean sendChange) throws AbleException {
    watchFileName = theName;
    watchFile = new File(theName);
    lastModified = watchFile.lastModified();
    if (sendChange) firePropertyChange("fileWatcherFileName", watchFileName, theName);
  }

 /**
  * Set the file name and get a reference to the file.
  */
  public String getWatchFileName() { return watchFileName; }

  public long getFileSize() { if (watchFile == null) return 0;
                             else return watchFile.length();}

 /**
  * Set the file size threshold condition.
  * The watch condition is true if the file size exceeds
  * this value.
  * @param theThreshold A long containing the file size threshold.
  */
  public void setThreshold(long theThreshold) throws AbleException {
    firePropertyChange("fileWatcherThreshold", new Long(threshold), new Long(theThreshold));
    threshold = theThreshold;
  }
 /**
  * Get the file size threshold.
  * @return A long representing the file size threshold.
  */
  public long getThreshold() { return threshold; }

  //==================================================================
  //
  // Methods to override AbleObject
  //
  //==================================================================


  /**
   * Reset the bean to a known initialized state.
   *
   */
  public void reset() throws AbleException {

       // set defaults for member variables
       action           = ACTION_ALERT;
       command          = "";
       condition        = FILE_THRESHOLD;
       if (watchFile == null) lastModified = 0;
       else lastModified     = watchFile.lastModified();     // last file modification
       threshold        = Long.MAX_VALUE;    // file size threshold
       // Enable timer processing, but not asynch events or data flow
       setTimerEventProcessingEnabled(true);
       setSleepTime(5000);   // call processTimerEvent() every 5 seconds
       setAbleEventProcessingEnabled(Able.ProcessingDisabled_PostingDisabled);
       setDataFlowEnabled(false);
  }


 /**
  *  Check the file being watched for the
  *  condition of interest.  If the condition occurred, perform the
  *  action specified.
  *
  * @exception An exception is thrown if an action fails.
  */
  public void process() throws AbleException {
      if (checkCondition()) {
          performAction() ;
      }
  }

  /**
  *  The timer has expired, so check the file being watched for the
  *  condition of interest.  If the condition occurred, perform the
  *  action specified.
  *
  * @exception An exception is thrown if an action fails.
   */
   public void processTimerEvent() throws AbleException {
      process() ; // just call process
   }


  //==================================================================
  //
  // Miscellaneous methods
  //
  //==================================================================


  /**
   *  Check to see if the condition monitored is true.
   *  @return boolean A boolean value which indicates whether the
   *                  desired condition is true.
   */
   public boolean checkCondition() {
       boolean truth = false ;
       if (watchFile == null) return truth;
       switch (condition) {
         case FILE_MODIFIED:
            truth = changed() ;
            break ;
         case FILE_DELETED:
            truth = !exists() ;
            break ;
         case FILE_THRESHOLD:
            truth = watchFile.length() > threshold;
            break ;
         default:
            truth = false;
            break;
       }
       return truth ;
   }

   /**
    *  Take the action that is specified by the user.
    */
    private void performAction() throws AbleException{
      switch (action) {
        case ACTION_NONE:
            break;
        case ACTION_ALERT:
            System.out.println(name + ": Alert fired "+Able.LS) ;
            if (dialog == null) {
                Object[] options = { "Continue", "Quit" };
                int ans = JOptionPane.showOptionDialog(null
                              , "Continue watching '" + watchFileName + "'?"
                              , "Continue?"
                              , JOptionPane.YES_NO_OPTION
                              , JOptionPane.QUESTION_MESSAGE
                              , null
                              , options
                              , options[1]);
                if (ans == JOptionPane.NO_OPTION) {
                    this.quitEnabledEventProcessing();
                }
            } else {
                dialog.setVisible(true);
            }
            break ;
        case ACTION_EXECUTE:
            System.out.println(name + ": Executing command "+Able.LS) ;
            try {
                if (command.length() > 0)
                    Able.run(command);
            } catch (Exception err) {
                System.out.println("Error: EXEC failed, " + err.toString()) ;
                err.printStackTrace();
            }
            break ;
        case ACTION_EVENT:
                 notifyAbleEventListeners(new AbleEvent(this,"watcher"));   // signal interested observer
                 System.out.println(name + ": Event sent "+Able.LS) ;
             break ;
         default:
             System.out.println("Invalid action specified.");
             break;
      }
    }


 /**
  *  Return a string for display in a list box.  This displays the
  *  object name and state information.
  *
  *  @return String containing the object name, file being watched, and condition.
  */
  public String getDisplayString() {
    String out = new String() ;
    out = name + " fileName='" + watchFileName + "' cond='" + condition +"'";
    return out ;
  }


  //==================================================================
  //
  // Methods for querying the file being watched
  //
  //==================================================================
  /**
   * Check to see if the file being watched changed.
   *
   * @return boolean A boolean indicating whether the file changed since the last call.
   */
   public boolean changed() {
     if (watchFile == null) {
        return false;
     } else {
        long lclLastModified = lastModified ;
        lastModified = watchFile.lastModified() ;
        return !(lastModified == lclLastModified) ;
     }
   }

  /**
   * Check to see if the file being watched actually exists.
   *
   * @return boolean A boolean indicating whether the file exits.
   */
   public boolean exists() {
    if (watchFile == null) return false;
    else return watchFile.exists() ; }

  /**
   * Check to see if the file being watched is a directory.
   *
   * @return boolean A boolean indicating whether the file watched is a directory.
   */
   public boolean isDirectory() {
    if (watchFile == null) return false;
    else return watchFile.isDirectory(); }

  /**
   * Return the timestamp of the last file modification.
   *
   * @return long A long containing the timestamp of the last file modification.
   */
   public long lastModified() {
     if (watchFile == null) return 0l;
     else return watchFile.lastModified(); }

  /**
   * Return the length of the file watched.
   *
   * @return long A long containing the number of bytes in the file watched.
   */
   public long length() {
     if (watchFile == null) return 0l;
     else return watchFile.length();
   }



    /**
     * Determine the copyright of this class.
     *
     * @return    String A String containing this class's copyright statement.
     *            <p>
     */
    private static String Copyright() {
      return Able.Copyright;
    }




}
