001: /* *************************************************************************
002:
003: Millstone(TM)
004: Open Sourced User Interface Library for
005: Internet Development with Java
006:
007: Millstone is a registered trademark of IT Mill Ltd
008: Copyright (C) 2000-2005 IT Mill Ltd
009:
010: *************************************************************************
011:
012: This library is free software; you can redistribute it and/or
013: modify it under the terms of the GNU Lesser General Public
014: license version 2.1 as published by the Free Software Foundation.
015:
016: This library is distributed in the hope that it will be useful,
017: but WITHOUT ANY WARRANTY; without even the implied warranty of
018: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019: Lesser General Public License for more details.
020:
021: You should have received a copy of the GNU Lesser General Public
022: License along with this library; if not, write to the Free Software
023: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024:
025: *************************************************************************
026:
027: For more information, contact:
028:
029: IT Mill Ltd phone: +358 2 4802 7180
030: Ruukinkatu 2-4 fax: +358 2 4802 7181
031: 20540, Turku email: info@itmill.com
032: Finland company www: www.itmill.com
033:
034: Primary source for MillStone information and releases: www.millstone.org
035:
036: ********************************************************************** */
037:
038: package org.millstone.base.ui;
039:
040: import org.millstone.base.Application;
041: import org.millstone.base.event.EventRouter;
042: import org.millstone.base.event.MethodEventSource;
043: import org.millstone.base.terminal.*;
044: import org.millstone.base.terminal.VariableOwner;
045: import org.millstone.base.terminal.PaintTarget;
046: import org.millstone.base.terminal.PaintException;
047:
048: import java.util.Collection;
049: import java.util.LinkedList;
050: import java.util.Locale;
051: import java.util.Map;
052: import java.util.Set;
053: import java.util.HashSet;
054: import java.lang.reflect.Method;
055:
056: /** An abstract class that defines default implementation for the
057: * {@link Component} interface. Basic UI components that are not derived
058: * from an external component can inherit this class to easily qualify as a
059: * MillStone component. Most components in the MillStone base UI package do
060: * just that.
061: *
062: * @author IT Mill Ltd.
063: * @version 3.1.1
064: * @since 3.0
065: */
066: public abstract class AbstractComponent implements Component,
067: MethodEventSource {
068:
069: /* Private members ************************************************* */
070:
071: /** Look-and-feel style of the component. */
072: private String style;
073:
074: /** Caption text. */
075: private String caption;
076:
077: /** Application specific data object. */
078: private Object applicationData;
079:
080: /** Icon to be shown together with caption. */
081: private Resource icon;
082:
083: /** Is the component enable (its normal usage is allowed). */
084: private boolean enabled = true;
085:
086: /** Is the component visible (it is rendered). */
087: private boolean visible = true;
088:
089: /** Is the component read-only ? */
090: private boolean readOnly = false;
091:
092: /** Description of the usage (XML). */
093: private String description = null;
094:
095: /** The container this component resides in. */
096: private Component parent = null;
097:
098: /** The EventRouter used for the MillStone event model. */
099: private EventRouter eventRouter = null;
100:
101: /** The internal error message of the component. */
102: private ErrorMessage componentError = null;
103:
104: /** List of event variable change event handling dependencies */
105: private Set dependencies = null;
106:
107: /** Immediate mode: if true, all variable changes are required to be sent
108: * from the terminal immediately
109: */
110: private boolean immediate = false;
111:
112: /** Debug mode: if true, the component may output visual debug information
113: */
114: private boolean debug = false;
115:
116: /** Locale of this component. */
117: private Locale locale;
118:
119: /** List of repaint request listeners or null if not listened at all */
120: private LinkedList repaintRequestListeners = null;
121:
122: /** Are all the repaint listeners notified about recent changes ? */
123: private boolean repaintRequestListenersNotified = false;
124:
125: /* Constructor ***************************************************** */
126:
127: /** Constructs a new Component */
128: public AbstractComponent() {
129: }
130:
131: /* Get/Set component properties ************************************ */
132:
133: /** Gets the UIDL tag corresponding to the component.
134: *
135: * @return component's UIDL tag as <code>String</code>
136: */
137: public abstract String getTag();
138:
139: /* Gets the component's style.
140: * Don't add a JavaDoc comment here, we use the default documentation
141: * from implemented interface.
142: */
143: public String getStyle() {
144: return this .style;
145: }
146:
147: /* Sets the component's style.
148: * Don't add a JavaDoc comment here, we use the default documentation
149: * from implemented interface.
150: */
151: public void setStyle(String style) {
152: this .style = style;
153: requestRepaint();
154: }
155:
156: /* Get's the component's caption.
157: * Don't add a JavaDoc comment here, we use the default documentation
158: * from implemented interface.
159: */
160: public String getCaption() {
161: return this .caption;
162: }
163:
164: /** Sets the component's caption <code>String</code>. Caption is the
165: * visible name of the component. This method will trigger a
166: * {@link org.millstone.base.terminal.Paintable.RepaintRequestEvent RepaintRequestEvent}.
167: *
168: * @param caption new caption <code>String</code> for the component
169: */
170: public void setCaption(String caption) {
171: this .caption = caption;
172: requestRepaint();
173: }
174:
175: /* Don't add a JavaDoc comment here, we use the default documentation
176: * from implemented interface.
177: */
178: public Locale getLocale() {
179: if (this .locale != null)
180: return this .locale;
181: if (this .parent != null)
182: return parent.getLocale();
183: Application app = this .getApplication();
184: if (app != null)
185: return app.getLocale();
186: return null;
187: }
188:
189: /** Sets the locale of this component.
190: * @param locale The locale to become this component's locale.
191: */
192: public void setLocale(Locale locale) {
193: this .locale = locale;
194: }
195:
196: /* Gets the component's icon resource.
197: * Don't add a JavaDoc comment here, we use the default documentation
198: * from implemented interface.
199: */
200: public Resource getIcon() {
201: return this .icon;
202: }
203:
204: /** Sets the component's icon. This method will trigger a
205: * {@link org.millstone.base.terminal.Paintable.RepaintRequestEvent RepaintRequestEvent}.
206: *
207: * @param icon the icon to be shown with the component's caption
208: */
209: public void setIcon(Resource icon) {
210: this .icon = icon;
211: requestRepaint();
212: }
213:
214: /* Tests if the component is enabled or not.
215: * Don't add a JavaDoc comment here, we use the default documentation
216: * from implemented interface.
217: */
218: public boolean isEnabled() {
219: return this .enabled && isVisible();
220: }
221:
222: /* Enables or disables the component.
223: * Don't add a JavaDoc comment here, we use the default documentation
224: * from implemented interface.
225: */
226: public void setEnabled(boolean enabled) {
227: if (this .enabled != enabled) {
228: this .enabled = enabled;
229: requestRepaint();
230: }
231: }
232:
233: /* Tests if the component is in the immediate mode.
234: * Don't add a JavaDoc comment here, we use the default documentation
235: * from implemented interface.
236: */
237: public boolean isImmediate() {
238: return immediate;
239: }
240:
241: /** Sets the component's immediate mode to the specified status. This
242: * method will trigger a
243: * {@link org.millstone.base.terminal.Paintable.RepaintRequestEvent RepaintRequestEvent}.
244: *
245: * @param immediate boolean value specifying if the component should
246: * be in the immediate mode after the call.
247: * @see Component#isImmediate()
248: */
249: public void setImmediate(boolean immediate) {
250: this .immediate = immediate;
251: requestRepaint();
252: }
253:
254: /* Tests if the component is visible.
255: * Don't add a JavaDoc comment here, we use the default documentation
256: * from implemented interface.
257: */
258: public boolean isVisible() {
259: return this .visible;
260: }
261:
262: /* Sets the components visibility.
263: * Don't add a JavaDoc comment here, we use the default documentation
264: * from implemented interface.
265: */
266: public void setVisible(boolean visible) {
267:
268: if (this .visible != visible) {
269: this .visible = visible;
270: // Instead of requesting repaint normally we
271: // fire the event directly to assure that the
272: // event goes through event in the component might
273: // now be invisible
274: fireRequestRepaintEvent(null);
275: }
276: }
277:
278: /** <p>Gets the component's description. The description can be used to
279: * briefly describe the state of the component to the user. The
280: * description string may contain certain XML tags:</p>
281: *
282: * <p><table border=1>
283: * <tr><td width=120><b>Tag</b></td>
284: * <td width=120><b>Description</b></td>
285: * <td width=120><b>Example</b></td>
286: * </tr>
287: * <tr><td><b></td>
288: * <td>bold</td>
289: * <td><b>bold text</b></td>
290: * </tr>
291: * <tr><td><i></td>
292: * <td>italic</td>
293: * <td><i>italic text</i></td>
294: * </tr>
295: * <tr><td><u></td>
296: * <td>underlined</td>
297: * <td><u>underlined text</u></td>
298: * </tr>
299: * <tr><td><br></td>
300: * <td>linebreak</td>
301: * <td>N/A</td>
302: * </tr>
303: * <tr><td><ul><br><li>item1<br><li>item1<br></ul></td>
304: * <td>item list</td>
305: * <td><ul><li>item1 <li>item2</ul></td>
306: * </tr>
307: * </table></p>
308: *
309: * <p>These tags may be nested.</p>
310: *
311: * @return component's description <code>String</code>
312: */
313: public String getDescription() {
314: return this .description;
315: }
316:
317: /** Sets the component's description. See {@link #getDescription()} for
318: * more information on what the description is. This method will trigger
319: * a {@link org.millstone.base.terminal.Paintable.RepaintRequestEvent RepaintRequestEvent}.
320: *
321: * @param description new description string for the component
322: */
323: public void setDescription(String description) {
324: this .description = description;
325: requestRepaint();
326: }
327:
328: /* Gets the component's parent component.
329: * Don't add a JavaDoc comment here, we use the default documentation
330: * from implemented interface.
331: */
332: public Component getParent() {
333: return this .parent;
334: }
335:
336: /* Set the parent component.
337: * Don't add a JavaDoc comment here, we use the default documentation
338: * from implemented interface.
339: */
340: public void setParent(Component parent) {
341:
342: // If the parent is not changed, dont do nothing
343: if (parent == this .parent)
344: return;
345:
346: // Send detach event if the component have been connected to a window
347: if (getApplication() != null) {
348: detach();
349: this .parent = null;
350: }
351:
352: // Connect to new parent
353: this .parent = parent;
354:
355: // Send attach event if connected to a window
356: if (getApplication() != null)
357: attach();
358: }
359:
360: /** Get the error message for this component.
361: *
362: * @return ErrorMessage containing the description of the error state
363: * of the component or null, if the component contains no errors. Extending
364: * classes should override this method if they support other error message
365: * types such as validation errors or buffering errors. The returned error
366: * message contains information about all the errors.
367: */
368: public ErrorMessage getErrorMessage() {
369: return this .componentError;
370: }
371:
372: /** Gets the component's error message.
373: * @link Terminal.ErrorMessage#ErrorMessage(String, int)
374: *
375: * @return component's error message
376: */
377: public ErrorMessage getComponentError() {
378: return this .componentError;
379: }
380:
381: /** Sets the component's error message. The message may contain certain
382: * XML tags, for more information see
383: * @link Component.ErrorMessage#ErrorMessage(String, int)
384: *
385: * @param errorMessage new <code>ErrorMessage</code> of the component
386: */
387: public void setComponentError(ErrorMessage componentError) {
388: this .componentError = componentError;
389: fireComponentErrorEvent();
390: requestRepaint();
391: }
392:
393: /* Tests if the component is in read-only mode.
394: * Don't add a JavaDoc comment here, we use the default documentation
395: * from implemented interface.
396: */
397: public boolean isReadOnly() {
398: return readOnly;
399: }
400:
401: /* Set the component's read-only mode.
402: * Don't add a JavaDoc comment here, we use the default documentation
403: * from implemented interface.
404: */
405: public void setReadOnly(boolean readOnly) {
406: this .readOnly = readOnly;
407: requestRepaint();
408: }
409:
410: /* Get the parent window of the component.
411: * Don't add a JavaDoc comment here, we use the default documentation
412: * from implemented interface.
413: */
414: public Window getWindow() {
415: if (parent == null)
416: return null;
417: else
418: return parent.getWindow();
419: }
420:
421: /* Notify the component that it's attached to a window.
422: * Don't add a JavaDoc comment here, we use the default documentation
423: * from implemented interface.
424: */
425: public void attach() {
426: }
427:
428: /* Detach the component from application.
429: * Don't add a JavaDoc comment here, we use the default documentation
430: * from implemented interface.
431: */
432: public void detach() {
433: }
434:
435: /* Get the parent application of the component.
436: * Don't add a JavaDoc comment here, we use the default documentation
437: * from implemented interface.
438: */
439: public Application getApplication() {
440: if (parent == null)
441: return null;
442: else
443: return parent.getApplication();
444: }
445:
446: /* Component painting ********************************************** */
447:
448: /* Documented in super interface */
449: public void requestRepaintRequests() {
450: repaintRequestListenersNotified = false;
451: }
452:
453: /* Paints the component into a UIDL stream.
454: * Don't add a JavaDoc comment here, we use the default documentation
455: * from implemented interface.
456: */
457: public final void paint(PaintTarget target) throws PaintException {
458:
459: if (!target.startTag(this , this .getTag())) {
460: if (getStyle() != null && getStyle().length() > 0)
461: target.addAttribute("style", getStyle());
462: if (isReadOnly())
463: target.addAttribute("readonly", true);
464: if (!isVisible())
465: target.addAttribute("invisible", true);
466: if (isImmediate())
467: target.addAttribute("immediate", true);
468: if (!isEnabled())
469: target.addAttribute("disabled", true);
470: if (getCaption() != null)
471: target.addAttribute("caption", getCaption());
472: if (getIcon() != null)
473: target.addAttribute("icon", getIcon());
474:
475: // Only paint content of visible components.
476: if (isVisible()) {
477: paintContent(target);
478:
479: String desc = getDescription();
480: if (desc != null && description.length() > 0) {
481: target.startTag("description");
482: target.addUIDL(getDescription());
483: target.endTag("description");
484: }
485:
486: ErrorMessage error = getErrorMessage();
487: if (error != null)
488: error.paint(target);
489: }
490: }
491: target.endTag(this .getTag());
492:
493: repaintRequestListenersNotified = false;
494: }
495:
496: /** Paints any needed component-specific things to the given UIDL
497: * stream. The more general {@link #paint(PaintTarget)} method handles
498: * all general attributes common to all components, and it calls this
499: * method to paint any component-specific attributes to the UIDL stream.
500: *
501: * @param target target UIDL stream where the component should paint
502: * itself to
503: * @throws PaintException if the operation failed
504: */
505: public void paintContent(PaintTarget target) throws PaintException {
506:
507: }
508:
509: /* Documentation copied from interface */
510: public void requestRepaint() {
511:
512: // The effect of the repaint request is identical to case where a
513: // child requests repaint
514: childRequestedRepaint(null);
515: }
516:
517: /* Documentation copied from interface */
518: public void childRequestedRepaint(Collection alreadyNotified) {
519:
520: // Invisible components do not need repaints
521: if (!isVisible())
522: return;
523:
524: fireRequestRepaintEvent(alreadyNotified);
525: }
526:
527: /** Fire repaint request event */
528: private void fireRequestRepaintEvent(Collection alreadyNotified) {
529:
530: // Notify listeners only once
531: if (!repaintRequestListenersNotified) {
532:
533: // Notify the listeners
534: if (repaintRequestListeners != null
535: && !repaintRequestListeners.isEmpty()) {
536: Object[] listeners = repaintRequestListeners.toArray();
537: RepaintRequestEvent event = new RepaintRequestEvent(
538: this );
539: for (int i = 0; i < listeners.length; i++) {
540: if (alreadyNotified == null)
541: alreadyNotified = new LinkedList();
542: if (!alreadyNotified.contains(listeners[i])) {
543: ((RepaintRequestListener) listeners[i])
544: .repaintRequested(event);
545: alreadyNotified.add(listeners[i]);
546: repaintRequestListenersNotified = true;
547: }
548: }
549: }
550:
551: // Notify the parent
552: Component parent = getParent();
553: if (parent != null)
554: parent.childRequestedRepaint(alreadyNotified);
555: }
556: }
557:
558: /* Documentation copied from interface */
559: public void addListener(RepaintRequestListener listener) {
560: if (repaintRequestListeners == null)
561: repaintRequestListeners = new LinkedList();
562: if (!repaintRequestListeners.contains(listener)) {
563: repaintRequestListeners.add(listener);
564: }
565: }
566:
567: /* Documentation copied from interface */
568: public void removeListener(RepaintRequestListener listener) {
569: if (repaintRequestListeners != null) {
570: repaintRequestListeners.remove(listener);
571: if (repaintRequestListeners.isEmpty())
572: repaintRequestListeners = null;
573: }
574: }
575:
576: /* Component variable changes ************************************** */
577:
578: /* Invoked when the value of a variable has changed.
579: * Don't add a JavaDoc comment here, we use the default documentation
580: * from implemented interface.
581: */
582: public void changeVariables(Object source, Map variables) {
583:
584: }
585:
586: /* Adds a variable-change dependency to this component.
587: * Don't add a JavaDoc comment here, we use the default documentation
588: * from implemented interface.
589: */
590: public void dependsOn(VariableOwner depended) {
591:
592: // Assure that the list exists
593: if (dependencies == null)
594: dependencies = new HashSet();
595:
596: // Add to the list of dependencies
597: if (depended != null)
598: dependencies.add(depended);
599: }
600:
601: /* Removes a dependency from the component.
602: * Don't add a JavaDoc comment here, we use the default documentation
603: * from implemented interface.
604: */
605: public void removeDirectDependency(VariableOwner depended) {
606:
607: // Remove the listener if necessary
608: if (dependencies != null && depended != null)
609: dependencies.remove(depended);
610: }
611:
612: /* Gets the set of depended components.
613: * Don't add a JavaDoc comment here, we use the default documentation
614: * from implemented interface.
615: */
616: public Set getDirectDependencies() {
617: return dependencies;
618: }
619:
620: /* General event framework *************************************** */
621:
622: private static final Method COMPONENT_EVENT_METHOD;
623:
624: static {
625: try {
626: COMPONENT_EVENT_METHOD = Component.Listener.class
627: .getDeclaredMethod("componentEvent",
628: new Class[] { Component.Event.class });
629: } catch (java.lang.NoSuchMethodException e) {
630: // This should never happen
631: e.printStackTrace();
632: throw new java.lang.RuntimeException();
633: }
634: }
635:
636: /** <p>Registers a new listener with the specified activation method to
637: * listen events generated by this component. If the activation method
638: * does not have any arguments the event object will not be passed to it
639: * when it's called.</p>
640: *
641: * <p>For more information on the MillStone inheritable event mechanism
642: * see the
643: * {@link org.millstone.base.event org.millstone.base.event package documentation}.</p>
644: *
645: * @param eventType type of the listened event. Events of this type or
646: * its subclasses activate the listener.
647: * @param object the object instance who owns the activation method
648: * @param method the activation method
649: * @throws java.lang.IllegalArgumentException unless <code>method</code>
650: * has exactly one match in <code>object</code>
651: */
652: public void addListener(Class eventType, Object object,
653: Method method) {
654: if (eventRouter == null)
655: eventRouter = new EventRouter();
656: eventRouter.addListener(eventType, object, method);
657: }
658:
659: /** <p>Registers a new listener with the specified activation method to
660: * listen events generated by this component. If the activation method
661: * does not have any arguments the event object will not be passed to it
662: * when it's called.</p>
663: *
664: * <p>This version of <code>addListener</code> gets the name of the
665: * activation method as a parameter. The actual method is reflected from
666: * <code>object</code>, and unless exactly one match is found,
667: * <code>java.lang.IllegalArgumentException</code> is thrown.</p>
668: *
669: * <p>For more information on the MillStone inheritable event mechanism
670: * see the
671: * {@link org.millstone.base.event org.millstone.base.event package documentation}.</p>
672: *
673: * @param eventType type of the listened event. Events of this type or
674: * its subclasses activate the listener.
675: * @param object the object instance who owns the activation method
676: * @param methodName the name of the activation method
677: * @throws java.lang.IllegalArgumentException unless <code>method</code>
678: * has exactly one match in <code>object</code>
679: */
680: public void addListener(Class eventType, Object object,
681: String methodName) {
682: if (eventRouter == null)
683: eventRouter = new EventRouter();
684: eventRouter.addListener(eventType, object, methodName);
685: }
686:
687: /** Removes all registered listeners matching the given parameters.
688: * Since this method receives the event type and the listener object as
689: * parameters, it will unregister all <code>object</code>'s methods that
690: * are registered to listen to events of type <code>eventType</code>
691: * generated by this component.
692: *
693: * <p>For more information on the MillStone inheritable event mechanism
694: * see the
695: * {@link org.millstone.base.event org.millstone.base.event package documentation}.</p>
696: *
697: * @param eventType exact event type the <code>object</code> listens to
698: * @param target target object that has registered to listen to events
699: * of type <code>eventType</code> with one or more methods
700: */
701: public void removeListener(Class eventType, Object target) {
702: if (eventRouter != null)
703: eventRouter.removeListener(eventType, target);
704: }
705:
706: /** Removes one registered listener method. The given method owned by
707: * the given object will no longer be called when the specified events
708: * are generated by this component.
709: *
710: * <p>For more information on the MillStone inheritable event mechanism
711: * see the
712: * {@link org.millstone.base.event org.millstone.base.event package documentation}.</p>
713: *
714: * @param eventType exact event type the <code>object</code> listens to
715: * @param target target object that has registered to listen to events
716: * of type <code>eventType</code> with one or more methods
717: * @param method the method owned by <code>target</code> that's
718: * registered to listen to events of type <code>eventType</code>
719: */
720: public void removeListener(Class eventType, Object target,
721: Method method) {
722: if (eventRouter != null)
723: eventRouter.removeListener(eventType, target, method);
724: }
725:
726: /** <p>Removes one registered listener method. The given method owned by
727: * the given object will no longer be called when the specified events
728: * are generated by this component.</p>
729: *
730: * <p>This version of <code>removeListener</code> gets the name of the
731: * activation method as a parameter. The actual method is reflected from
732: * <code>target</code>, and unless exactly one match is found,
733: * <code>java.lang.IllegalArgumentException</code> is thrown.</p>
734: *
735: * <p>For more information on the MillStone inheritable event mechanism
736: * see the
737: * {@link org.millstone.base.event org.millstone.base.event package documentation}.</p>
738: *
739: * @param eventType exact event type the <code>object</code> listens to
740: * @param target target object that has registered to listen to events
741: * of type <code>eventType</code> with one or more methods
742: * @param methodName name of the method owned by <code>target</code>
743: * that's registered to listen to events of type <code>eventType</code>
744: */
745: public void removeListener(Class eventType, Object target,
746: String methodName) {
747: if (eventRouter != null)
748: eventRouter.removeListener(eventType, target, methodName);
749: }
750:
751: /** Send event to all listeners
752: * @param event Event to be sent to all listeners
753: */
754: protected void fireEvent(Component.Event event) {
755:
756: if (eventRouter != null)
757: eventRouter.fireEvent(event);
758:
759: }
760:
761: /* Component event framework *************************************** */
762:
763: /* Registers a new listener to listen events generated by this
764: * component.
765: * Don't add a JavaDoc comment here, we use the default documentation
766: * from implemented interface.
767: */
768: public void addListener(Component.Listener listener) {
769:
770: if (eventRouter == null)
771: eventRouter = new EventRouter();
772:
773: eventRouter.addListener(Component.Event.class, listener,
774: COMPONENT_EVENT_METHOD);
775: }
776:
777: /* Removes a previously registered listener from this component.
778: * Don't add a JavaDoc comment here, we use the default documentation
779: * from implemented interface.
780: */
781: public void removeListener(Component.Listener listener) {
782:
783: if (eventRouter != null) {
784: eventRouter.removeListener(Component.Event.class, listener,
785: COMPONENT_EVENT_METHOD);
786: }
787: }
788:
789: /** Emits a component event. It is transmitted to all registered
790: * listeners interested in such events.
791: */
792: protected void fireComponentEvent() {
793: fireEvent(new Component.Event(this ));
794: }
795:
796: /** Emits a component error event. It is transmitted to all registered
797: * listeners interested in such events.
798: */
799: protected void fireComponentErrorEvent() {
800: fireEvent(new Component.ErrorEvent(this .getComponentError(),
801: this ));
802: }
803:
804: /** Sets application specific data object.
805: *
806: * @param data Application specific data.
807: * @since 3.1
808: */
809: public void setData(Object data) {
810: this .applicationData = data;
811: }
812:
813: /** Gets application specific data.
814: *
815: * @return Application specific data set with setData function.
816: * @since 3.1
817: */
818: public Object getData() {
819: return this.applicationData;
820: }
821: }
|