/**
  * Delivers the event to the registered event listeners for the type
  * specified by the event from the subject.
  * If a listeners is an object fire attempts to invoke the methods
  * defined by concatenating 'on' with the id of the source object
  * and the type of the method. For example if:
  *     the source id = test
  *     the type of ONVALUECHANGE
  * the method name would be -> onTestChange
  * If that method does not exist and the listener is an instanceof
  * ZFormElementEventListenerInterface the general handleEvent is
  * invoked.
  * Finally if the object listener is a string and a callable the
  * function is invoked with the event as an argument
  *
  * @return boolean true no listeners found or the the result of
  * invoking the listeners method/function.
  */
 public function fire()
 {
     $listeners = $this->_source->getEventListeners($this->_type);
     if ($listeners) {
         foreach ($listeners as $listener) {
             $methodName = 'on' . ucfirst($this->_source->getID()) . $this->_type;
             /**
              * @todo check visibility - method_exists() returns true on priv/prot as well
              */
             if (is_object($listener)) {
                 if (is_callable(array($listener, $methodName))) {
                     return $listener->{$methodName}($this);
                 } else {
                     if ($listener instanceof ZFormElementEventListenerInterface) {
                         return $listener->handleEvent($this);
                     } else {
                         throw new ZFormElementException("Event handler not found for ");
                     }
                 }
             } elseif (is_string($listener) && is_callable($listener)) {
                 // @todo can this work?
                 return $listener($this);
             }
         }
     }
     return true;
 }