001: /* SwingML
002: * Copyright (C) 2002 Robert Morris.
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the
016: * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
017: * Boston, MA 02111-1307, USA.
018: *
019: * Authors:
020: * Robert Morris <robertj@morris.net>
021: *
022: */
023:
024: package org.swingml.event;
025:
026: import java.util.*;
027:
028: import org.swingml.*;
029:
030: /**
031: *
032: * This class provides a cache of ExternalEvent implementations.
033: * When an ExternalEvent implementation implements the RetainedInMemory
034: * Interface and returns true from the retainInMemory() method, this class
035: * will create one instance and re-use for the lifetime of the current
036: * document. Once the document is released, the cache of objects is
037: * flushed.
038: *
039: * @author <a href="mailto:robertj@morris.net">Robert J. Morris</a>
040: */
041: public class ExternalEventManager {
042:
043: protected static Map documents = null;
044: protected static Map globalExternalEvents = null;
045:
046: /**
047: * This method forces all cached ExternalEvent instances to
048: * be released.
049: */
050: public static void flush() {
051: if (ExternalEventManager.globalExternalEvents != null) {
052: ExternalEventManager.globalExternalEvents.clear();
053: }
054:
055: if (ExternalEventManager.documents != null) {
056: ExternalEventManager.documents.clear();
057: }
058: }
059:
060: /**
061: * This method flushes the InvokableEvent cache associated
062: * with the referenced renderer parameter. This will release
063: * all InvokableEvent instances that were cached using
064: * RetainedInMemory.retainInMemory() == RetainedInMemory.MEM_DOCUMENT.
065: * Globally stored events are left intact. Events associated with
066: * other renderer instances are also left intact.
067: */
068: public static void flush(SwingMLRenderer aRenderer) {
069: if (ExternalEventManager.documents != null) {
070: if (ExternalEventManager.documents.containsKey(aRenderer)) {
071: ExternalEventManager.documents.remove(aRenderer);
072: }
073: }
074: }
075:
076: /**
077: * This method returns an instance of the InvokableEvent implementation
078: * as specified by the className argument. If the referenced class does not
079: * implement the InvokableEvent interface, a value of null is returned.
080: * If the referenced class also implements the RetainedInMemory interface
081: * and returns true for the retainInMemory() method, it will either retrieve
082: * an existing instance from static memory, or create a new instance and
083: * store it in static memory.
084: *
085: * @param className The name of the InvokableEvent implementation to instnatiate.
086: *
087: * @return A valid reference to the class described in the className argument.
088: */
089: public static InvokableEventHandler loadInvokableEvent(
090: SwingMLRenderer aRenderer, String aClassName,
091: String aFactoryClass) {
092: InvokableEventHandler theInvokableEvent = null;
093: Map theDocumentEvents = null;
094: try {
095: if (ExternalEventManager.globalExternalEvents == null) {
096: ExternalEventManager.globalExternalEvents = new HashMap(
097: 1);
098: }
099: if (ExternalEventManager.documents == null) {
100: ExternalEventManager.documents = new HashMap(1);
101: }
102: // Determine whether or not the class has been cached
103: // at the document-level of the referenced renderer
104: // instance.
105: if (ExternalEventManager.documents.containsKey(aRenderer)) {
106: theDocumentEvents = (Map) ExternalEventManager.documents
107: .get(aRenderer);
108: if (theDocumentEvents.containsKey(aClassName)) {
109: theInvokableEvent = (InvokableEventHandler) theDocumentEvents
110: .get(aClassName);
111: }
112: }
113: if (theInvokableEvent == null) {
114: if (ExternalEventManager.globalExternalEvents
115: .containsKey(aClassName)) {
116: theInvokableEvent = (InvokableEventHandler) ExternalEventManager.globalExternalEvents
117: .get(aClassName);
118: } else {
119: if (aFactoryClass == null) {
120: theInvokableEvent = (InvokableEventHandler) Class
121: .forName(aClassName).newInstance();
122: } else {
123: InvokableEventHandlerFactory factory = (InvokableEventHandlerFactory) Class
124: .forName(aFactoryClass).newInstance();
125: Class eventClass = Class.forName(aClassName);
126: theInvokableEvent = factory
127: .newEventHandler(eventClass);
128: }
129: if (theInvokableEvent instanceof RetainedInMemory) {
130: int theMemoryStyle = ((RetainedInMemory) theInvokableEvent)
131: .retainInMemory();
132: if (theMemoryStyle == RetainedInMemory.MEM_GLOBAL) {
133: ExternalEventManager.globalExternalEvents
134: .put(aClassName, theInvokableEvent);
135: } else if (theMemoryStyle == RetainedInMemory.MEM_DOCUMENT) {
136: // The current instance of the InvokableEvent implementation
137: // has specified that it should be cached on a per-document
138: // basis. To do this, we must first obtain a document-level
139: // event cache. Then we add the new object to it.
140: if (theDocumentEvents == null) {
141: theDocumentEvents = new HashMap(1);
142: ExternalEventManager.documents.put(
143: aRenderer, theDocumentEvents);
144: }
145: theDocumentEvents.put(aClassName,
146: theInvokableEvent);
147: } else if (theMemoryStyle == RetainedInMemory.MEM_VOLATILE) {
148: // DO NOTHING. MEM_VOLATILE is the same as not implementing RetainedInMemory.
149: }
150: }
151: }
152: }
153: } catch (Exception e) {
154: e.printStackTrace();
155: }
156: return theInvokableEvent;
157: }
158: }
|