class ObserverCallBack implements EventListener {

  private Object callback = null;
  private String scriptRunnerType = null;

  /**
   * setup a callback to be used on the Java API level
   <pre>
   * // example (called when image appears):
   * aRegion.onAppear(anImageOrPattern,
   *   new ObserverCallBack() {
   *     appeared(ObserveEvent e) {
   *       // do something
   *     }
   *   }
   * );
   * </pre>
   *    */
  public ObserverCallBack() {
  }


  /**
   * INTERNAL: callbacks from Jython or JRuby
   * @param callback funtion to call
   * @param obsType observer type
   */
  public ObserverCallBack(Object callback, ObserveEvent.Type obsType) {
    this.callback = callback;
    this.obsType = obsType;
    scriptRunnerType = callback.getClass().getName();
  }

  /**
   * INTERNAL USE
   * @param givenType observer type
   */
  public void setType(ObserveEvent.Type givenType) {
    obsType = givenType;
  }

  /**
   * INTERNAL USE
   * @return observer type
   */
  public ObserveEvent.Type getType() {
    return obsType;
  }

  private ObserveEvent.Type obsType = ObserveEvent.Type.GENERIC;

  /**
   * to be overwritten to handle appear events
   * @param event that happened
   */
  public void appeared(ObserveEvent event) {
    if (scriptRunnerType != null && ObserveEvent.Type.APPEAR.equals(obsType)) {
      run(event);
    }
  }

  /**
   * to be overwritten to handle vanish events
   * @param event that happened
   */
  public void vanished(ObserveEvent event) {
    if (scriptRunnerType != null && ObserveEvent.Type.VANISH.equals(obsType)) {
      run(event);
    }
  }

  /**
   * to be overwritten to handle changed events
   * @param event that happened
   */
  public void changed(ObserveEvent event) {
    if (scriptRunnerType != null && ObserveEvent.Type.CHANGE.equals(obsType)) {
      run(event);
    }
  }

  /**
   * to be overwritten to handle FindFailed events
   * @param event that happened
   */
  public void findfailed(ObserveEvent event) {
    if (scriptRunnerType != null && ObserveEvent.Type.FINDFAILED.equals(obsType)) {
      run(event);
    }
  }

  /**
   * to be overwritten to handle image missing events
   * @param event that happened
   */
  public void missing(ObserveEvent event) {
    if (scriptRunnerType != null && ObserveEvent.Type.MISSING.equals(obsType)) {
      run(event);
    }
  }

  /**
   * to be overwritten to handle generic events
   * @param event that happened
   */
  public void happened(ObserveEvent event) {
    if (scriptRunnerType != null && ObserveEvent.Type.GENERIC.equals(obsType)) {
      run(event);
    }
  }

  private void run(ObserveEvent e) {<FILL_FUNCTION_BODY>}
}

    Object[] args = new Object[]{callback, e};
    if (scriptRunnerType != null) {
      if (!(Boolean) Commons.runFunctionScriptingSupport(scriptRunnerType, "runObserveCallback", args)) {
        Debug.error("ObserverCallBack: problem with scripting handler: %s\n%s",
                scriptRunnerType, callback.getClass().getName());
      }
    }
  
<no_super_class>