001    package org.hackystat.sensorshell;
002    
003    import java.util.Map;
004    
005    import org.hackystat.sensorbase.resource.sensordata.jaxb.SensorData;
006    
007    /**
008     * An interface that is implemented by SensorShell and MultiSensorShell. This enables
009     * sensors that can restrict themselves to the use of the following public methods to
010     * easily toggle between the use of SensorShell or MultiSensorShell depending upon 
011     * load requirements.
012     * 
013     * As a simple example, a sensor might contain code similar to the following:
014     * <pre>
015     * boolean useMulti = isMultiSensorShellRequested();
016     * Shell shell = (useMulti) ? new MultiSensorShell(...) : new SensorShell(...);
017     *  :
018     * shell.add(...)
019     *  :
020     * shell.quit()
021     * </pre>
022     * Thus, the decision to use a SensorShell vs. a MultiSensorShell can be made at run-time.
023     *   
024     * @author Philip Johnson
025     */
026    public interface Shell {
027      
028      /**
029       * Adds the passed SensorData instance to the Shell.
030       * 
031       * @param sensorData The SensorData instance to be queued for transmission.
032       * @throws SensorShellException If problems occur sending the data.
033       */
034      public void add(SensorData sensorData) throws SensorShellException;
035      
036      /**
037       * Converts the values in the KeyValMap to a SensorData instance and adds it to the
038       * Shell. Owner will default to the hackystat user in the sensor.properties file.
039       * Timestamp and Runtime will default to the current time.
040       * 
041       * @param keyValMap The map of key-value pairs.
042       * @throws SensorShellException If the Map cannot be translated into SensorData, 
043       * typically because a value
044       * was passed for Timestamp or Runtime that could not be parsed into XMLGregorianCalendar.
045       * Or if problems occur sending the data.
046       */
047      public void add(Map<String, String> keyValMap) throws SensorShellException;
048      
049      /**
050       * Returns true if the host can be pinged and the email/password combination is valid.
051       * 
052       * @return True if the host can be pinged and the user credentials are valid.
053       */
054      public boolean ping();
055      
056      /**
057       * Immediately invokes send() on this Shell. Note that you will rarely want
058       * to invoke this method. Instead, during normal operation you will rely on the
059       * autoSendTimeInterval to invoke send() in a separate thread, and then invoke quit() to invoke
060       * send() at the conclusion of the run.
061       * @return The total number of instances sent by Shell.
062       * @throws SensorShellException If problems occur sending the data.  
063       */
064      public int send() throws SensorShellException;
065      
066      /**
067       * Invokes quit() on this Shell, which invokes a final send() and closes any
068       * logging files.
069       * @throws SensorShellException If an exception occurred during any autosend. 
070       */
071      public void quit() throws SensorShellException;
072      
073      /**
074       * Returns true if any of shells in this interface have stored data offline. 
075       * @return True if any of these shells have stored offline data during this session.
076       */
077      public boolean hasOfflineData();
078      
079      /**
080       * Implements the "StateChange" algorithm.  The goal of StateChange is to add a new SensorData
081       * instance for sending to the SensorBase only when "something has changed" in the tool (which
082       * is typically an interactive editor or IDE). This method is designed to be used in conjunction
083       * with a timer-based process in the sensor client.  The timer-based process should wake up 
084       * at regular intervals, determine the currently "active" resource (typically a file), and 
085       * compute a "checksum" for that resource representing its state. (This checksum is typically
086       * the size of the resource in bytes or characters.) Having obtained those two values, the 
087       * sensor client can then create a keyValMap as if it were going to do a regular Add command,
088       * and invoke this method with it as well as with the resourceCheckSum.  This method keeps
089       * track of the last Resource and last ResourceCheckSum provided to it, and if either has
090       * changed, it will automatically invoke the Add command, passing the keyValMap to it. 
091       * <p>
092       * Thus, if an editor is running but the user is out at lunch, repeated invocations of the 
093       * StateChange method will not result in any new data being sent to the server.  
094       * @param resourceCheckSum An integer representing the state of the Resource. 
095       * @param keyValMap A map of key-value pairs representing sensor data fields and properties. 
096       * @throws Exception If problems occur during the Add (if the Add actually occurs.)
097       */
098      public void statechange(long resourceCheckSum, Map<String, String> keyValMap) 
099      throws Exception;
100      
101      /**
102       * Returns the SensorShell properties instance used to create this SensorShell.
103       * @return The SensorShellProperties instance. 
104       */
105      public SensorShellProperties getProperties();
106    
107    }