001: /* Page.java
002:
003: {{IS_NOTE
004: Purpose:
005:
006: Description:
007:
008: History:
009: Fri Jun 3 18:17:32 2005, Created by tomyeh
010: }}IS_NOTE
011:
012: Copyright (C) 2005 Potix Corporation. All Rights Reserved.
013:
014: {{IS_RIGHT
015: This program is distributed under GPL Version 2.0 in the hope that
016: it will be useful, but WITHOUT ANY WARRANTY.
017: }}IS_RIGHT
018: */
019: package org.zkoss.zk.ui;
020:
021: import java.util.Map;
022: import java.util.Collection;
023: import java.util.Iterator;
024: import java.util.List;
025:
026: import org.zkoss.xel.FunctionMapper;
027: import org.zkoss.xel.VariableResolver;
028: import org.zkoss.xel.Function;
029:
030: import org.zkoss.zk.scripting.Interpreter;
031: import org.zkoss.zk.scripting.Namespace;
032: import org.zkoss.zk.scripting.InterpreterNotFoundException;
033: import org.zkoss.zk.ui.event.EventListener;
034: import org.zkoss.zk.ui.metainfo.LanguageDefinition;
035: import org.zkoss.zk.ui.metainfo.ComponentDefinition;
036: import org.zkoss.zk.ui.metainfo.ComponentDefinitionMap;
037:
038: /**
039: * A page. A desktop consists of a set of pages.
040:
041: * <p>When a ZK request is asking to render a new page, a new page is
042: * created and components that are created duing this request all belong to
043: * this page.
044: *
045: * <p>If a ZK requst is asking an update, it must have at lease one UUID of
046: * a component ({@link Component#getUuid}.
047: * From this UUID, we know which page it belongs and activate it
048: * to process the update.
049: *
050: <p>By activation, the system guarantees no concurrent access to pages
051: * and components (so you don't need use synchronized for them).
052: *
053: * <h2>Desktop</h2>
054: *
055: * <p>In portal and some environments, a client request (e.g., ServletRequest)
056: * might consists of several ZK requests ({@link org.zkoss.zk.au.AuRequest}).
057: * While each ZK request might ask to create an independent page,
058: * all these pages are grouped as a desktop, such that they are activated
059: * and removed at the same time.
060: * Moreover, pages in the same desktop could communicate to eath other
061: * (see <a href="#inter-page">Inter-page communication</a>).
062: *
063: * <p>A session, {@link Session}, might have multiple desktops of pages,
064: * {@link Page}, while a page belongs to exactly one session.
065: * A page, {@link Page}, might have many components, {@link Component}, while
066: * a component belongs to exactly one page.
067: *
068: * <p>All components of the same desktop of pages are removed at the same time
069: * if a page become 'obsolete'.
070: *
071: * <p>During each execution (${link Execution}), exactly one desktop of
072: * pages are locked (aka., activated). Though an execution serves
073: * a client request (e.g., ServletRequest), a client request might consist
074: * of multiple ZK request ({@link org.zkoss.zk.au.AuRequest}).
075: * Each ZK request might target to a different page (of the same desktop).
076: *
077: * <h2><a name="#inter-page"></a>Inter-page Communication</h2>
078: *
079: * <p>To do inter-page communication, you could do:
080: * <ol>
081: * <li>Invoke methods of components from another page directly.</li>
082: * <li>Use {@link Execution#postEvent} to post events to components from
083: * another page.</li>
084: * </ol>
085: *
086: * <p>They are the same as handling components from the same page.
087: * However, invoking method directly for components from another page has
088: * one restriction:<br>
089: * It cannot <b>create</b> component.
090: *
091: * @author tomyeh
092: */
093: public interface Page extends IdSpace {
094: /** Returns ID which is unique in the request (never null).
095: *
096: * <p>Note: it returns null when
097: * {@link org.zkoss.zk.ui.util.Initiator#doInit} is called.
098: */
099: public String getId();
100:
101: /** Sets the identifier of this page.
102: *
103: * <p>Note: you can change the page's ID only in
104: * {@link org.zkoss.zk.ui.util.Initiator#doInit}
105: * or {@link org.zkoss.zk.ui.util.ExecutionInit#init}.
106: * Once the page is initialized (by {@link org.zkoss.zk.ui.sys.PageCtrl#init}),
107: * calling this
108: * method will cause an exception.
109: *
110: * @exception UiException if the page is initialized, i.e.,
111: * {@link org.zkoss.zk.ui.sys.PageCtrl#init} is called.
112: */
113: public void setId(String id);
114:
115: /** Returns UUID (universal unique ID) which is unquie in the whole
116: * session. The UUID is generated automatically and immutable.
117: *
118: * <p>It is mainly used for communication between client and server
119: * and you rarely need to access it.
120: */
121: public String getUuid();
122:
123: /** Returns the title of the desktop this page belongs to
124: * (and evaluate it if it contains an expression).
125: * <p>Default: "".
126: */
127: public String getTitle();
128:
129: /** Sets the title of the desktop this page belongs to
130: * (it might contain an expression).
131: */
132: public void setTitle(String title);
133:
134: /** Returns the CSS style of this page, or empty if not specified.
135: */
136: public String getStyle();
137:
138: /** Sets the CSS style of this page.
139: *
140: * <p>Note: Unlike {@link #setTitle}, you can change the style only in
141: * the lifecycle of the loading page.
142: */
143: public void setStyle(String style);
144:
145: /** Returns the request path of this page, or "" if not available.
146: * <p>It is the same as the servlet path
147: * (javax.servlet.http.HttpServletRequest's getServletPath), if ZK is running
148: * at a servlet container.
149: *
150: * <p>Note: {@link Desktop#getRequestPath} returns the request path
151: * that causes the desktop to create. And, there might be multiple
152: * pages in the same desktop.
153: *
154: * @see Execution#getContextPath
155: * @see Desktop#getRequestPath
156: */
157: public String getRequestPath();
158:
159: /** Returns the desktop that this page belongs to.
160: *
161: * <p>Note: it returns null when
162: * {@link org.zkoss.zk.ui.util.Initiator#doInit} is called.
163: */
164: public Desktop getDesktop();
165:
166: /** Returns a readonly list of the root components.
167: */
168: public Collection getRoots();
169:
170: /** Used with {@link #getAttribute} and relevants to denote
171: * custom attributes shared by the same page.
172: * <p>It is also known as the page attributes.
173: * <p>It is the same as {@link Page#getAttributes}.
174: */
175: public static final int PAGE_SCOPE = Component.PAGE_SCOPE;
176: /** Used with {@link #getAttribute} and relevants to denote
177: * custom attributes shared by the same desktop.
178: * <p>It is also known as the desktop attributes.
179: * <p>It is the same as {@link Desktop#getAttributes}.
180: */
181: public static final int DESKTOP_SCOPE = Component.DESKTOP_SCOPE;
182: /** Used with {@link #getAttribute} and relevants to denote
183: * custom attributes shared by the same session.
184: * <p>It is also known as the session attributes.
185: * <p>It is the same as {@link Session#getAttributes}.
186: */
187: public static final int SESSION_SCOPE = Component.SESSION_SCOPE;
188: /** Used with {@link #getAttribute} and relevants to denote
189: * custom attributes shared by the whole application.
190: * <p>It is also known as the application attributes.
191: * <p>It is the same as {@link WebApp#getAttributes}.
192: */
193: public static final int APPLICATION_SCOPE = Component.APPLICATION_SCOPE;
194: /** Used with {@link #getAttribute} and relevants to denote
195: * custom attributes shared by the same request.
196: * <p>It is also known as the request attributes.
197: * <p>It is the same as {@link Execution#getAttributes}.
198: */
199: public static final int REQUEST_SCOPE = Component.REQUEST_SCOPE;
200:
201: /** Returns all custom attributes of the specified scope.
202: * You could reference them thru componentScope, spaceScope, pageScope,
203: * requestScope and desktopScope in zscript and EL.
204: *
205: * <p>If scope is {@link #PAGE_SCOPE}, it means custom attributes shared
206: * by components from the same page as this one's.
207: * <p>If scope is {@link #DESKTOP_SCOPE}, it means custom attributes shared
208: * by components from the same desktopas this one's.
209: * @param scope {@link #APPLICATION_SCOPE}, {@link #SESSION_SCOPE},
210: * {@link #PAGE_SCOPE}, {@link #REQUEST_SCOPE} or {@link #DESKTOP_SCOPE}.
211: */
212: public Map getAttributes(int scope);
213:
214: /** Returns the value of the specified custom attribute in the specified scope.
215: *
216: * <p>If scope is {@link #PAGE_SCOPE}, it means custom attributes shared
217: * by components from the same page as this one's.
218: * <p>If scope is {@link #DESKTOP_SCOPE}, it means custom attributes shared
219: * by components from the same desktopas this one's.
220: * @param scope {@link #APPLICATION_SCOPE}, {@link #SESSION_SCOPE},
221: * {@link #PAGE_SCOPE}, {@link #REQUEST_SCOPE} or {@link #DESKTOP_SCOPE}.
222: */
223: public Object getAttribute(String name, int scope);
224:
225: /** Sets the value of the specified custom attribute in the specified scope.
226: *
227: * <p>If scope is {@link #PAGE_SCOPE}, it means custom attributes shared
228: * by components from the same page as this one's.
229: * <p>If scope is {@link #DESKTOP_SCOPE}, it means custom attributes shared
230: * by components from the same desktopas this one's.
231: * @param scope {@link #APPLICATION_SCOPE}, {@link #SESSION_SCOPE},
232: * {@link #PAGE_SCOPE}, {@link #REQUEST_SCOPE} or {@link #DESKTOP_SCOPE}.
233: */
234: public Object setAttribute(String name, Object value, int scope);
235:
236: /** Removes the specified custom attribute in the specified scope.
237: *
238: * <p>If scope is {@link #PAGE_SCOPE}, it means custom attributes shared
239: * by components from the same page as this one's.
240: * <p>If scope is {@link #DESKTOP_SCOPE}, it means custom attributes shared
241: * by components from the same desktopas this one's.
242: * @param scope {@link #APPLICATION_SCOPE}, {@link #SESSION_SCOPE},
243: * {@link #PAGE_SCOPE}, {@link #REQUEST_SCOPE} or {@link #DESKTOP_SCOPE}.
244: */
245: public Object removeAttribute(String name, int scope);
246:
247: /** Returns all custom attributes associated with this page.
248: */
249: public Map getAttributes();
250:
251: /** Returns the value of the specified attribute associated with this page.
252: */
253: public Object getAttribute(String name);
254:
255: /** Sets the value of the specified custom attribute associated with this page.
256: *
257: * <p>Note: The attribute is removed (by {@link #removeAttribute}
258: * if value is null, while {@link #setVariable} considers null as a legal value.
259: *
260: * @param value the value. If null, the attribute is removed.
261: */
262: public Object setAttribute(String name, Object value);
263:
264: /** Removes the specified attribute custom associated with the page.
265: */
266: public Object removeAttribute(String name);
267:
268: /** Sets a variable to the namespace ({@link #getNamespace}).
269: *
270: * <p>It is the same as getNamespace().setVariable(name, value, true).
271: *
272: * @see Component#setVariable
273: * @see Component#getNamespace
274: */
275: public void setVariable(String name, Object val);
276:
277: /** Returns whether the specified variable is defined.
278: *
279: * <p>Note: null is a valid value for variable, so this method is used
280: * to know whether a variable is defined.
281: * On the other hand, {@link #setAttribute} actually remove
282: * an attribute (by {@link #removeAttribute} if value is null.
283: */
284: public boolean containsVariable(String name);
285:
286: /** Returns the value of a variable defined in the namespace ({@link #getNamespace}).
287: *
288: * <p>It is the same as getNamespace().getVariable(name, true).
289: *
290: * <h3>Differences between {@link #getVariable} and {@link #getZScriptVariable}</h3>
291: *
292: * <p>{@link #getVariable} returns only variables defined by
293: * {@link #setVariable} (i.e., a shortcut to {@link Namespace#setVariable}).
294: * On the other hand, {@link #getZScriptVariable} returns these variables
295: * and those defined when executing zscripts.
296: *
297: * @see Component#getVariable
298: * @see Component#getNamespace
299: */
300: public Object getVariable(String name);
301:
302: /** Unsets a variable from the namespace ({@link #getNamespace}).
303: *
304: * <p>It is the same as getNamespace().unsetVariable(name, true).
305: *
306: * @see Component#unsetVariable
307: * @see Component#getNamespace
308: */
309: public void unsetVariable(String name);
310:
311: /** Returns the class of the specified name by searching
312: * the thread class loader and the classes defined in the
313: * loaded interpreters.
314: *
315: * <p>Note: if not defined in the interpeter, it will also look for
316: * the class by use of the current thread's class loader.
317: * See {@link #resolveClass}.
318: *
319: * @return the class, or null if not found
320: * @see #getLoadedInterpreters
321: */
322: public Class getZScriptClass(String clsnm);
323:
324: /** Resolves the class of the specified name.
325: * It first looks at Classes and then all loaded interpreters
326: * {@link #getLoadedInterpreters}.
327: *
328: * <p>It is similar to {@link #getZScriptClass}, except
329: * <ol>
330: * <li>It searches the current thread's class loader first,
331: * and then, the loaded interpreters.</li>
332: * <li>It throws ClassNotFoundException if not found</li>
333: * </ol>
334: *
335: * @since 3.0.1
336: * @see #getZScriptClass
337: */
338: public Class resolveClass(String clsnm)
339: throws ClassNotFoundException;
340:
341: /** Returns the variable of the specified name by searching
342: * the loaded interpreters.
343: *
344: * @return the method, or null if not found
345: * @see #getLoadedInterpreters
346: * @since 3.0.0
347: */
348: public Function getZScriptFunction(String name, Class[] argTypes);
349:
350: /** Returns the variable of the specified name by searching
351: * the logical scope of the specified namespace for all
352: * the loaded interpreters.
353: *
354: * <p>It is similar to {@link #getZScriptVariable(String)}, except
355: * it uses the specified namespace as a reference to identify the
356: * correct scope for searching the variable.
357: * If the interpreter does NOT support hierachical scopes,
358: * this method is the same as {@link #getZScriptVariable(String)}.
359: *
360: * @param ns the namespace used as a reference to identify the
361: * correct scope for searching the variable.
362: * It is ignored if the interpreter doesn't support hierachical scopes.
363: * Note: this method doesn't look for any variable stored in ns.
364: * @return the method, or null if not found
365: * @see #getLoadedInterpreters
366: * @since 2.4.1
367: */
368: public Function getZScriptFunction(Namespace ns, String name,
369: Class[] argTypes);
370:
371: /** Returns the variable of the specified name by searching
372: * the logical scope of the namespace of the specified component
373: * for all the loaded interpreters.
374: *
375: * <p>It is a shortcut: getZScriptFunction(comp.getNamespace(), name, argTypes);
376: * @since 3.0.0
377: */
378: public Function getZScriptFunction(Component comp, String name,
379: Class[] argTypes);
380:
381: /** @deprecated As of release 3.0.0, replaced by {@link #getZScriptFunction(String,Class[])}.
382: */
383: public org.zkoss.zk.scripting.Method getZScriptMethod(String name,
384: Class[] argTypes);
385:
386: /** @deprecated As of release 3.0.0, replaced by {@link #getZScriptFunction(String,Class[])}.
387: */
388: public org.zkoss.zk.scripting.Method getZScriptMethod(Namespace ns,
389: String name, Class[] argTypes);
390:
391: /** Returns the value of the variable of the specified name by searching
392: * the loaded interpreters, if any.
393: *
394: * <h3>Differences between {@link #getVariable} and {@link #getZScriptVariable}</h3>
395: *
396: * <p>{@link #getVariable} returns variables defined by
397: * {@link #setVariable} (i.e., a shortcut to {@link Namespace#setVariable}).
398: * On the other hand, {@link #getZScriptVariable} returns the variables
399: * that are defined when executing zscripts.
400: *
401: * @return the value of the variable, or null if not found
402: * @see #getLoadedInterpreters
403: */
404: public Object getZScriptVariable(String name);
405:
406: /** Returns the value of the variable of the specified name by searching
407: * the logical scope of the specified namespace for all
408: * the loaded interpreters, if any.
409: *
410: * <p>It is similar to {@link #getZScriptVariable(String)}, except
411: * it uses the specified namespace as a reference to identify the
412: * correct scope for searching the variable.
413: * If the interpreter does NOT support hierachical scopes,
414: * this method is the same as {@link #getZScriptVariable(String)}.
415: *
416: * @param ns the namespace used as a reference to identify the
417: * correct scope for searching the variable.
418: * It is ignored if the interpreter doesn't support hierachical scopes.
419: * Note: this method doesn't look for any variable stored in ns.
420: */
421: public Object getZScriptVariable(Namespace ns, String name);
422:
423: /** Returns the value of the variable of the specified name by searching
424: * the logical scope of the namespace of the specified component
425: * for all the loaded interpreters, if any.
426: *
427: * <p>It is a shortcut: getZScriptVariable(comp.getNamespace(), name);
428: * @since 3.0.0
429: */
430: public Object getZScriptVariable(Component comp, String name);
431:
432: /** Returns a variable that is visible to XEL expressions.
433: *
434: * <p>This method is mainly used to access special variable, such as
435: * request parameters (if this page is requested by HTTP).
436: *
437: * <p>Note: components that are specified with an ID are already accessible
438: * by {@link #getVariable}.
439: * @since 3.0.0
440: */
441: public Object getXelVariable(String name);
442:
443: /** Returns a variable that is visible to XEL expressions.
444: * @deprecated As of release 3.0.0, replaced by {@link #getXelVariable}.
445: */
446: public Object getELVariable(String name);
447:
448: /** Adds a name resolver that will be used to resolve a variable
449: * by {@link #getVariable}.
450: *
451: * <p>Note: the variables resolved by the specified resolver are
452: * accessible to both zscript and EL expressions.
453: *
454: * @return wether the resolver is added successfully.
455: * Note: if the resolver was added before, it won't be added again
456: * and this method returns false.
457: */
458: public boolean addVariableResolver(VariableResolver resolver);
459:
460: /** Removes a name resolve that was added by {@link #addVariableResolver}.
461: *
462: * @return false if resolved is not added before.
463: */
464: public boolean removeVariableResolver(VariableResolver resolver);
465:
466: //-- event listener --//
467: /** Adds an event listener to specified event for all components in
468: * this page.
469: *
470: * <p>Due to performance consideration, unlike {@link Component#addEventListener},
471: * all event listeners for the page are deferrable, no matter
472: * {@link org.zkoss.zk.ui.event.Deferrable} is implemented or not.
473: *
474: * @param evtnm what event to listen (never null)
475: * @return whether the listener is added; false if it was added before.
476: * @see Component#addEventListener
477: */
478: public boolean addEventListener(String evtnm, EventListener listener);
479:
480: /** Removes an event listener.
481: * @return whether the listener is removed; false if it was never added.
482: */
483: public boolean removeEventListener(String evtnm,
484: EventListener listener);
485:
486: /** Returns whether the event listener is available.
487: */
488: public boolean isListenerAvailable(String evtnm);
489:
490: /** Returns an iterator for iterating listener for the specified event.
491: */
492: public Iterator getListenerIterator(String evtnm);
493:
494: //-- special control --//
495: /** Removes all components in this page.
496: *
497: * @see Execution#createComponents(String,Component,Map)
498: */
499: public void removeComponents();
500:
501: /** Invalidates this page to cause all components to redraw.
502: */
503: public void invalidate();
504:
505: /** Returns the namespace used to store variables belonging to
506: * the ID space of this page.
507: *
508: * @see #interpret
509: */
510: public Namespace getNamespace();
511:
512: /** Interpret a script of the specified scripting language against
513: * the specified namespace.
514: *
515: * @param zslang the scripting language. If null, {@link #getZScriptLanguage}
516: * is assumed.
517: * @param ns the namspace. If null, the current namespace is assumed.
518: * The current namespace is the event target's namespace
519: * ({@link org.zkoss.zk.ui.event.Event#getTarget}),
520: * if the thread is processing an event.
521: * Otherwise, the current namespace is this page's namespace
522: */
523: public void interpret(String zslang, String script, Namespace ns);
524:
525: /** Returns the interpreter of the specified scripting language.
526: *
527: * <p>The interpreter will be loaded and initialized,
528: * if it is not loaded yet.
529: *
530: * @param zslang the scripting language. If null, {@link #getZScriptLanguage}
531: * is assumed.
532: * @exception InterpreterNotFoundException if not found.
533: */
534: public Interpreter getInterpreter(String zslang);
535:
536: /** Returns all loaded interpreters.
537: */
538: public Collection getLoadedInterpreters();
539:
540: /** Returns the default scripting language which is assumed when
541: * a zscript element doesn't specify any language.
542: *
543: * @return the default scripting language, say, Java. Never null.
544: */
545: public String getZScriptLanguage();
546:
547: /** Sets the defafult scripting language which will be assumed
548: * if a zscript element doesn't specify any language.
549: *
550: * @exception InterpreterNotFoundException if no such language
551: */
552: public void setZScriptLanguage(String zslang)
553: throws InterpreterNotFoundException;
554:
555: //metainfo//
556: /** Returns the function mapper for resolving XEL functions, or null if
557: * not available.
558: *
559: * @since 3.0.0
560: */
561: public FunctionMapper getFunctionMapper();
562:
563: /** Adds the function mapper in addition to the current one.
564: *
565: * <p>The new added function mapper has the higher priority.
566: * {@link #getFunctionMapper} will return the new
567: *
568: * @param mapper the new function mapper (null to ignore).
569: */
570: public void addFunctionMapper(FunctionMapper mapper);
571:
572: /** Returns the language definition that this page belongs to (never null).
573: */
574: public LanguageDefinition getLanguageDefinition();
575:
576: /** Returns the map of component definitions (never null).
577: *
578: * <p>Note: the map is shared among all instance of the same page definition.
579: * Any component definition added (by {@link ComponentDefinitionMap#add})
580: * are visible to all other instances of the same page definition.
581: * Thus, it is NOT a good idea to change its content.
582: */
583: public ComponentDefinitionMap getComponentDefinitionMap();
584:
585: /** Returns the component definition of the specified name, or null
586: * if not found.
587: *
588: * <p>Note: unlike {@link LanguageDefinition#getComponentDefinition},
589: * this method doesn't throw ComponentNotFoundException if not found.
590: * It just returns null.
591: *
592: * @param recur whether to look up the component from {@link #getLanguageDefinition}
593: */
594: public ComponentDefinition getComponentDefinition(String name,
595: boolean recur);
596:
597: /** Returns the component definition of the specified class, or null
598: * if not found.
599: *
600: * <p>Note: unlike {@link LanguageDefinition#getComponentDefinition},
601: * this method doesn't throw ComponentNotFoundException if not found.
602: * It just returns null.
603: *
604: * @param recur whether to look up the component from {@link #getLanguageDefinition}
605: */
606: public ComponentDefinition getComponentDefinition(Class cls,
607: boolean recur);
608: }
|