1 /*
   2  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.nashorn.internal.runtime;
  27 
  28 import java.util.Map;
  29 import java.util.WeakHashMap;
  30 
  31 /**
  32  * Helper class to manage property listeners and notification.
  33  */
  34 public class PropertyListenerManager implements PropertyListener {
  35 
  36     /** property listeners for this object. */
  37     private Map<PropertyListener,Boolean> listeners;
  38 
  39     // These counters are updated in debug mode
  40     private static int listenersAdded;
  41     private static int listenersRemoved;
  42 
  43     /**
  44      * @return the listenersAdded
  45      */
  46     public static int getListenersAdded() {
  47         return listenersAdded;
  48     }
  49 
  50     /**
  51      * @return the listenersRemoved
  52      */
  53     public static int getListenersRemoved() {
  54         return listenersRemoved;
  55     }
  56 
  57     // Property listener management methods
  58 
  59     /**
  60      * Add a property listener to this object.
  61      *
  62      * @param listener The property listener that is added.
  63      */
  64     public final void addPropertyListener(final PropertyListener listener) {
  65         if (listeners == null) {
  66             listeners = new WeakHashMap<>();
  67         }
  68 
  69         if (Context.DEBUG) {
  70             listenersAdded++;
  71         }
  72         listeners.put(listener, Boolean.TRUE);
  73     }
  74 
  75     /**
  76      * Remove a property listener from this object.
  77      *
  78      * @param listener The property listener that is removed.
  79      */
  80     public final void removePropertyListener(final PropertyListener listener) {
  81         if (listeners != null) {
  82             if (Context.DEBUG) {
  83                 listenersRemoved++;
  84             }
  85             listeners.remove(listener);
  86         }
  87     }
  88 
  89     /**
  90      * This method can be called to notify property addition to this object's listeners.
  91      *
  92      * @param object The ScriptObject to which property was added.
  93      * @param prop The property being added.
  94      */
  95     protected final void notifyPropertyAdded(final ScriptObject object, final Property prop) {
  96         if (listeners != null) {
  97             for (PropertyListener listener : listeners.keySet()) {
  98                 listener.propertyAdded(object, prop);
  99             }
 100         }
 101     }
 102 
 103     /**
 104      * This method can be called to notify property deletion to this object's listeners.
 105      *
 106      * @param object The ScriptObject from which property was deleted.
 107      * @param prop The property being deleted.
 108      */
 109     protected final void notifyPropertyDeleted(final ScriptObject object, final Property prop) {
 110         if (listeners != null) {
 111             for (PropertyListener listener : listeners.keySet()) {
 112                 listener.propertyDeleted(object, prop);
 113             }
 114         }
 115     }
 116 
 117     /**
 118      * This method can be called to notify property modification to this object's listeners.
 119      *
 120      * @param object The ScriptObject to which property was modified.
 121      * @param oldProp The old property being replaced.
 122      * @param newProp The new property that replaces the old property.
 123      */
 124     protected final void notifyPropertyModified(final ScriptObject object, final Property oldProp, final Property newProp) {
 125         if (listeners != null) {
 126             for (PropertyListener listener : listeners.keySet()) {
 127                 listener.propertyModified(object, oldProp, newProp);
 128             }
 129         }
 130     }
 131 
 132     // PropertyListener methods
 133 
 134     @Override
 135     public final void propertyAdded(final ScriptObject object, final Property prop) {
 136         notifyPropertyAdded(object, prop);
 137     }
 138 
 139     @Override
 140     public final void propertyDeleted(final ScriptObject object, final Property prop) {
 141         notifyPropertyDeleted(object, prop);
 142     }
 143 
 144     @Override
 145     public final void propertyModified(final ScriptObject object, final Property oldProp, final Property newProp) {
 146         notifyPropertyModified(object, oldProp, newProp);
 147     }
 148 }