Spec-Zone .ru
спецификации, руководства, описания, API
|
001/* 002 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. Oracle designates this 008 * particular file as subject to the "Classpath" exception as provided 009 * by Oracle in the LICENSE file that accompanied this code. 010 * 011 * This code is distributed in the hope that it will be useful, but WITHOUT 012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 014 * version 2 for more details (a copy is included in the LICENSE file that 015 * accompanied this code). 016 * 017 * You should have received a copy of the GNU General Public License version 018 * 2 along with this work; if not, write to the Free Software Foundation, 019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 020 * 021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 022 * or visit www.oracle.com if you need additional information or have any 023 * questions. 024 */ 025 026package javafx.event; 027 028// PENDING_DOC_REVIEW 029 030import java.io.InvalidObjectException; 031import java.io.ObjectStreamException; 032import java.io.Serializable; 033import java.util.ArrayList; 034import java.util.Deque; 035import java.util.Iterator; 036import java.util.LinkedList; 037import java.util.List; 038import java.util.Set; 039import java.util.WeakHashMap; 040 041/** 042 * This class represents a specific event type associated with an {@code Event}. 043 * <p> 044 * Event types form a hierarchy with the {@link EventType#ROOT} (equals to 045 * {@link Event#ANY}) as its root. This is useful in event filter / handler 046 * registration where a single event filter / handler can be registered to a 047 * super event type and will be receiving its sub type events as well. 048 * Note that you cannot construct two different EventType objects with the same 049 * name and parent. 050 * 051 * <p> 052 * <b>Note about deserialization</b>: All EventTypes that are going to be deserialized 053 * (e.g. as part of {@link Event} deserialization), need to exist at the time of 054 * deserialization. Deserialization of EventType will not create new EventType 055 * objects. 056 * 057 * @param <T> the event class to which this type applies 058 */ 059public final class EventType<T extends Event> implements Serializable{ 060 061 /** 062 * The root event type. All other event types are either direct or 063 * indirect sub types of it. It is also the only event type which 064 * has its super event type set to {@code null}. 065 */ 066 public static final EventType<Event> ROOT = 067 new EventType<Event>("EVENT", null); 068 069 private WeakHashMap<EventType<? extends T>, Void> subTypes; 070 071 private final EventType<? super T> superType; 072 073 private final String name; 074 075 /** 076 * Constructs a new {@code EventType} with the {@code EventType.ROOT} as its 077 * super type and the name set to {@code null}. 078 * @deprecated Do not use this constructor, as only one such EventType can exist 079 */ 080 @Deprecated 081 public EventType() { 082 this(ROOT, null); 083 } 084 085 /** 086 * Constructs a new {@code EventType} with the specified name and the 087 * {@code EventType.ROOT} as its super type. 088 * 089 * @param name the name 090 * @throws IllegalArgumentException if an EventType with the same name and 091 * {@link EventType#ROOT}/{@link Event#ANY} as parent 092 */ 093 public EventType(final String name) { 094 this(ROOT, name); 095 } 096 097 /** 098 * Constructs a new {@code EventType} with the specified super type and 099 * the name set to {@code null}. 100 * 101 * @param superType the event super type 102 * @throws IllegalArgumentException if an EventType with "null" name and 103 * under this supertype exists 104 */ 105 public EventType(final EventType<? super T> superType) { 106 this(superType, null); 107 } 108 109 /** 110 * Constructs a new {@code EventType} with the specified super type and 111 * name. 112 * 113 * @param superType the event super type 114 * @param name the name 115 * @throws IllegalArgumentException if an EventType with the same name and 116 * superType exists 117 */ 118 public EventType(final EventType<? super T> superType, 119 final String name) { 120 if (superType == null) { 121 throw new NullPointerException( 122 "Event super type must not be null!"); 123 } 124 125 this.superType = superType; 126 this.name = name; 127 superType.register(this); 128 } 129 130 /** 131 * Internal constructor that skips various checks 132 */ 133 EventType(final String name, 134 final EventType<? super T> superType) { 135 this.superType = superType; 136 this.name = name; 137 if (superType != null) { 138 if (superType.subTypes != null) { 139 for (Iterator i = superType.subTypes.keySet().iterator(); i.hasNext();) { 140 EventType t = (EventType) i.next(); 141 if (name == null && t.name == null || (name != null && name.equals(t.name))) { 142 i.remove(); 143 } 144 } 145 } 146 superType.register(this); 147 } 148 } 149 150 /** 151 * Gets the super type of this event type. The returned value is 152 * {@code null} only for the {@code EventType.ROOT}. 153 * 154 * @return the super type 155 */ 156 public final EventType<? super T> getSuperType() { 157 return superType; 158 } 159 160 /** 161 * Gets the name of this event type. 162 * 163 * @return the name 164 */ 165 public final String getName() { 166 return name; 167 } 168 169 /** 170 * Returns a string representation of this {@code EventType} object. 171 * @return a string representation of this {@code EventType} object. 172 */ 173 @Override 174 public String toString() { 175 return (name != null) ? name : super.toString(); 176 } 177 178 private void register(javafx.event.EventType<? extends T> subType) { 179 if (subTypes == null) { 180 subTypes = new WeakHashMap<EventType<? extends T>, Void>(); 181 } 182 for (EventType<? extends T> t : subTypes.keySet()) { 183 if (((t.name == null && subType.name == null) || (t.name != null && t.name.equals(subType.name)))) { 184 throw new IllegalArgumentException("EventType \"" + subType + "\"" 185 + "with parent \"" + subType.getSuperType()+"\" already exists"); 186 } 187 } 188 subTypes.put(subType, null); 189 } 190 191 private Object writeReplace() throws ObjectStreamException { 192 Deque<String> path = new LinkedList<String>(); 193 EventType<?> t = this; 194 while (t != ROOT) { 195 path.addFirst(t.name); 196 t = t.superType; 197 } 198 return new EventTypeSerialization(new ArrayList<String>(path)); 199 } 200 201 static class EventTypeSerialization implements Serializable { 202 private List<String> path; 203 204 public EventTypeSerialization(List<String> path) { 205 this.path = path; 206 } 207 208 private Object readResolve() throws ObjectStreamException { 209 EventType t = ROOT; 210 for (int i = 0; i < path.size(); ++i) { 211 String p = path.get(i); 212 if (t.subTypes != null) { 213 EventType s = findSubType(t.subTypes.keySet(), p); 214 if (s == null) { 215 throw new InvalidObjectException("Cannot find event type \"" + p + "\" (of " + t + ")"); 216 } 217 t = s; 218 } else { 219 throw new InvalidObjectException("Cannot find event type \"" + p + "\" (of " + t + ")"); 220 } 221 } 222 return t; 223 } 224 225 private EventType findSubType(Set<EventType> subTypes, String name) { 226 for (EventType t : subTypes) { 227 if (((t.name == null && name == null) || (t != null && t.name.equals(name)))) { 228 return t; 229 } 230 } 231 return null; 232 } 233 234 } 235}