001: /*
002: ItsNat Java Web Application Framework
003: Copyright (C) 2007 Innowhere Software Services S.L., Spanish Company
004: Author: Jose Maria Arranz Santamaria
005:
006: This program is free software: you can redistribute it and/or modify
007: it under the terms of the GNU Affero General Public License as published by
008: the Free Software Foundation, either version 3 of the License, or
009: (at your option) any later version. See the GNU Affero General Public
010: License for more details. See the copy of the GNU Affero General Public License
011: included in this program. If not, see <http://www.gnu.org/licenses/>.
012: */
013:
014: package org.itsnat.impl.core.event.fromserv;
015:
016: import java.util.ArrayList;
017: import org.itsnat.core.ItsNatException;
018: import org.itsnat.impl.core.ItsNatDocumentImpl;
019: import org.itsnat.impl.core.event.EventInternal;
020: import org.itsnat.impl.core.event.fromserv.dom.ServerDOMEventImpl;
021: import org.itsnat.impl.core.event.fromserv.domext.ServerContinueEventImpl;
022: import org.itsnat.impl.core.event.fromserv.domext.ServerDOMExtensionEventImpl;
023: import org.itsnat.impl.core.event.fromserv.domext.ServerUserEventImpl;
024: import org.itsnat.impl.core.listener.DOMBasedEventListenerRegistryByTargetTooImpl;
025: import org.itsnat.impl.core.listener.DOMBasedEventListenerRegistryImpl;
026: import org.w3c.dom.DOMException;
027: import org.w3c.dom.Node;
028: import org.w3c.dom.events.Event;
029: import org.w3c.dom.events.EventException;
030: import org.w3c.dom.events.EventListener;
031: import org.w3c.dom.events.EventTarget;
032:
033: /**
034: *
035: * @author jmarranz
036: */
037: public abstract class ServerDOMBasedEventImpl extends
038: ServerNormalEventImpl implements EventInternal {
039: protected EventTarget target;
040: protected String type;
041: protected boolean canBubble;
042: protected boolean cancelable;
043: protected long time = System.currentTimeMillis();
044: protected boolean stopPropagation = false;
045: protected boolean preventDefault = false;
046: protected short phase;
047: protected boolean initialized;
048:
049: /** Creates a new instance of ServerDOMBasedEventImpl */
050: public ServerDOMBasedEventImpl(ItsNatDocumentImpl itsNatDoc) {
051: super (itsNatDoc);
052: }
053:
054: public static Event createDOMBasedEvent(String eventGroup,
055: ItsNatDocumentImpl itsNatDoc) throws DOMException {
056: if (eventGroup.startsWith("itsnat:"))
057: return ServerDOMExtensionEventImpl.createDOMExtensionEvent(
058: eventGroup, itsNatDoc);
059: else
060: return ServerDOMEventImpl.createDOMEvent(eventGroup,
061: itsNatDoc);
062: }
063:
064: public void initEvent(String eventTypeArg, boolean canBubbleArg,
065: boolean cancelableArg) {
066: this .type = eventTypeArg;
067: this .canBubble = canBubbleArg;
068: this .cancelable = cancelableArg;
069:
070: this .initialized = true;
071: }
072:
073: public boolean isInitialized() {
074: return initialized;
075: }
076:
077: public void checkInitializedEvent() {
078: String type = getType();
079: if (!initialized || (type == null) || type.equals(""))
080: throw new EventException(
081: EventException.UNSPECIFIED_EVENT_TYPE_ERR,
082: "Unspecified event type");
083: }
084:
085: public EventTarget getTarget() {
086: return target;
087: }
088:
089: public void setTarget(EventTarget target) {
090: this .target = target;
091: }
092:
093: public String getType() {
094: return type;
095: }
096:
097: public boolean getBubbles() {
098: return canBubble;
099: }
100:
101: public boolean getCancelable() {
102: return cancelable;
103: }
104:
105: public long getTimeStamp() {
106: return time;
107: }
108:
109: public short getEventPhase() {
110: return phase;
111: }
112:
113: public void setEventPhase(short phase) {
114: this .phase = phase;
115: }
116:
117: public void stopPropagation() {
118: this .stopPropagation = true;
119: }
120:
121: public boolean getStopPropagation() {
122: return stopPropagation;
123: }
124:
125: public void setStopPropagation(boolean value) {
126: this .stopPropagation = value;
127: }
128:
129: public void preventDefault() {
130: this .preventDefault = true;
131: }
132:
133: public boolean getPreventDefault() {
134: return preventDefault;
135: }
136:
137: public void setPreventDefault(boolean value) {
138: this .preventDefault = value;
139: }
140:
141: public static boolean dispatchEventLocally(EventTarget target,
142: Event event) {
143: if (event == null)
144: return false;
145:
146: ServerDOMBasedEventImpl evt = (ServerDOMBasedEventImpl) event; // No valen los eventos que no hayan sido creados con el createDOMEvent público
147: evt.checkInitializedEvent();
148:
149: ItsNatDocumentImpl itsNatDoc = evt.getItsNatDocumentImpl();
150: DOMBasedEventListenerRegistryImpl registry;
151: if (evt instanceof ServerDOMEventImpl)
152: registry = itsNatDoc.getDOMEventListenerRegistry();
153: else if (evt instanceof ServerUserEventImpl)
154: registry = itsNatDoc.getUserEventListenerRegistry();
155: else if (evt instanceof ServerContinueEventImpl)
156: registry = itsNatDoc.getContinueEventListenerRegistry();
157: else
158: throw new ItsNatException("Event type is not supported:"
159: + event.getType()); // Por ahora no hay más casos
160:
161: return dispatchEventLocally(target, evt, registry);
162: }
163:
164: public static boolean dispatchEventLocally(EventTarget target,
165: ServerDOMBasedEventImpl evt,
166: DOMBasedEventListenerRegistryImpl registry) {
167: Node targetNode = (Node) target;
168:
169: evt.setTarget(target);
170: evt.setStopPropagation(false);
171: evt.setPreventDefault(false);
172:
173: // Guardamos los padres para evitar la interferencia que supone los cambios
174: // en el DOM al ejecutar los handlers.
175: boolean someoneCaptures = registry.getCapturingCount() > 0;
176:
177: ArrayList parentList = null;
178: if (someoneCaptures || evt.getBubbles()) {
179: parentList = new ArrayList();
180: Node current = targetNode.getParentNode();
181: while (current != null) {
182: parentList.add(current);
183: current = current.getParentNode();
184: }
185: }
186:
187: if (someoneCaptures) {
188: // Fase CAPTURING_PHASE, desde el más alto hasta el target
189: evt.setEventPhase(Event.CAPTURING_PHASE);
190: for (int i = parentList.size() - 1; i >= 0; i--) {
191: EventTarget currentTarget = (EventTarget) parentList
192: .get(i);
193: dispatchEventLocallyCurrentTarget(currentTarget, evt,
194: true, registry);
195:
196: if (evt.getStopPropagation())
197: return evt.getPreventDefault(); // Fin capturing
198: }
199: }
200:
201: evt.setEventPhase(Event.AT_TARGET);
202: dispatchEventLocallyCurrentTarget(target, evt, false, registry);
203:
204: if (evt.getStopPropagation())
205: return evt.getPreventDefault();
206:
207: if (evt.getBubbles()) {
208: evt.setEventPhase(Event.BUBBLING_PHASE);
209: for (int i = 0; i < parentList.size(); i++) {
210: EventTarget currentTarget = (EventTarget) parentList
211: .get(i);
212: dispatchEventLocallyCurrentTarget(currentTarget, evt,
213: false, registry);
214:
215: if (evt.getStopPropagation())
216: return evt.getPreventDefault(); // fin bubbling
217: }
218: }
219:
220: return evt.getPreventDefault();
221: }
222:
223: public static void dispatchEventLocallyCurrentTarget(
224: EventTarget currentTarget, ServerDOMBasedEventImpl evt,
225: boolean useCapture,
226: DOMBasedEventListenerRegistryImpl registry) {
227: evt.setCurrentTarget(currentTarget);
228: EventListener[] listeners = registry.getDOMBasedEventListeners(
229: currentTarget, evt.getType(), useCapture);
230: if (listeners == null)
231: return;
232:
233: // El array se ha creado nuevo, no hay problema de que al procesar los handlers se añadan o se quiten listeners, no nos enteraremos
234: // call listeners in the order in which they got registered
235: for (int i = 0; i < listeners.length; i++) {
236: EventListener listener = listeners[i];
237: listener.handleEvent(evt);
238: }
239: }
240: }
|