Package org.olat.core.util.event

Source Code of org.olat.core.util.event.AbstractEventBus

package org.olat.core.util.event;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import org.olat.core.id.Identity;
import org.olat.core.id.OLATResourceable;
import org.olat.core.logging.OLog;
import org.olat.core.logging.Tracing;
import org.olat.core.util.event.businfo.BusListenerInfo;

/**
* abstract class for common services of the system bus
* @author Felix Jost
*/
public abstract class AbstractEventBus implements EventBus {

  private Map<String, EventAgency> infocenter;
  private Map<String, EventAgency> typeInfocenter;
  private OLog log = Tracing.createLoggerFor(this.getClass());

  public AbstractEventBus() {
    infocenter = new HashMap<String, EventAgency>();
    typeInfocenter = new HashMap<String, EventAgency>();
  }

  public void registerFor(GenericEventListener gel, Identity identity, OLATResourceable ores) {
    EventAgency ea = getEventAgencyFor(ores);
    ea.addListener(gel, identity);
  }

  public void deregisterFor(GenericEventListener gel, OLATResourceable ores) {
    EventAgency ea = getEventAgencyFor(ores);
    ea.removeListener(gel);
  }

  /**
   * @return the listening names on a resource - only use for admin purposes!
   */
  public Set getListeningIdentityNamesFor(OLATResourceable ores) {
    EventAgency ea = getEventAgencyFor(ores);
    Set s = ea.getListeningIdentityNames();
    return s;
  }

  public abstract int getListeningIdentityCntFor(OLATResourceable ores);
 
  public abstract void fireEventToListenersOf(MultiUserEvent event, OLATResourceable ores);
 
  /**
   * fires events to registered listeners of generic events.
   * To see all events set this class and also DefaultController and Component to debug.
   * @param event
   * @param ores
   */
  protected void doFire(MultiUserEvent event, OLATResourceable ores) {
    Long oresId = ores.getResourceableId();
    String typeName = ores.getResourceableTypeName();

    // 1. fire to all instance listeners
    if (oresId != null) {
      // fire event to all id - listeners
     
      //try to avoid synchronize on infocenter over next two codelines
      //see OLAT-3681 -
      EventAgency ea = getEventAgencyFor(typeName, oresId);//synchronizes shortly on infocenter
      ea.fireEvent(event);//synchronizes short on listeners but only to copy
    }
   
    //try to avoid synchronize on infocenter over next two codelines
    //see OLAT-3681
    // 2. fire event to all type - listeners
    EventAgency tea = getEventAgencyFor(typeName, null);
    if (log.isDebug()) log.debug("Generic Event from: "+typeName+": of type: "+event.getClass().getName());
    tea.fireEvent(event);//synchronizes short on listeners but only to copy
  }
 
  /**
   * used only for monitoring purposes
   */
  public Map<String, EventAgency> getUnmodifiableInfoCenter() {
    synchronized (infocenter) {  //o_clusterOK by:fj
      Map<String, EventAgency> all = new HashMap<String, EventAgency>(infocenter.size() + typeInfocenter.size());
      all.putAll(infocenter);
      all.putAll(typeInfocenter);
      return all;
    }
  }
 
  protected BusListenerInfo createBusListenerInfo() {
    BusListenerInfo bii = new BusListenerInfo();
    synchronized(infocenter) { // o_clusterOK by:fj: extract quickly so that we can later serialize and send across the wire. data affects only one vm.
      // for all types: the name of the type + "::"+ the id (integer) is used as key
      for (Entry<String, EventAgency> entry: infocenter.entrySet()) {
        String derivedOres = entry.getKey();
        int cnt = entry.getValue().getListenerCount();
        // only add those with at least one current listener. Telling that a resource has no listeners is unneeded since we update
        // the whole table on each clusterInfoEvent (cluster:: could be improved by only sending the delta of listeners)
        if (cnt > 0) bii.addEntry(derivedOres, cnt);
      }
      // for all types: the name of the type is used as key
      for (Entry<String, EventAgency> entry: typeInfocenter.entrySet()) {
        String derivedOres = entry.getKey();
        int cnt = entry.getValue().getListenerCount();
        if (cnt > 0) bii.addEntry(derivedOres, cnt);
      }
    }
    return bii;
  }

  private EventAgency getEventAgencyFor(OLATResourceable ores) {
    Long oresId = ores.getResourceableId();
    String typeName = ores.getResourceableTypeName();
    return getEventAgencyFor(typeName, oresId);
  }

  private EventAgency getEventAgencyFor(String typeName, Long oresId) {
    EventAgency ea;
    synchronized (infocenter) { 
      //o_clusterOK by:fj for cluster: clustereventbus is async vm to vm, and
      // here we only the eventagency of one vm need to be synchronized
      if (oresId == null) {
        // return the eventagency which listens to all events with the type of
        // the ores
        ea = typeInfocenter.get(typeName);
        if (ea == null) { // we are the first listener -> create an agency
          ea = new EventAgency();
          typeInfocenter.put(typeName, ea);
        }
      } else {
        // type and id
        String oresStr = typeName + "::" + oresId.toString();
        ea = infocenter.get(oresStr);
        if (ea == null) { // we are the first listener
          ea = new EventAgency();
          infocenter.put(oresStr, ea);
        }
      }
    }
    return ea;
  }
 
  public String toString() {
   
    if (log.isDebug()) {
      int totalListenerCount = 0;
      for (Entry<String, EventAgency> entry: getUnmodifiableInfoCenter().entrySet()) {
        EventAgency eventAgency = entry.getValue();
        int listenerCount = eventAgency.getListenerCount();
        //if (listenerCount > 0)
        //System.out.println("TEST AbstractEventBus  derivedOres(key)=" + entry.getKey() + "  listenerCount=" + listenerCount);
        totalListenerCount = totalListenerCount + listenerCount;
      }
      return "AbstractEventBus : #totalListenerCount=" + totalListenerCount + "   #EventAgency of infocenter=" + infocenter.size() + " #EventAgency of  typeInfocenter=" + typeInfocenter.size();
    }
    return "Enable debugging to see number of listeners";
  }

}
TOP

Related Classes of org.olat.core.util.event.AbstractEventBus

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.