All Downloads are FREE. Search and download functionalities are using the official Maven repository.

weka.gui.beans.Filter Maven / Gradle / Ivy

Go to download

The Waikato Environment for Knowledge Analysis (WEKA), a machine learning workbench. This version represents the developer version, the "bleeding edge" of development, you could say. New functionality gets added to this version.

There is a newer version: 3.9.6
Show newest version
/*
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see .
 */

/*
 *    Filter.java
 *    Copyright (C) 2002-2012 University of Waikato, Hamilton, New Zealand
 *
 */

package weka.gui.beans;

import java.awt.BorderLayout;
import java.beans.EventSetDescriptor;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.EventObject;
import java.util.Hashtable;
import java.util.Vector;

import javax.swing.JPanel;

import weka.core.Instance;
import weka.core.Instances;
import weka.core.OptionHandler;
import weka.core.SerializedObject;
import weka.core.Utils;
import weka.filters.AllFilter;
import weka.filters.StreamableFilter;
import weka.filters.SupervisedFilter;
import weka.gui.Logger;

/**
 * A wrapper bean for Weka filters
 * 
 * @author Mark Hall
 * @version $Revision: 10220 $
 */
public class Filter extends JPanel implements BeanCommon, Visible, WekaWrapper,
  Serializable, UserRequestAcceptor, TrainingSetListener, TestSetListener,
  TrainingSetProducer, TestSetProducer, DataSource, DataSourceListener,
  InstanceListener, EventConstraints, ConfigurationProducer {

  /** for serialization */
  private static final long serialVersionUID = 8249759470189439321L;

  protected BeanVisual m_visual = new BeanVisual("Filter", BeanVisual.ICON_PATH
    + "DefaultFilter.gif", BeanVisual.ICON_PATH + "DefaultFilter_animated.gif");

  private static int IDLE = 0;
  private static int FILTERING_TRAINING = 1;
  private static int FILTERING_TEST = 2;
  private int m_state = IDLE;

  protected transient Thread m_filterThread = null;

  private transient Instances m_trainingSet;
  private transient Instances m_testingSet;

  /**
   * Global info for the wrapped filter (if it exists).
   */
  protected String m_globalInfo;

  /**
   * Objects talking to us
   */
  private final Hashtable m_listenees = new Hashtable();

  /**
   * Objects listening for training set events
   */
  private final Vector m_trainingListeners = new Vector();

  /**
   * Objects listening for test set events
   */
  private final Vector m_testListeners = new Vector();

  /**
   * Objects listening for instance events
   */
  private final Vector m_instanceListeners = new Vector();

  /**
   * Objects listening for data set events
   */
  private final Vector m_dataListeners = new Vector();

  /**
   * The filter to use.
   */
  private weka.filters.Filter m_Filter = new AllFilter();

  /**
   * Instance event object for passing on filtered instance streams
   */
  private final InstanceEvent m_ie = new InstanceEvent(this);

  /**
   * Logging.
   */
  private transient Logger m_log = null;

  /**
   * Counts incoming streamed instances.
   */
  private transient int m_instanceCount;

  /**
   * Global info (if it exists) for the wrapped filter
   * 
   * @return the global info
   */
  public String globalInfo() {
    return m_globalInfo;
  }

  public Filter() {
    setLayout(new BorderLayout());
    add(m_visual, BorderLayout.CENTER);
    setFilter(m_Filter);
  }

  /**
   * Set a custom (descriptive) name for this bean
   * 
   * @param name the name to use
   */
  @Override
  public void setCustomName(String name) {
    m_visual.setText(name);
  }

  /**
   * Get the custom (descriptive) name for this bean (if one has been set)
   * 
   * @return the custom name (or the default name)
   */
  @Override
  public String getCustomName() {
    return m_visual.getText();
  }

  /**
   * Set the filter to be wrapped by this bean
   * 
   * @param c a weka.filters.Filter value
   */
  public void setFilter(weka.filters.Filter c) {
    boolean loadImages = true;
    if (c.getClass().getName().compareTo(m_Filter.getClass().getName()) == 0) {
      loadImages = false;
    }
    m_Filter = c;
    String filterName = c.getClass().toString();
    filterName = filterName.substring(filterName.indexOf('.') + 1,
      filterName.length());
    if (loadImages) {
      if (m_Filter instanceof Visible) {
        m_visual = ((Visible) m_Filter).getVisual();
      } else {
        if (!m_visual.loadIcons(BeanVisual.ICON_PATH + filterName + ".gif",
          BeanVisual.ICON_PATH + filterName + "_animated.gif")) {
          useDefaultVisual();
        }
      }
    }
    m_visual.setText(filterName.substring(filterName.lastIndexOf('.') + 1,
      filterName.length()));

    if (m_Filter instanceof LogWriter && m_log != null) {
      ((LogWriter) m_Filter).setLog(m_log);
    }

    if (!(m_Filter instanceof StreamableFilter)
      && (m_listenees.containsKey("instance"))) {
      if (m_log != null) {
        m_log.logMessage("[Filter] " + statusMessagePrefix() + " WARNING : "
          + m_Filter.getClass().getName() + " is not an incremental filter");
        m_log.statusMessage(statusMessagePrefix()
          + "WARNING: Not an incremental filter.");
      }
    }

    // get global info
    m_globalInfo = KnowledgeFlowApp.getGlobalInfo(m_Filter);
  }

  public weka.filters.Filter getFilter() {
    return m_Filter;
  }

  /**
   * Set the filter to be wrapped by this bean
   * 
   * @param algorithm a weka.filters.Filter
   * @exception IllegalArgumentException if an error occurs
   */
  @Override
  public void setWrappedAlgorithm(Object algorithm) {

    if (!(algorithm instanceof weka.filters.Filter)) {
      throw new IllegalArgumentException(algorithm.getClass() + " : incorrect "
        + "type of algorithm (Filter)");
    }
    setFilter((weka.filters.Filter) algorithm);
  }

  /**
   * Get the filter wrapped by this bean
   * 
   * @return an Object value
   */
  @Override
  public Object getWrappedAlgorithm() {
    return getFilter();
  }

  /**
   * Accept a training set
   * 
   * @param e a TrainingSetEvent value
   */
  @Override
  public void acceptTrainingSet(TrainingSetEvent e) {
    processTrainingOrDataSourceEvents(e);
  }

  private boolean m_structurePassedOn = false;

  /**
   * Accept an instance for processing by StreamableFilters only
   * 
   * @param e an InstanceEvent value
   */
  @Override
  public void acceptInstance(InstanceEvent e) {
    // to do!
    if (m_filterThread != null) {
      String messg = "[Filter] " + statusMessagePrefix()
        + " is currently batch processing!";
      if (m_log != null) {
        m_log.logMessage(messg);
        m_log.statusMessage(statusMessagePrefix()
          + "WARNING: Filter is currently batch processing.");
      } else {
        System.err.println(messg);
      }
      return;
    }
    if (!(m_Filter instanceof StreamableFilter)) {
      stop(); // stop all processing
      if (m_log != null) {
        m_log.logMessage("[Filter] " + statusMessagePrefix() + " ERROR : "
          + m_Filter.getClass().getName()
          + "can't process streamed instances; can't continue");
        m_log.statusMessage(statusMessagePrefix()
          + "ERROR: Can't process streamed instances; can't continue.");
      }
      return;
    }
    if (e.getStatus() == InstanceEvent.FORMAT_AVAILABLE) {
      try {
        m_instanceCount = 0;
        // notifyInstanceListeners(e);
        // Instances dataset = e.getInstance().dataset();
        Instances dataset = e.getStructure();
        if (m_Filter instanceof SupervisedFilter) {
          // defualt to last column if no class is set
          if (dataset.classIndex() < 0) {
            dataset.setClassIndex(dataset.numAttributes() - 1);
          }
        }
        // initialize filter
        m_Filter.setInputFormat(dataset);
        // attempt to determine post-filtering
        // structure. If successful this can be passed on to instance
        // listeners as a new FORMAT_AVAILABLE event.
        m_structurePassedOn = false;
        try {
          if (m_Filter.isOutputFormatDefined()) {
            // System.err.println("Filter - passing on output format...");
            // System.err.println(m_Filter.getOutputFormat());
            m_ie.setStructure(new Instances(m_Filter.getOutputFormat(), 0));
            m_ie.m_formatNotificationOnly = e.m_formatNotificationOnly;
            notifyInstanceListeners(m_ie);
            m_structurePassedOn = true;
          }
        } catch (Exception ex) {
          stop(); // stop all processing
          if (m_log != null) {
            m_log
              .logMessage("[Filter] " + statusMessagePrefix()
                + " Error in obtaining post-filter structure. "
                + ex.getMessage());
            m_log.statusMessage(statusMessagePrefix()
              + "ERROR (See log for details).");
          } else {
            System.err.println("[Filter] " + statusMessagePrefix()
              + " Error in obtaining post-filter structure");
          }
        }
      } catch (Exception ex) {
        ex.printStackTrace();
      }
      return;
    }

    if (e.getStatus() == InstanceEvent.BATCH_FINISHED
      || e.getInstance() == null) {
      // get the last instance (if available)
      try {
        if (m_log != null) {
          m_log.statusMessage(statusMessagePrefix() + "Stream finished.");
        }
        if (e.getInstance() != null) {
          if (m_Filter.input(e.getInstance())) {
            Instance filteredInstance = m_Filter.output();
            if (filteredInstance != null) {
              if (!m_structurePassedOn) {
                // pass on the new structure first
                m_ie.setStructure(new Instances(filteredInstance.dataset(), 0));
                notifyInstanceListeners(m_ie);
                m_structurePassedOn = true;
              }

              m_ie.setInstance(filteredInstance);

              // if there are instances pending for output don't want to send
              // a batch finisehd at this point...
              // System.err.println("Filter - in batch finisehd...");
              if (m_Filter.batchFinished() && m_Filter.numPendingOutput() > 0) {
                m_ie.setStatus(InstanceEvent.INSTANCE_AVAILABLE);
              } else {
                m_ie.setStatus(e.getStatus());
              }
              notifyInstanceListeners(m_ie);
            }
          }
        }
        if (m_log != null) {
          m_log.statusMessage(statusMessagePrefix() + "Finished.");
        }
      } catch (Exception ex) {
        stop(); // stop all processing
        if (m_log != null) {
          m_log.logMessage("[Filter] " + statusMessagePrefix()
            + ex.getMessage());
          m_log.statusMessage(statusMessagePrefix()
            + "ERROR (See log for details).");
        }
        ex.printStackTrace();
      }

      // check for any pending instances that we might need to pass on
      try {
        if (m_Filter.batchFinished() && m_Filter.numPendingOutput() > 0) {
          if (m_log != null) {
            m_log.statusMessage(statusMessagePrefix()
              + "Passing on pending instances...");
          }
          Instance filteredInstance = m_Filter.output();
          if (filteredInstance != null) {
            if (!m_structurePassedOn) {
              // pass on the new structure first
              m_ie.setStructure((Instances) (new SerializedObject(
                filteredInstance.dataset()).getObject()));
              notifyInstanceListeners(m_ie);
              m_structurePassedOn = true;
            }

            m_ie.setInstance(filteredInstance);

            // TODO here is the problem I think
            m_ie.setStatus(InstanceEvent.INSTANCE_AVAILABLE);
            notifyInstanceListeners(m_ie);
          }
          while (m_Filter.numPendingOutput() > 0) {
            filteredInstance = m_Filter.output();

            if (filteredInstance.dataset().checkForStringAttributes()) {
              for (int i = 0; i < filteredInstance.dataset().numAttributes(); i++) {
                if (filteredInstance.dataset().attribute(i).isString()
                  && !filteredInstance.isMissing(i)) {
                  String val = filteredInstance.stringValue(i);

                  m_ie.getStructure().attribute(i).setStringValue(val);
                  filteredInstance.setValue(i, 0);
                }
              }
            }
            filteredInstance.setDataset(m_ie.getStructure());

            m_ie.setInstance(filteredInstance);
            // System.err.println("Filter - sending pending...");
            if (m_Filter.numPendingOutput() == 0) {
              m_ie.setStatus(InstanceEvent.BATCH_FINISHED);
            } else {
              m_ie.setStatus(InstanceEvent.INSTANCE_AVAILABLE);
            }
            notifyInstanceListeners(m_ie);
          }
          if (m_log != null) {
            m_log.statusMessage(statusMessagePrefix() + "Finished.");
          }
        }
      } catch (Exception ex) {
        stop(); // stop all processing
        if (m_log != null) {
          m_log.logMessage("[Filter] " + statusMessagePrefix() + ex.toString());
          m_log.statusMessage(statusMessagePrefix()
            + "ERROR (See log for details.");
        }
        ex.printStackTrace();
      }
    } else {
      // pass instance through the filter
      try {
        if (!m_Filter.input(e.getInstance())) {
          // System.err.println("Filter - inputing instance into filter...");
          /*
           * if (m_log != null) {
           * m_log.logMessage("ERROR : filter not ready to output instance"); }
           */

          // quietly return. Filter might be able to output some instances
          // once the batch is finished.
          return;
        }

        // collect output instance.
        Instance filteredInstance = m_Filter.output();
        if (filteredInstance == null) {
          return;
        }
        m_instanceCount++;

        if (!m_structurePassedOn) {
          // pass on the new structure first
          m_ie.setStructure(new Instances(filteredInstance.dataset(), 0));
          notifyInstanceListeners(m_ie);
          m_structurePassedOn = true;
        }

        filteredInstance.setDataset(m_ie.getStructure());

        if (filteredInstance.dataset().checkForStringAttributes()) {
          for (int i = 0; i < filteredInstance.dataset().numAttributes(); i++) {
            if (filteredInstance.dataset().attribute(i).isString()
              && !filteredInstance.isMissing(i)) {
              String val = filteredInstance.stringValue(i);

              filteredInstance.dataset().attribute(i).setStringValue(val);
              filteredInstance.setValue(i, 0);
            }
          }
        }

        m_ie.setInstance(filteredInstance);
        m_ie.setStatus(e.getStatus());

        if (m_log != null && (m_instanceCount % 10000 == 0)) {
          m_log.statusMessage(statusMessagePrefix() + "Received "
            + m_instanceCount + " instances.");
        }
        notifyInstanceListeners(m_ie);
      } catch (Exception ex) {
        stop(); // stop all processing
        if (m_log != null) {
          m_log.logMessage("[Filter] " + statusMessagePrefix() + ex.toString());
          m_log.statusMessage(statusMessagePrefix()
            + "ERROR (See log for details).");
        }
        ex.printStackTrace();
      }
    }
  }

  private void processTrainingOrDataSourceEvents(final EventObject e) {
    boolean structureOnly = false;
    if (e instanceof DataSetEvent) {
      structureOnly = ((DataSetEvent) e).isStructureOnly();
      if (structureOnly) {
        notifyDataOrTrainingListeners(e);
      }
    }
    if (e instanceof TrainingSetEvent) {
      structureOnly = ((TrainingSetEvent) e).isStructureOnly();
      if (structureOnly) {
        notifyDataOrTrainingListeners(e);
      }
    }
    if (structureOnly && !(m_Filter instanceof StreamableFilter)) {
      return; // nothing can be done
    }

    if (m_filterThread == null) {
      try {
        if (m_state == IDLE) {
          synchronized (this) {
            m_state = FILTERING_TRAINING;
          }
          m_trainingSet = (e instanceof TrainingSetEvent) ? ((TrainingSetEvent) e)
            .getTrainingSet() : ((DataSetEvent) e).getDataSet();

          // final String oldText = m_visual.getText();
          m_filterThread = new Thread() {
            @SuppressWarnings("deprecation")
            @Override
            public void run() {
              try {
                if (m_trainingSet != null) {
                  m_visual.setAnimated();
                  // m_visual.setText("Filtering training data...");
                  if (m_log != null) {
                    m_log.statusMessage(statusMessagePrefix()
                      + "Filtering training data ("
                      + m_trainingSet.relationName() + ")");
                  }
                  m_Filter.setInputFormat(m_trainingSet);
                  Instances filteredData = weka.filters.Filter.useFilter(
                    m_trainingSet, m_Filter);
                  // m_visual.setText(oldText);
                  m_visual.setStatic();
                  EventObject ne;
                  if (e instanceof TrainingSetEvent) {
                    ne = new TrainingSetEvent(weka.gui.beans.Filter.this,
                      filteredData);
                    ((TrainingSetEvent) ne).m_setNumber = ((TrainingSetEvent) e).m_setNumber;
                    ((TrainingSetEvent) ne).m_maxSetNumber = ((TrainingSetEvent) e).m_maxSetNumber;
                  } else {
                    ne = new DataSetEvent(weka.gui.beans.Filter.this,
                      filteredData);
                  }

                  notifyDataOrTrainingListeners(ne);
                }
              } catch (Exception ex) {
                ex.printStackTrace();
                if (m_log != null) {
                  m_log.logMessage("[Filter] " + statusMessagePrefix()
                    + ex.getMessage());
                  m_log.statusMessage(statusMessagePrefix()
                    + "ERROR (See log for details).");
                  // m_log.statusMessage("Problem filtering: see log for details.");
                }
                Filter.this.stop(); // stop all processing
              } finally {
                // m_visual.setText(oldText);
                m_visual.setStatic();
                m_state = IDLE;
                if (isInterrupted()) {
                  m_trainingSet = null;
                  if (m_log != null) {
                    m_log.logMessage("[Filter] " + statusMessagePrefix()
                      + " training set interrupted!");
                    m_log.statusMessage(statusMessagePrefix() + "INTERRUPTED");
                  }
                } else {
                  if (m_log != null) {
                    m_log.statusMessage(statusMessagePrefix() + "Finished.");
                  }
                }
                block(false);
                m_filterThread = null;
              }
            }
          };
          m_filterThread.setPriority(Thread.MIN_PRIORITY);
          m_filterThread.start();
          block(true);
          m_filterThread = null;
          m_state = IDLE;
        }
      } catch (Exception ex) {
        ex.printStackTrace();
      }
    }
  }

  /**
   * Accept a test set
   * 
   * @param e a TestSetEvent value
   */
  @Override
  public void acceptTestSet(final TestSetEvent e) {
    if (e.isStructureOnly()) {
      notifyTestListeners(e);
    }
    if (m_trainingSet != null && m_trainingSet.equalHeaders(e.getTestSet())
      && m_filterThread == null) {
      try {
        if (m_state == IDLE) {
          m_state = FILTERING_TEST;
        }
        m_testingSet = e.getTestSet();
        // final String oldText = m_visual.getText();
        m_filterThread = new Thread() {
          @SuppressWarnings("deprecation")
          @Override
          public void run() {
            try {
              if (m_testingSet != null) {
                m_visual.setAnimated();
                // m_visual.setText("Filtering test data...");
                if (m_log != null) {
                  m_log.statusMessage(statusMessagePrefix()
                    + "Filtering test data (" + m_testingSet.relationName()
                    + ")");
                }
                Instances filteredTest = weka.filters.Filter.useFilter(
                  m_testingSet, m_Filter);
                // m_visual.setText(oldText);
                m_visual.setStatic();
                TestSetEvent ne = new TestSetEvent(weka.gui.beans.Filter.this,
                  filteredTest);
                ne.m_setNumber = e.m_setNumber;
                ne.m_maxSetNumber = e.m_maxSetNumber;
                notifyTestListeners(ne);
              }
            } catch (Exception ex) {
              ex.printStackTrace();
              if (m_log != null) {
                m_log.logMessage("[Filter] " + statusMessagePrefix()
                  + ex.getMessage());
                m_log.statusMessage(statusMessagePrefix()
                  + "ERROR (See log for details).");
              }
              Filter.this.stop();
            } finally {
              // m_visual.setText(oldText);
              m_visual.setStatic();
              m_state = IDLE;
              if (isInterrupted()) {
                m_trainingSet = null;
                if (m_log != null) {
                  m_log.logMessage("[Filter] " + statusMessagePrefix()
                    + " test set interrupted!");
                  m_log.statusMessage(statusMessagePrefix() + "INTERRUPTED");
                  // m_log.statusMessage("OK");
                }
              } else {
                if (m_log != null) {
                  m_log.statusMessage(statusMessagePrefix() + "Finished.");
                }
              }
              block(false);
              m_filterThread = null;
            }
          }
        };
        m_filterThread.setPriority(Thread.MIN_PRIORITY);
        m_filterThread.start();
        block(true);
        m_filterThread = null;
        m_state = IDLE;
      } catch (Exception ex) {
        ex.printStackTrace();
      }
    }
  }

  /**
   * Accept a data set
   * 
   * @param e a DataSetEvent value
   */
  @Override
  public void acceptDataSet(DataSetEvent e) {
    processTrainingOrDataSourceEvents(e);
  }

  /**
   * Set the visual appearance of this bean
   * 
   * @param newVisual a BeanVisual value
   */
  @Override
  public void setVisual(BeanVisual newVisual) {
    m_visual = newVisual;
  }

  /**
   * Get the visual appearance of this bean
   * 
   * @return a BeanVisual value
   */
  @Override
  public BeanVisual getVisual() {
    return m_visual;
  }

  /**
   * Use the default visual appearance
   */
  @Override
  public void useDefaultVisual() {
    m_visual.loadIcons(BeanVisual.ICON_PATH + "DefaultFilter.gif",
      BeanVisual.ICON_PATH + "DefaultFilter_animated.gif");
  }

  /**
   * Add a training set listener
   * 
   * @param tsl a TrainingSetListener value
   */
  @Override
  public synchronized void addTrainingSetListener(TrainingSetListener tsl) {
    m_trainingListeners.addElement(tsl);
  }

  /**
   * Remove a training set listener
   * 
   * @param tsl a TrainingSetListener value
   */
  @Override
  public synchronized void removeTrainingSetListener(TrainingSetListener tsl) {
    m_trainingListeners.removeElement(tsl);
  }

  /**
   * Add a test set listener
   * 
   * @param tsl a TestSetListener value
   */
  @Override
  public synchronized void addTestSetListener(TestSetListener tsl) {
    m_testListeners.addElement(tsl);
  }

  /**
   * Remove a test set listener
   * 
   * @param tsl a TestSetListener value
   */
  @Override
  public synchronized void removeTestSetListener(TestSetListener tsl) {
    m_testListeners.removeElement(tsl);
  }

  /**
   * Add a data source listener
   * 
   * @param dsl a DataSourceListener value
   */
  @Override
  public synchronized void addDataSourceListener(DataSourceListener dsl) {
    m_dataListeners.addElement(dsl);
  }

  /**
   * Remove a data source listener
   * 
   * @param dsl a DataSourceListener value
   */
  @Override
  public synchronized void removeDataSourceListener(DataSourceListener dsl) {
    m_dataListeners.remove(dsl);
  }

  /**
   * Add an instance listener
   * 
   * @param tsl an InstanceListener value
   */
  @Override
  public synchronized void addInstanceListener(InstanceListener tsl) {
    m_instanceListeners.addElement(tsl);
  }

  /**
   * Remove an instance listener
   * 
   * @param tsl an InstanceListener value
   */
  @Override
  public synchronized void removeInstanceListener(InstanceListener tsl) {
    m_instanceListeners.removeElement(tsl);
  }

  /**
   * We don't have to keep track of configuration listeners (see the
   * documentation for ConfigurationListener/ConfigurationEvent).
   * 
   * @param cl a ConfigurationListener.
   */
  @Override
  public synchronized void addConfigurationListener(ConfigurationListener cl) {

  }

  /**
   * We don't have to keep track of configuration listeners (see the
   * documentation for ConfigurationListener/ConfigurationEvent).
   * 
   * @param cl a ConfigurationListener.
   */
  @Override
  public synchronized void removeConfigurationListener(ConfigurationListener cl) {

  }

  private void notifyDataOrTrainingListeners(EventObject ce) {
    Vector l;
    synchronized (this) {
      l = (ce instanceof TrainingSetEvent) ? (Vector) m_trainingListeners
        .clone() : (Vector) m_dataListeners.clone();
    }
    if (l.size() > 0) {
      for (int i = 0; i < l.size(); i++) {
        if (ce instanceof TrainingSetEvent) {
          ((TrainingSetListener) l.elementAt(i))
            .acceptTrainingSet((TrainingSetEvent) ce);
        } else {
          ((DataSourceListener) l.elementAt(i))
            .acceptDataSet((DataSetEvent) ce);
        }
      }
    }
  }

  @SuppressWarnings("unchecked")
  private void notifyTestListeners(TestSetEvent ce) {
    Vector l;
    synchronized (this) {
      l = (Vector) m_testListeners.clone();
    }
    if (l.size() > 0) {
      for (int i = 0; i < l.size(); i++) {
        l.elementAt(i).acceptTestSet(ce);
      }
    }
  }

  @SuppressWarnings("unchecked")
  protected void notifyInstanceListeners(InstanceEvent tse) {
    Vector l;
    synchronized (this) {
      l = (Vector) m_instanceListeners.clone();
    }
    if (l.size() > 0) {
      for (int i = 0; i < l.size(); i++) {
        // System.err.println("Notifying instance listeners "
        // +"(Filter)");
        l.elementAt(i).acceptInstance(tse);
      }
    }
  }

  /**
   * Returns true if, at this time, the object will accept a connection with
   * respect to the supplied event name
   * 
   * @param eventName the event
   * @return true if the object will accept a connection
   */
  @Override
  public boolean connectionAllowed(String eventName) {

    if (m_listenees.containsKey(eventName)) {
      return false;
    }

    /*
     * reject a test event if we don't have a training or data set event if
     * (eventName.compareTo("testSet") == 0) { if
     * (!m_listenees.containsKey("trainingSet") &&
     * !m_listenees.containsKey("dataSet")) { return false; } }
     */

    // will need to reject train/test listener if we have a
    // data source listener and vis versa
    if (m_listenees.containsKey("dataSet")
      && (eventName.compareTo("trainingSet") == 0
        || eventName.compareTo("testSet") == 0 || eventName
        .compareTo("instance") == 0)) {
      return false;
    }

    if ((m_listenees.containsKey("trainingSet") || m_listenees
      .containsKey("testSet"))
      && (eventName.compareTo("dataSet") == 0 || eventName
        .compareTo("instance") == 0)) {
      return false;
    }

    if (m_listenees.containsKey("instance")
      && (eventName.compareTo("trainingSet") == 0
        || eventName.compareTo("testSet") == 0 || eventName
        .compareTo("dataSet") == 0)) {
      return false;
    }

    // reject an instance event connection if our filter isn't
    // streamable
    if (eventName.compareTo("instance") == 0
      && !(m_Filter instanceof StreamableFilter)) {
      return false;
    }
    return true;
  }

  /**
   * Returns true if, at this time, the object will accept a connection
   * according to the supplied EventSetDescriptor
   * 
   * @param esd the EventSetDescriptor
   * @return true if the object will accept a connection
   */
  @Override
  public boolean connectionAllowed(EventSetDescriptor esd) {
    return connectionAllowed(esd.getName());
  }

  /**
   * Notify this object that it has been registered as a listener with a source
   * with respect to the supplied event name
   * 
   * @param eventName
   * @param source the source with which this object has been registered as a
   *          listener
   */
  @Override
  public synchronized void connectionNotification(String eventName,
    Object source) {
    if (connectionAllowed(eventName)) {
      m_listenees.put(eventName, source);
      if (m_Filter instanceof ConnectionNotificationConsumer) {
        ((ConnectionNotificationConsumer) m_Filter).connectionNotification(
          eventName, source);
      }
    }
  }

  /**
   * Notify this object that it has been deregistered as a listener with a
   * source with respect to the supplied event name
   * 
   * @param eventName the event
   * @param source the source with which this object has been registered as a
   *          listener
   */
  @Override
  public synchronized void disconnectionNotification(String eventName,
    Object source) {
    if (m_Filter instanceof ConnectionNotificationConsumer) {
      ((ConnectionNotificationConsumer) m_Filter).disconnectionNotification(
        eventName, source);
    }
    m_listenees.remove(eventName);
  }

  /**
   * Function used to stop code that calls acceptTrainingSet, acceptTestSet, or
   * acceptDataSet. This is needed as filtering is performed inside a separate
   * thread of execution.
   * 
   * @param tf a boolean value
   */
  private synchronized void block(boolean tf) {
    if (tf) {
      try {
        // only block if thread is still doing something useful!
        if (m_filterThread.isAlive() && m_state != IDLE) {
          wait();
        }
      } catch (InterruptedException ex) {
      }
    } else {
      notifyAll();
    }
  }

  /**
   * Stop all action if possible
   */
  @SuppressWarnings("deprecation")
  @Override
  public void stop() {
    // tell all listenees (upstream beans) to stop
    Enumeration en = m_listenees.keys();
    while (en.hasMoreElements()) {
      Object tempO = m_listenees.get(en.nextElement());
      if (tempO instanceof BeanCommon) {
        ((BeanCommon) tempO).stop();
      }
    }

    // stop the filter thread
    if (m_filterThread != null) {
      m_filterThread.interrupt();
      m_filterThread.stop();
      m_filterThread = null;
      m_visual.setStatic();
    }
  }

  /**
   * Returns true if. at this time, the bean is busy with some (i.e. perhaps a
   * worker thread is performing some calculation).
   * 
   * @return true if the bean is busy.
   */
  @Override
  public boolean isBusy() {
    return (m_filterThread != null);
  }

  /**
   * Set a logger
   * 
   * @param logger a Logger value
   */
  @Override
  public void setLog(Logger logger) {
    m_log = logger;

    if (m_Filter != null && m_Filter instanceof LogWriter) {
      ((LogWriter) m_Filter).setLog(m_log);
    }
  }

  /**
   * Return an enumeration of user requests
   * 
   * @return an Enumeration value
   */
  @Override
  public Enumeration enumerateRequests() {
    Vector newVector = new Vector(0);
    if (m_filterThread != null) {
      newVector.addElement("Stop");
    }
    return newVector.elements();
  }

  /**
   * Perform the named request
   * 
   * @param request a String value
   * @exception IllegalArgumentException if an error occurs
   */
  @Override
  public void performRequest(String request) {
    if (request.compareTo("Stop") == 0) {
      stop();
    } else {
      throw new IllegalArgumentException(request + " not supported (Filter)");
    }
  }

  /**
   * Returns true, if at the current time, the named event could be generated.
   * Assumes that supplied event names are names of events that could be
   * generated by this bean.
   * 
   * @param eventName the name of the event in question
   * @return true if the named event could be generated at this point in time
   */
  @Override
  public boolean eventGeneratable(String eventName) {

    if (eventName.equals("configuration") && m_Filter != null) {
      return true;
    }

    // can't generate the named even if we are not receiving it as an
    // input!
    if (!m_listenees.containsKey(eventName)) {
      return false;
    }
    Object source = m_listenees.get(eventName);
    if (source instanceof EventConstraints) {
      if (!((EventConstraints) source).eventGeneratable(eventName)) {
        return false;
      }
    }
    if (eventName.compareTo("instance") == 0) {
      if (!(m_Filter instanceof StreamableFilter)) {
        return false;
      }
    }
    return true;
  }

  private String statusMessagePrefix() {
    return getCustomName()
      + "$"
      + hashCode()
      + "|"
      + ((m_Filter instanceof OptionHandler && Utils.joinOptions(
        ((OptionHandler) m_Filter).getOptions()).length() > 0) ? Utils
        .joinOptions(((OptionHandler) m_Filter).getOptions()) + "|" : "");
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy