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

com.tangosol.util.MapEvent Maven / Gradle / Ivy

There is a newer version: 24.09
Show newest version
/*
 * Copyright (c) 2000, 2024, Oracle and/or its affiliates.
 *
 * Licensed under the Universal Permissive License v 1.0 as shown at
 * https://oss.oracle.com/licenses/upl.
 */

package com.tangosol.util;

import com.tangosol.internal.tracing.Span;
import com.tangosol.internal.tracing.TracingHelper;

import com.tangosol.io.ClassLoaderAware;

import com.tangosol.io.pof.PofReader;
import com.tangosol.io.pof.PofWriter;
import com.tangosol.io.pof.PortableObject;

import java.io.IOException;

import java.util.EventListener;
import java.util.EventObject;
import java.util.Map;

import javax.json.bind.annotation.JsonbProperty;

import static com.tangosol.net.cache.ReadWriteBackingMap.BIN_ERASE_PENDING;


/**
* An event which indicates that the content of a map has changed:
* 
    *
  • an entry has been added *
  • an entry has been removed *
  • an entry has been changed *
* A MapEvent object is sent as an argument to the MapListener interface * methods. Null values may be provided for the old and the new values. * * @param the type of the Map entry key * @param the type of the Map entry value * * @author gg 2002.02.11 */ public class MapEvent extends EventObject implements PortableObject { /** * Default constructor for serialization. */ public MapEvent() { // We cannot pass a null source to the super class constructor // but the source is transient and will not have been serialized // so we pass a dummy source to the constructor and then set it // to null super(new Object()); source = null; } /** * Constructs a new MapEvent. * * @param map the ObservableMap object that fired the event * @param nId this event's id, one of {@link #ENTRY_INSERTED}, * {@link #ENTRY_UPDATED} or {@link #ENTRY_DELETED} * @param oKey the key into the map * @param oValueOld the old value (for update and delete events) * @param oValueNew the new value (for insert and update events) */ public MapEvent(ObservableMap map, int nId, K oKey, V oValueOld, V oValueNew) { super(map); // write-behind remove entries have the fixed value BIN_ERASE_PENDING // until the erase call is successful if (nId == MapEvent.ENTRY_UPDATED && BIN_ERASE_PENDING.equals(oValueNew)) { m_nId = MapEvent.ENTRY_DELETED; } else { m_nId = nId; } m_oKey = oKey; m_oValueOld = oValueOld; m_oValueNew = oValueNew; } /** * Return an ObservableMap object on which this event has actually * occurred. * * @return an ObservableMap object */ public ObservableMap getMap() { // IMPORTANT: The return type here must be raw as we transformers // may have changed the key and value types. return (ObservableMap) getSource(); } /** * Return this event's id. The event id is one of the ENTRY_* * enumerated constants. * * @return an id */ public int getId() { return m_nId; } /** * Return a key associated with this event. * * @return a key */ public K getKey() { return m_oKey; } /** * Return an old value associated with this event. *

* The old value represents a value deleted from or updated in a map. * It is always null for "insert" notifications. * * @return an old value */ public V getOldValue() { return m_oValueOld; } /** * Return a new value associated with this event. *

* The new value represents a new value inserted into or updated in * a map. It is always null for "delete" notifications. * * @return a new value */ public V getNewValue() { return m_oValueNew; } /** * Return a Map Entry that represents the state of the Entry before the * change occurred that generated this event. * * @return a Map Entry representing the pre-event state of the Entry * * @since Coherence 3.6 */ public Map.Entry getOldEntry() { return new SimpleMapEntry() { public K getKey() { return MapEvent.this.getKey(); } public V getValue() { return MapEvent.this.getOldValue(); } public V setValue(V oValue) { throw new UnsupportedOperationException(); } }; } /** * Return a Map Entry that represents the state of the Entry after the * change occurred that generated this event. * * @return a Map Entry representing the post-event state of the Entry * * @since Coherence 3.6 */ public Map.Entry getNewEntry() { return new SimpleMapEntry() { public K getKey() { return MapEvent.this.getKey(); } public V getValue() { return MapEvent.this.getNewValue(); } public V setValue(V oValue) { throw new UnsupportedOperationException(); } }; } /** * Determine whether this event is an insert event. * * @return {@code true} if this event is an insert event */ public boolean isInsert() { return m_nId == ENTRY_INSERTED; } /** * Determine whether this event is an update event. * * @return {@code true} if this event is an update event */ public boolean isUpdate() { return m_nId == ENTRY_UPDATED; } /** * Determine whether this event is a delete event. * * @return {@code true} if this event is a delete event */ public boolean isDelete() { return m_nId == ENTRY_DELETED; } // ----- PortableObject methods ----------------------------------------- @Override public void readExternal(PofReader in) throws IOException { m_nId = in.readInt(0); m_oKey = in.readObject(1); m_oValueOld = in.readObject(2); m_oValueNew = in.readObject(3); } @Override public void writeExternal(PofWriter out) throws IOException { out.writeInt(0, m_nId); out.writeObject(1, m_oKey); out.writeObject(2, m_oValueOld); out.writeObject(3, m_oValueNew); } // ----- Object methods ------------------------------------------------- /** * Return a String representation of this MapEvent object. * * @return a String representation of this MapEvent object */ public String toString() { String sEvt = getClass().getName(); String sSrc = getSource().getClass().getName(); return sEvt.substring(sEvt.lastIndexOf('.') + 1) + '{' + sSrc.substring(sSrc.lastIndexOf('.') + 1) + getDescription() + '}'; } // ----- helpers ------------------------------------------------------ /** * Dispatch this event to the specified listeners collection. *

* This call is equivalent to *

    *   dispatch(listeners, true);
    * 
* * @param listeners the listeners collection * * @throws ClassCastException if any of the targets is not * an instance of MapListener interface */ public void dispatch(Listeners listeners) { dispatch(listeners, true); } /** * Dispatch this event to the specified listeners collection. * * @param listeners the listeners collection * @param fStrict if true then any RuntimeException thrown by event * handlers stops all further event processing and the * exception is re-thrown; if false then all exceptions * are logged and the process continues * * @throws ClassCastException if any of the targets is not * an instance of MapListener interface */ public void dispatch(Listeners listeners, boolean fStrict) { if (listeners != null) { EventListener[] targets = listeners.listeners(); Span span = TracingHelper.getActiveSpan(); if (span != null) { span.setMetadata(Span.Metadata.LISTENER_CLASSES.key(), listeners.getListenerClassNames()); } for (int i = targets.length; --i >= 0; ) { MapListener target = (MapListener) targets[i]; try { if (shouldDispatch(target)) { dispatch(target); } } catch (RuntimeException e) { if (fStrict || Thread.currentThread().isInterrupted()) { throw e; } else { Base.err(e); } } } } } /** * Dispatch this event to the specified MapListener. * * @param listener the listener */ public void dispatch(MapListener listener) { Thread thread = Thread.currentThread(); ClassLoader loader = null; Object oSource = getSource(); // context class loader should be set to that of the source (cache) if (oSource instanceof ClassLoaderAware) { loader = thread.getContextClassLoader(); thread.setContextClassLoader( ((ClassLoaderAware) oSource).getContextClassLoader()); } try { if (shouldDispatch(listener)) { switch (getId()) { case MapEvent.ENTRY_INSERTED: listener.entryInserted((MapEvent) this); break; case MapEvent.ENTRY_UPDATED: listener.entryUpdated((MapEvent) this); break; case MapEvent.ENTRY_DELETED: listener.entryDeleted((MapEvent) this); break; } } } finally { if (loader != null) { thread.setContextClassLoader(loader); } } } /** * Return true if the provided {@link MapListener} should receive this * event. * * @param listener the MapListener to dispatch this event to * * @return true if the provided MapListener should receive the event */ protected boolean shouldDispatch(MapListener listener) { return true; } /** * Get the event's description. * * @return this event's description */ protected String getDescription() { switch (getId()) { case ENTRY_INSERTED: return " inserted: key=" + getKey() + ", value=" + getNewValue(); case ENTRY_UPDATED: return " updated: key=" + getKey() + ", old value=" + getOldValue() + ", new value=" + getNewValue(); case ENTRY_DELETED: return " deleted: key=" + getKey() + ", value=" + getOldValue(); default: throw new IllegalStateException(); } } /** * Convert an event ID into a human-readable string. * * @param nId an event ID, one of the ENTRY_* enumerated values * * @return a corresponding human-readable string, for example "inserted" */ public static String getDescription(int nId) { switch (nId) { case ENTRY_INSERTED: return "inserted"; case ENTRY_UPDATED: return "updated"; case ENTRY_DELETED: return "deleted"; default: return "'; } } // ----- constants ------------------------------------------------------ /** * This event indicates that an entry has been added to the map. */ public static final int ENTRY_INSERTED = 1; /** * This event indicates that an entry has been updated in the map. */ public static final int ENTRY_UPDATED = 2; /** * This event indicates that an entry has been removed from the map. */ public static final int ENTRY_DELETED = 3; // ----- data members --------------------------------------------------- /** * The event's id. */ @JsonbProperty("id") protected int m_nId; /** * A key. */ @JsonbProperty("key") protected K m_oKey; /** * A previous value. May be null if not known. */ @JsonbProperty(value = "oldValue", nillable = true) protected V m_oValueOld; /** * A new value. May be null if not known. */ @JsonbProperty(value = "newValue", nillable = true) protected V m_oValueNew; }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy