1.1 --- a/emul/compact/src/main/java/java/beans/ChangeListenerMap.java Tue Feb 26 14:55:55 2013 +0100
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,248 +0,0 @@
1.4 -/*
1.5 - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
1.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
1.7 - *
1.8 - * This code is free software; you can redistribute it and/or modify it
1.9 - * under the terms of the GNU General Public License version 2 only, as
1.10 - * published by the Free Software Foundation. Oracle designates this
1.11 - * particular file as subject to the "Classpath" exception as provided
1.12 - * by Oracle in the LICENSE file that accompanied this code.
1.13 - *
1.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
1.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1.17 - * version 2 for more details (a copy is included in the LICENSE file that
1.18 - * accompanied this code).
1.19 - *
1.20 - * You should have received a copy of the GNU General Public License version
1.21 - * 2 along with this work; if not, write to the Free Software Foundation,
1.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
1.23 - *
1.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
1.25 - * or visit www.oracle.com if you need additional information or have any
1.26 - * questions.
1.27 - */
1.28 -package java.beans;
1.29 -
1.30 -import java.util.ArrayList;
1.31 -import java.util.Collections;
1.32 -import java.util.EventListener;
1.33 -import java.util.EventListenerProxy;
1.34 -import java.util.HashMap;
1.35 -import java.util.List;
1.36 -import java.util.Map;
1.37 -import java.util.Map.Entry;
1.38 -import java.util.Set;
1.39 -import org.apidesign.bck2brwsr.emul.lang.System;
1.40 -
1.41 -/**
1.42 - * This is an abstract class that provides base functionality
1.43 - * for the {@link PropertyChangeSupport PropertyChangeSupport} class
1.44 - * and the {@link VetoableChangeSupport VetoableChangeSupport} class.
1.45 - *
1.46 - * @see PropertyChangeListenerMap
1.47 - * @see VetoableChangeListenerMap
1.48 - *
1.49 - * @author Sergey A. Malenkov
1.50 - */
1.51 -abstract class ChangeListenerMap<L extends EventListener> {
1.52 - private Map<String, L[]> map;
1.53 -
1.54 - /**
1.55 - * Creates an array of listeners.
1.56 - * This method can be optimized by using
1.57 - * the same instance of the empty array
1.58 - * when {@code length} is equal to {@code 0}.
1.59 - *
1.60 - * @param length the array length
1.61 - * @return an array with specified length
1.62 - */
1.63 - protected abstract L[] newArray(int length);
1.64 -
1.65 - /**
1.66 - * Creates a proxy listener for the specified property.
1.67 - *
1.68 - * @param name the name of the property to listen on
1.69 - * @param listener the listener to process events
1.70 - * @return a proxy listener
1.71 - */
1.72 - protected abstract L newProxy(String name, L listener);
1.73 -
1.74 - /**
1.75 - * Adds a listener to the list of listeners for the specified property.
1.76 - * This listener is called as many times as it was added.
1.77 - *
1.78 - * @param name the name of the property to listen on
1.79 - * @param listener the listener to process events
1.80 - */
1.81 - public final synchronized void add(String name, L listener) {
1.82 - if (this.map == null) {
1.83 - this.map = new HashMap<String, L[]>();
1.84 - }
1.85 - L[] array = this.map.get(name);
1.86 - int size = (array != null)
1.87 - ? array.length
1.88 - : 0;
1.89 -
1.90 - L[] clone = newArray(size + 1);
1.91 - clone[size] = listener;
1.92 - if (array != null) {
1.93 - System.arraycopy(array, 0, clone, 0, size);
1.94 - }
1.95 - this.map.put(name, clone);
1.96 - }
1.97 -
1.98 - /**
1.99 - * Removes a listener from the list of listeners for the specified property.
1.100 - * If the listener was added more than once to the same event source,
1.101 - * this listener will be notified one less time after being removed.
1.102 - *
1.103 - * @param name the name of the property to listen on
1.104 - * @param listener the listener to process events
1.105 - */
1.106 - public final synchronized void remove(String name, L listener) {
1.107 - if (this.map != null) {
1.108 - L[] array = this.map.get(name);
1.109 - if (array != null) {
1.110 - for (int i = 0; i < array.length; i++) {
1.111 - if (listener.equals(array[i])) {
1.112 - int size = array.length - 1;
1.113 - if (size > 0) {
1.114 - L[] clone = newArray(size);
1.115 - System.arraycopy(array, 0, clone, 0, i);
1.116 - System.arraycopy(array, i + 1, clone, i, size - i);
1.117 - this.map.put(name, clone);
1.118 - }
1.119 - else {
1.120 - this.map.remove(name);
1.121 - if (this.map.isEmpty()) {
1.122 - this.map = null;
1.123 - }
1.124 - }
1.125 - break;
1.126 - }
1.127 - }
1.128 - }
1.129 - }
1.130 - }
1.131 -
1.132 - /**
1.133 - * Returns the list of listeners for the specified property.
1.134 - *
1.135 - * @param name the name of the property
1.136 - * @return the corresponding list of listeners
1.137 - */
1.138 - public final synchronized L[] get(String name) {
1.139 - return (this.map != null)
1.140 - ? this.map.get(name)
1.141 - : null;
1.142 - }
1.143 -
1.144 - /**
1.145 - * Sets new list of listeners for the specified property.
1.146 - *
1.147 - * @param name the name of the property
1.148 - * @param listeners new list of listeners
1.149 - */
1.150 - public final void set(String name, L[] listeners) {
1.151 - if (listeners != null) {
1.152 - if (this.map == null) {
1.153 - this.map = new HashMap<String, L[]>();
1.154 - }
1.155 - this.map.put(name, listeners);
1.156 - }
1.157 - else if (this.map != null) {
1.158 - this.map.remove(name);
1.159 - if (this.map.isEmpty()) {
1.160 - this.map = null;
1.161 - }
1.162 - }
1.163 - }
1.164 -
1.165 - /**
1.166 - * Returns all listeners in the map.
1.167 - *
1.168 - * @return an array of all listeners
1.169 - */
1.170 - public final synchronized L[] getListeners() {
1.171 - if (this.map == null) {
1.172 - return newArray(0);
1.173 - }
1.174 - List<L> list = new ArrayList<L>();
1.175 -
1.176 - L[] listeners = this.map.get(null);
1.177 - if (listeners != null) {
1.178 - for (L listener : listeners) {
1.179 - list.add(listener);
1.180 - }
1.181 - }
1.182 - for (Entry<String, L[]> entry : this.map.entrySet()) {
1.183 - String name = entry.getKey();
1.184 - if (name != null) {
1.185 - for (L listener : entry.getValue()) {
1.186 - list.add(newProxy(name, listener));
1.187 - }
1.188 - }
1.189 - }
1.190 - return list.toArray(newArray(list.size()));
1.191 - }
1.192 -
1.193 - /**
1.194 - * Returns listeners that have been associated with the named property.
1.195 - *
1.196 - * @param name the name of the property
1.197 - * @return an array of listeners for the named property
1.198 - */
1.199 - public final L[] getListeners(String name) {
1.200 - if (name != null) {
1.201 - L[] listeners = get(name);
1.202 - if (listeners != null) {
1.203 - return listeners.clone();
1.204 - }
1.205 - }
1.206 - return newArray(0);
1.207 - }
1.208 -
1.209 - /**
1.210 - * Indicates whether the map contains
1.211 - * at least one listener to be notified.
1.212 - *
1.213 - * @param name the name of the property
1.214 - * @return {@code true} if at least one listener exists or
1.215 - * {@code false} otherwise
1.216 - */
1.217 - public final synchronized boolean hasListeners(String name) {
1.218 - if (this.map == null) {
1.219 - return false;
1.220 - }
1.221 - L[] array = this.map.get(null);
1.222 - return (array != null) || ((name != null) && (null != this.map.get(name)));
1.223 - }
1.224 -
1.225 - /**
1.226 - * Returns a set of entries from the map.
1.227 - * Each entry is a pair consisted of the property name
1.228 - * and the corresponding list of listeners.
1.229 - *
1.230 - * @return a set of entries from the map
1.231 - */
1.232 - public final Set<Entry<String, L[]>> getEntries() {
1.233 - return (this.map != null)
1.234 - ? this.map.entrySet()
1.235 - : Collections.<Entry<String, L[]>>emptySet();
1.236 - }
1.237 -
1.238 - /**
1.239 - * Extracts a real listener from the proxy listener.
1.240 - * It is necessary because default proxy class is not serializable.
1.241 - *
1.242 - * @return a real listener
1.243 - */
1.244 - public final L extract(L listener) {
1.245 - while (listener instanceof EventListenerProxy) {
1.246 - EventListenerProxy<L> proxy = (EventListenerProxy<L>) listener;
1.247 - listener = proxy.getListener();
1.248 - }
1.249 - return listener;
1.250 - }
1.251 -}