In Vorbereitung auf die Ausgabe der Informationen zur Programmversion wird nun ein bebop:pageGenerator erzeugt, sobald HashMap<String, String> m_pageGenerator mit den entsprechenden Informationen gefüllt wird. Dieses geht über die Methode addGeneratorInformation(String key, String value). Fehlt jetzt die Möglichkeit diese Informationen beim Start aus den Metataden auszulesen und immer zu setzen. Dazu muß vermutlich die Struktur noch etwas angepaßt werden.

git-svn-id: https://svn.libreccm.org/ccm/trunk@2281 8810af33-2d31-482b-a856-94f89814c4df
master
quasi 2013-08-01 06:14:10 +00:00
parent 2ce26b2386
commit 722a74ce2f
1 changed files with 258 additions and 218 deletions

View File

@ -32,7 +32,6 @@ import com.arsdigita.profiler.Profiler;
import com.arsdigita.util.Assert;
import com.arsdigita.xml.Document;
import com.arsdigita.xml.Element;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.Collection;
@ -43,48 +42,46 @@ import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.log4j.Logger;
/**
* <p>The top-level container for all Bebop components and containers. </p>
*
* <UL>
* <LI>Holds references to the components of a page.</LI>
* <LI>Provides methods for servicing requests and for notifying
* other components that a request for this page has been received through
*
* <UL> <LI>Holds references to the components of a page.</LI> <LI>Provides
* methods for servicing requests and for notifying other components that a
* request for this page has been received through
* {@link ActionListener ActionListeners}.</LI>
*
* <LI>Tracks request parameters for stateful components, such as tabbed
* panes and sortable tables.</LI>
* </UL>
* <p>
* A typical <code>Page</code> may be created as follows:
* <blockquote><pre><code>
* <LI>Tracks request parameters for stateful components, such as tabbed panes
* and sortable tables.</LI> </UL> <p> A typical
* <code>Page</code> may be created as follows: null <blockquote><pre><code>
* Page p = new Page("Hello World");
* p.add(new Label("Hello World");
* p.lock();
* </code></pre></blockquote>
* </p>
* </code></pre></blockquote> </p>
*
* @author David Lutterkort
* @author Stanislav Freidin
* @author Uday Mathur
* @author David Lutterkort
* @author Stanislav Freidin
* @author Uday Mathur
*
* @version $Id: Page.java 1270 2006-07-18 13:34:55Z cgyg9330 $
*/
public class Page extends BlockStylable implements Container {
/** Class specific logger instance. */
/**
* Class specific logger instance.
*/
private static final Logger s_log = Logger.getLogger(Page.class);
/** The delimiter character for components naming */
/**
* The delimiter character for components naming
*/
private static final String DELIMITER = ".";
/**
* The prefix that gets prepended to all state variables. Components must
@ -95,8 +92,8 @@ public class Page extends BlockStylable implements Container {
private static final String COMPONENT_PREFIX = "bbp" + DELIMITER;
private static final String INTERNAL = COMPONENT_PREFIX;
/**
* The name of the special parameter that indicates which component has
* been selected.
* The name of the special parameter that indicates which component has been
* selected.
*/
static final String SELECTED = INTERNAL + "s";
static final String CONTROL_EVENT = INTERNAL + "e";
@ -117,10 +114,10 @@ public class Page extends BlockStylable implements Container {
*/
static final String INVISIBLE = INTERNAL + "i";
/**
* Map of stateful components (id --> Component)
* SortedMap used because component based hash for page is based on concatenation of
* component ids, and so need to guarantee that they are returned in the same order
* for the same page - cg.
* Map of stateful components (id --> Component) SortedMap used because
* component based hash for page is based on concatenation of component ids,
* and so need to guarantee that they are returned in the same order for the
* same page - cg.
*/
private SortedMap m_componentMap;
private List m_components;
@ -130,15 +127,16 @@ public class Page extends BlockStylable implements Container {
private Map m_componentParameterMap = new HashMap();
private FormModel m_stateModel;
/**
* <code>Container</code> that renders this <code>Page</code>.
* <code>Container</code> that renders this
* <code>Page</code>.
*/
protected Container m_panel;
private List m_actionListeners;
private List m_requestListeners;
/**
* The title of the page to be added in the head of HTML output. The
* title is wrapped in a Label to allow developers to add
* PrintListeners to dynamically change the value of the title.
* The title of the page to be added in the head of HTML output. The title
* is wrapped in a Label to allow developers to add PrintListeners to
* dynamically change the value of the title.
*/
private Label m_title;
/**
@ -147,16 +145,16 @@ public class Page extends BlockStylable implements Container {
*/
private RequestLocal m_currentTitle;
/**
* A list of all the client-side stylesheets. The elements of the list
* are of type Page.Stylesheet, defined at the end of this file.
* A list of all the client-side stylesheets. The elements of the list are
* of type Page.Stylesheet, defined at the end of this file.
*/
private List m_clientStylesheets;
private StringParameter m_selected;
private StringParameter m_controlEvent;
private StringParameter m_controlValue;
/**
* The default (initial) visibility of components. The encoding is
* identical to that for PageState.m_invisible.
* The default (initial) visibility of components. The encoding is identical
* to that for PageState.m_invisible.
*
* This variable is package-friendly since it needs to be accessed by
* PageState.
@ -172,51 +170,53 @@ public class Page extends BlockStylable implements Container {
*/
private boolean m_finished = false;
/**
* indicates whether pageState.stateAsURL() should export the
* entire state for this page, or whether it should only export
* the control event as a URL and use the HttpSession for the
* rest of the page state.
* indicates whether pageState.stateAsURL() should export the entire state
* for this page, or whether it should only export the control event as a
* URL and use the HttpSession for the rest of the page state.
*/
private boolean m_useHttpSession = false;
/**
* HasMap for page generator information.
*/
private HashMap<String, String> m_pageGenerator = new HashMap<String, String>();
/**
* Returns <code>true</code> if this page should export state through
* the HttpSession instead of the URL query string.
* <P>If this returns <code>true</code>, then PageState.stateAsURL()
* will only export the control event as
* a URL query string. If this returns <code>false</code>,
* then stateAsURL() will export the entire page state.
* Returns
* <code>true</code> if this page should export state through the
* HttpSession instead of the URL query string. <P>If this returns
* <code>true</code>, then PageState.stateAsURL() will only export the
* control event as a URL query string. If this returns
* <code>false</code>, then stateAsURL() will export the entire page state.
*
*
* @see PageState#stateAsURL
*
* @return <code>true</code> if this page should export state through
* the HttpSession; <code>false</code> if it should export using
* the URL query string.
* @return <code>true</code> if this page should export state through the
* HttpSession; <code>false</code> if it should export using the URL query
* string.
*/
public boolean isUsingHttpSession() {
return m_useHttpSession;
}
/**
* Indicates to this page whether it should export its entire state
* to subsequent requests through the URL query string, or if it should
* use the HttpSession instead and only use the URL query string for
* the control event.
* Indicates to this page whether it should export its entire state to
* subsequent requests through the URL query string, or if it should use the
* HttpSession instead and only use the URL query string for the control
* event.
*
* @see PageState#stateAsURL
*
* @param b <code>true</code> if PageState.stateAsURL()
* will export only the control event as a URL query string.
* <code>false</code> if stateAsURL() will export the entire page state.
* @param b <code>true</code> if PageState.stateAsURL() will export only the
* control event as a URL query string. <code>false</code> if stateAsURL()
* will export the entire page state.
*/
public void setUsingHttpSession(boolean b) {
m_useHttpSession = b;
}
/**
* Creates an empty page with the specified title and
* panel.
* Creates an empty page with the specified title and panel.
*
* @param title title for this page
*
@ -227,8 +227,7 @@ public class Page extends BlockStylable implements Container {
}
/**
* Creates an empty page with the specified title and
* panel.
* Creates an empty page with the specified title and panel.
*
* @param title title for this page
*
@ -248,7 +247,6 @@ public class Page extends BlockStylable implements Container {
// Initialize the RequestLocal where the title for the current
// request will be kept
m_currentTitle = new RequestLocal() {
@Override
protected Object initialValue(PageState state) {
return m_title.firePrintEvent(state);
@ -270,21 +268,20 @@ public class Page extends BlockStylable implements Container {
// Set up the visibility tracking parameters
m_invisible = new BitSet(32);
BitSetParameter p = new BitSetParameter(INVISIBLE,
BitSetParameter.ENCODE_DGAP);
BitSetParameter.ENCODE_DGAP);
m_stateModel.addFormParam(p);
}
/**
* Creates an empty page with default title and implicit BoxPanel
* container.
* Creates an empty page with default title and implicit BoxPanel container.
*/
public Page() {
this("");
}
/**
* Creates an empty page with the specified title and implicit
* BoxPanel container.
* Creates an empty page with the specified title and implicit BoxPanel
* container.
*
* @param title title for this page
*/
@ -295,8 +292,8 @@ public class Page extends BlockStylable implements Container {
}
/**
* Creates an empty page with the specified title and implicit
* BoxPanel container.
* Creates an empty page with the specified title and implicit BoxPanel
* container.
*
* @param title title for this page
*/
@ -315,31 +312,31 @@ public class Page extends BlockStylable implements Container {
}
/**
* Adds a component with the specified layout constraints to this
* container. Layout constraints are defined in each layout container as
* static ints. To specify multiple constraints, use bitwise OR.
* Adds a component with the specified layout constraints to this container.
* Layout constraints are defined in each layout container as static ints.
* To specify multiple constraints, use bitwise OR.
*
* @param c component to add to this container
*
* @param constraints layout constraints (a
* bitwise OR of static ints in the particular layout)
* @param constraints layout constraints (a bitwise OR of static ints in the
* particular layout)
*/
public void add(Component c, int constraints) {
m_panel.add(c, constraints);
}
/**
* Returns <code>true</code> if this list contains the specified element.
* More formally, returns <code>true</code> if and only if this list
* contains at least
* one element e such that (o==null ? e==null : o.equals(e)).
* <P>
* This method returns <code>true</code> only if the component has been
* directly added to this container. If this container contains another
* container that contains this component, this method returns
* Returns
* <code>true</code> if this list contains the specified element. More
* formally, returns
* <code>true</code> if and only if this list contains at least one element
* e such that (o==null ? e==null : o.equals(e)). <P> This method returns
* <code>true</code> only if the component has been directly added to this
* container. If this container contains another container that contains
* this component, this method returns
* <code>false</code>.
*
* @param o element whose presence in this container is to be tested
* @param o element whose presence in this container is to be tested
*
* @return <code>true</code> if this Container contains the specified
* component directly; <code>false</code> otherwise.
@ -349,14 +346,12 @@ public class Page extends BlockStylable implements Container {
}
/**
* Returns the
* component at the specified position. Each call to the add method
* increments the index. Since the user has no control over the index
* of added components (other than counting each call to add), this
* method should be used in conjunction with indexOf.
* Returns the component at the specified position. Each call to the add
* method increments the index. Since the user has no control over the index
* of added components (other than counting each call to add), this method
* should be used in conjunction with indexOf.
*
* @param index the index of the item to be retrieved from this
* Container
* @param index the index of the item to be retrieved from this Container
*
* @return the component at the specified position in this container.
*/
@ -365,25 +360,26 @@ public class Page extends BlockStylable implements Container {
}
/**
* Gets the index of a
* component.
* Gets the index of a component.
*
* @param c component to search for
*
* @return the index in this list of the first occurrence of the
* specified element, or -1 if this list does not contain this element.
* @return the index in this list of the first occurrence of the specified
* element, or -1 if this list does not contain this element.
*
* @pre c != null
* @post contains(c) implies (return >= 0) && (return < size())
* @post !contains(c) implies return == -1 */
* @post !contains(c) implies return == -1
*/
public int indexOf(Component c) {
return m_panel.indexOf(c);
}
/**
* Returns <code>true</code> if the container contains no components.
* Returns
* <code>true</code> if the container contains no components.
*
* @return <code>true</code> if this container contains no
* @return <code>true</code> if this container contains no * *
* components; <code>false</code> otherwise.
*/
public boolean isEmpty() {
@ -392,8 +388,8 @@ public class Page extends BlockStylable implements Container {
/**
* Returns the number of elements in this container. This does not
* recursively count the components that are indirectly contained
* in this container.
* recursively count the components that are indirectly contained in this
* container.
*
* @return the number of components directly in this container.
*/
@ -407,8 +403,9 @@ public class Page extends BlockStylable implements Container {
}
/**
* Returns the panel that the <code>Page</code> uses for rendering its
* components.
* Returns the panel that the
* <code>Page</code> uses for rendering its components.
*
* @return the panel.
*/
public final Container getPanel() {
@ -427,9 +424,7 @@ public class Page extends BlockStylable implements Container {
}
/**
* <p>
* Retrieves the title of this page.
* </p>
* <p> Retrieves the title of this page. </p>
*
* @return the static title of this page.
*/
@ -468,16 +463,16 @@ public class Page extends BlockStylable implements Container {
}
/**
* Sets the {@link Component} that will display the validation errors
* in the current {@link PageState}. Any validation error in the
* <code>PageState</code> will cause the <code>Page</code> to completely
* ignore all other components and render only the error display component.
* <p>
* By default, a {@link PageErrorDisplay} component is used to display the
* validation errors.
* Sets the {@link Component} that will display the validation errors in the
* current {@link PageState}. Any validation error in the
* <code>PageState</code> will cause the
* <code>Page</code> to completely ignore all other components and render
* only the error display component. <p> By default, a
* {@link PageErrorDisplay} component is used to display the validation
* errors.
*
* @param c the component that will display the validation errors
* in the current <code>PageState</code>
* @param c the component that will display the validation errors in the
* current <code>PageState</code>
*/
public final void setErrorDisplay(Component c) {
Assert.isUnlocked(this);
@ -485,29 +480,29 @@ public class Page extends BlockStylable implements Container {
}
/**
* Gets the {@link Component} that will display the validation errors
* in the current {@link PageState}. Any validation error in the
* <code>PageState</code> will cause the <code>Page</code> to completely
* ignore all other components and render only the error display component.
* <p>
* By default, a {@link PageErrorDisplay} component is used to display the
* validation errors.
* Gets the {@link Component} that will display the validation errors in the
* current {@link PageState}. Any validation error in the
* <code>PageState</code> will cause the
* <code>Page</code> to completely ignore all other components and render
* only the error display component. <p> By default, a
* {@link PageErrorDisplay} component is used to display the validation
* errors.
*
* @return the component that will display the validation errors
* in the current <code>PageState</code>.
* @return the component that will display the validation errors in the
* current <code>PageState</code>.
*/
public final Component getErrorDisplay() {
return m_errorDisplay;
}
/**
* Adds a client-side stylesheet that should be used in HTML
* output. Arbitrarily many client-side stylesheets can be added with
* this method. To use a CSS stylesheet, call something like
* Adds a client-side stylesheet that should be used in HTML output.
* Arbitrarily many client-side stylesheets can be added with this method.
* To use a CSS stylesheet, call something like
* <code>setStyleSheet("style.css", "text/css")</code>.
*
* <p> These values will ultimately wind up in a <tt>&lt;link&gt;</tt>
* tag in the head of the HTML page.
* <p> These values will ultimately wind up in a <tt>&lt;link&gt;</tt> tag
* in the head of the HTML page.
*
* <p> Note that the stylesheet set with this call has nothing to do with
* the XSLT stylesheet (transformer) that is applied to the XML generated
@ -515,7 +510,7 @@ public class Page extends BlockStylable implements Container {
*
* @param styleSheetURI the location of the stylesheet
* @param mimeType the MIME type of the stylesheet, usually
* <tt>text/css</tt>
* <tt>text/css</tt>
* @pre ! isLocked()
*/
public void addClientStylesheet(String styleSheetURI, String mimeType) {
@ -523,14 +518,14 @@ public class Page extends BlockStylable implements Container {
}
/**
* Adds a global state parameter to this page. Global parameters are
* values that need to be preserved between requests, but that have no
* special connection to any of the components on the page. For a page
* that displays details about an item, a global parameter would be
* used to identify the item.
* Adds a global state parameter to this page. Global parameters are values
* that need to be preserved between requests, but that have no special
* connection to any of the components on the page. For a page that displays
* details about an item, a global parameter would be used to identify the
* item.
*
* <p> If the parameter was previously added as a component state
* parameter, its name is unmangled and stays unmangled.
* <p> If the parameter was previously added as a component state parameter,
* its name is unmangled and stays unmangled.
*
* @param p the global parameter to add
*
@ -546,18 +541,17 @@ public class Page extends BlockStylable implements Container {
}
/**
* Constructs the top nodes of the DOM or JDOM tree. Used by
* generateXML(PageState, Document) below.
* <p>Generates DOM fragment:
* Constructs the top nodes of the DOM or JDOM tree. Used by
* generateXML(PageState, Document) below. <p>Generates DOM fragment:
* <pre>
* &lt;bebop:page>
* &lt;bebop:title> ... value set with <i>setTitle</i> ... &lt;/bebop:title>
* &lt;bebop:stylesheet href='styleSheetURI' type='mimeType'>
* ... page content gnerated by children ...
* &lt;/bebop:page></pre>
* The content of the <tt>&lt;title&gt;</tt> element can be set by
* calling {@link #setTitle setTitle}. The <tt>&lt;stylesheet&gt;</tt>
* element will only be present if a stylesheet has been set with {@link
* &lt;/bebop:page></pre> The content of the <tt>&lt;title&gt;</tt> element
* can be set by calling {@link #setTitle setTitle}. The
* <tt>&lt;stylesheet&gt;</tt> element will only be present if a stylesheet
* has been set with {@link
* #setStyleSheet setStyleSheet}.
*
* @param ps the page state for the current page
@ -571,6 +565,9 @@ public class Page extends BlockStylable implements Container {
Element page = parent.createRootElement("bebop:page", BEBOP_XML_NS);
exportAttributes(page);
/* Generator information */
exportPageGenerator(page);
Element title = page.newChildElement("bebop:title", BEBOP_XML_NS);
title.setText(getTitle(ps).getLabel(ps));
@ -582,10 +579,11 @@ public class Page extends BlockStylable implements Container {
}
/**
* Constructs a DOM or JDOM tree with all components on the page. The tree
* represents the page that
* results from the {@link javax.servlet.http.HttpServletRequest} kept in
* the <code>state</code>.
* Constructs a DOM or JDOM tree with all components on the page. The tree
* represents the page that results from the
* {@link javax.servlet.http.HttpServletRequest} kept in the
* <code>state</code>.
*
* @param state the page state produced by {@link #process}
* @param parent the DOM node for the whole Document
* @see #process process
@ -623,19 +621,18 @@ public class Page extends BlockStylable implements Container {
}
/**
* Do nothing. Top-level add nodes is meaningless.
* Do nothing. Top-level add nodes is meaningless.
*/
public void generateXML(PageState state, Element elt) {
return;
}
/**
* Creates a PageState object and processes it by calling the
* respond method on the
* selected component. Processes a request by notifying the component
* Creates a PageState object and processes it by calling the respond method
* on the selected component. Processes a request by notifying the component
* from which the process originated and {@link #fireActionEvent
* broadcasts} an {@link ActionEvent} to all the listeners that
* registered with {@link #addActionListener addActionListener}.
* broadcasts} an {@link ActionEvent} to all the listeners that registered
* with {@link #addActionListener addActionListener}.
*
* @see #generateXML(PageState,Document) generateXML
* @pre isLocked()
@ -643,7 +640,7 @@ public class Page extends BlockStylable implements Container {
* @pre response != null
*/
public PageState process(HttpServletRequest request,
HttpServletResponse response)
HttpServletResponse response)
throws ServletException {
PageState result = new PageState(this, request, response);
@ -657,9 +654,8 @@ public class Page extends BlockStylable implements Container {
}
/**
* Processes the supplied PageState object according to this
* PageModel. Calls the respond method on the selected Bebop
* component.
* Processes the supplied PageState object according to this PageModel.
* Calls the respond method on the selected Bebop component.
*/
public void process(PageState state) throws ServletException {
Assert.isLocked(this);
@ -704,18 +700,17 @@ public class Page extends BlockStylable implements Container {
// return state;
// }
/**
* Builds a DOM Document from the current request state by
* doing a depth-first tree walk on the current set of components
* in this Page, calling generateXML on each. Does NOT do the rendering.
* If the HTTP response has already been committed, does not
* build the XML document.
* Builds a DOM Document from the current request state by doing a
* depth-first tree walk on the current set of components in this Page,
* calling generateXML on each. Does NOT do the rendering. If the HTTP
* response has already been committed, does not build the XML document.
*
* @return a DOM ready for rendering, or null if the response has
* already been committed.
* @return a DOM ready for rendering, or null if the response has already
* been committed.
* @post res.isCommitted() == (return == null)
*/
public Document buildDocument(HttpServletRequest req,
HttpServletResponse res)
HttpServletResponse res)
throws ServletException {
try {
Document doc = new Document();
@ -743,8 +738,7 @@ public class Page extends BlockStylable implements Container {
/**
* Finishes building the page. The tree of components is traversed and each
* component is told to add its state parameters to the page's state
* model.
* component is told to add its state parameters to the page's state model.
*
* @pre ! isLocked()
*/
@ -753,7 +747,6 @@ public class Page extends BlockStylable implements Container {
Assert.isUnlocked(this);
Traversal componentRegistrar = new Traversal() {
protected void act(Component c) {
addComponent(c);
c.register(Page.this);
@ -784,7 +777,6 @@ public class Page extends BlockStylable implements Container {
}
m_stateModel.lock();
Traversal componentLocker = new Traversal() {
protected void act(Component c) {
c.lock();
}
@ -800,8 +792,9 @@ public class Page extends BlockStylable implements Container {
}
/**
* Registers a listener that is notified whenever a request to this page
* is made, after the selected component has had a chance to respond.
* Registers a listener that is notified whenever a request to this page is
* made, after the selected component has had a chance to respond.
*
* @pre l != null
* @pre ! isLocked()
*/
@ -812,6 +805,7 @@ public class Page extends BlockStylable implements Container {
/**
* Remove a previously registered action listener.
*
* @pre l != null
* @pre ! isLocked()
*/
@ -821,8 +815,9 @@ public class Page extends BlockStylable implements Container {
}
/**
* Registers a listener that is notified whenever a request to this page
* is made, before the selected component has had a chance to respond.
* Registers a listener that is notified whenever a request to this page is
* made, before the selected component has had a chance to respond.
*
* @pre l != null
* @pre ! isLocked()
*/
@ -833,6 +828,7 @@ public class Page extends BlockStylable implements Container {
/**
* Removes a previously registered request listener.
*
* @param 1 the listener to remove
* @pre l != null
* @pre ! isLocked()
@ -843,9 +839,10 @@ public class Page extends BlockStylable implements Container {
}
/**
* Broadcasts an {@link ActionEvent} to all registered listeners. The
* source of the event is this page, and the state recorded in the event
* is the one resulting from processing the current request.
* Broadcasts an {@link ActionEvent} to all registered listeners. The source
* of the event is this page, and the state recorded in the event is the one
* resulting from processing the current request.
*
* @param the state for this event
*
* @pre state != null
@ -869,10 +866,11 @@ public class Page extends BlockStylable implements Container {
}
/**
* Broadcasts a {@link RequestEvent} to all registered listeners. The
* source of the event is this page, and the state recorded in the event
* is the one resulting from processing the current request.
* @param the state for this event
* Broadcasts a {@link RequestEvent} to all registered listeners. The source
* of the event is this page, and the state recorded in the event is the one
* resulting from processing the current request.
*
* @param state the state for this event
*
* @pre state != null
*/
@ -894,6 +892,49 @@ public class Page extends BlockStylable implements Container {
}
}
final protected void addPageGeneratorInformation(String key, String value) {
if (key != null && !key.isEmpty()) {
m_pageGenerator.put(key, value);
}
}
final protected String getPageGeneratorInformation(String key) {
if (key != null && !key.isEmpty()) {
return m_pageGenerator.get(key);
} else {
return null;
}
}
final protected String removePageGeneratorInformation(String key) {
if (key != null && !key.isEmpty()) {
return m_pageGenerator.remove(key);
} else {
return null;
}
}
/**
* Export page generator information if set. The m_pageGenerator is a
* HashMap containing the information as key value. In general this should
* include generator name and generator version.
*
* @param page parent element - should be bebeop:page
*
* @pre m_pageGenerator != null && !m_pageGenerator.isEmpty()
*/
final protected void exportPageGenerator(Element page) {
if (m_pageGenerator != null && !m_pageGenerator.isEmpty()) {
Element gen = page.newChildElement("bebop:pageGenerator", BEBOP_XML_NS);
Iterator<Map.Entry<String, String>> keyValues = ((Set<Map.Entry<String, String>>) m_pageGenerator.entrySet()).iterator();
while (keyValues.hasNext()) {
Map.Entry<String, String> entry = keyValues.next();
gen.addAttribute(entry.getKey(), entry.getValue());
}
}
}
// Client-side stylesheet storage
private class Stylesheet {
@ -907,7 +948,7 @@ public class Page extends BlockStylable implements Container {
public void generateXML(Element parent) {
Element style = parent.newChildElement("bebop:stylesheet",
BEBOP_XML_NS);
BEBOP_XML_NS);
style.addAttribute("href", m_URI);
if (m_type != null) {
style.addAttribute("type", m_type);
@ -927,8 +968,8 @@ public class Page extends BlockStylable implements Container {
if (c == null) {
s_log.error("c is null");
} /*else {
s_log.error("c: " + c.toString());
}*/
s_log.error("c: " + c.toString());
}*/
String key = c.getKey();
if (key == null) {
key = Integer.toString(m_components.size());
@ -946,10 +987,10 @@ public class Page extends BlockStylable implements Container {
/**
* Registers a state parameter for a component. It is permissible to
* register the same state parameter several times, from the same or
* different components. The name of the parameter will be changed
* to ensure that it won't clash with any other component's parameter.
* If the parameter is added more than once, the name is only changed
* the first time it is added.
* different components. The name of the parameter will be changed to ensure
* that it won't clash with any other component's parameter. If the
* parameter is added more than once, the name is only changed the first
* time it is added.
*
* @param c the component to register the parameter for
* @param p the state parameter to register
@ -970,7 +1011,7 @@ public class Page extends BlockStylable implements Container {
if (!m_stateModel.containsFormParam(p)) {
String name = parameterName(c, p.getName());
s_log.debug(String.format("Setting name of parameter to add to '%s'",
name));
name));
p.setName(name);
m_stateModel.addFormParam(p);
@ -991,13 +1032,13 @@ public class Page extends BlockStylable implements Container {
}
/**
* Gets the state index of a component. This is the number assigned
* to the component in the register traveral
* Gets the state index of a component. This is the number assigned to the
* component in the register traveral
*
* @param c the component to search for
*
* @return the index in this list of the first occurrence of the
* specified element, or -1 if this list does not contain this element.
* @return the index in this list of the first occurrence of the specified
* element, or -1 if this list does not contain this element.
*
* @pre c != null
* @post contains(c) implies (return >= 0) && (return < size())
@ -1045,8 +1086,7 @@ public class Page extends BlockStylable implements Container {
}
/**
* Gets the form model that contains the parameters for the page's
* state.
* Gets the form model that contains the parameters for the page's state.
*/
public final FormModel getStateModel() {
return m_stateModel;
@ -1062,14 +1102,13 @@ public class Page extends BlockStylable implements Container {
}
/**
* Checks whether the specified component is visible by default on
* the page.
* Checks whether the specified component is visible by default on the page.
*
* @param c a component contained in the page
* @return <code>true</code> if the component is visible by default;
* <code>false</code> otherwise.
* @see #setVisibleDefault setVisibleDefault
* @see Component#setVisible Component.setVisible
* @see Component#setVisible Component.setVisible
*/
public boolean isVisibleDefault(Component c) {
Assert.isTrue(stateContains(c));
@ -1078,10 +1117,10 @@ public class Page extends BlockStylable implements Container {
}
/**
* Sets whether the specified component is visible by default. The
* default visibility is used when a page is displayed for the first
* time and on subsequent requests until the visibility of a component
* is changed explicitly with {@link Component#setVisible
* Sets whether the specified component is visible by default. The default
* visibility is used when a page is displayed for the first time and on
* subsequent requests until the visibility of a component is changed
* explicitly with {@link Component#setVisible
* Component.setVisible}.
*
* <p> When a component is first added to a page, it is visible.
@ -1089,7 +1128,7 @@ public class Page extends BlockStylable implements Container {
* @param c a component whose visibility is to be set
* @param v <code>true</code> if the component is visible;
* <code>false</code> otherwise.
* @see Component#setVisible Component.setVisible
* @see Component#setVisible Component.setVisible
* @see Component#register Component.register
*/
public void setVisibleDefault(Component c, boolean v) {
@ -1105,7 +1144,8 @@ public class Page extends BlockStylable implements Container {
}
/**
* The global name of the parameter <code>name</code> in the component
* The global name of the parameter
* <code>name</code> in the component
* <code>c</code>.
*/
public String parameterName(Component c, String name) {
@ -1117,7 +1157,8 @@ public class Page extends BlockStylable implements Container {
}
/**
* The global name of the parameter <code>name</code>.
* The global name of the parameter
* <code>name</code>.
*/
public String parameterName(String name) {
return parameterName(null, name);
@ -1125,7 +1166,6 @@ public class Page extends BlockStylable implements Container {
void reset(final PageState ps, Component cmpnt) {
Traversal resetter = new Traversal() {
protected void act(Component c) {
Collection cp = getComponentParameters(c);
if (cp != null) {
@ -1142,8 +1182,8 @@ public class Page extends BlockStylable implements Container {
}
/**
* Return the prefix that is prepended to each component's state
* parameters to keep them unique.
* Return the prefix that is prepended to each component's state parameters
* to keep them unique.
*/
private final String componentPrefix(Component c) {
if (c == null) {
@ -1186,7 +1226,7 @@ public class Page extends BlockStylable implements Container {
private static String NAME = "name";
/**
* Produces an XML fragment that captures the layout of this page.
* Produces an XML fragment that captures the layout of this page.
*/
private void showStructure(PageState s, Element root) {
final HttpServletRequest req = s.getRequest();
@ -1248,7 +1288,7 @@ public class Page extends BlockStylable implements Container {
parent.newChildElement("bebop:param", BEBOP_XML_NS);
param.addAttribute(NAME, unmangle(p.getName()));
param.addAttribute("defaultValue",
String.valueOf(req.getParameter(p.getName())));
String.valueOf(req.getParameter(p.getName())));
param.addAttribute("currentValue", String.valueOf(s.getValue(p)));
}
}
@ -1267,21 +1307,21 @@ public class Page extends BlockStylable implements Container {
}
/**
* return a string that represents an ordered list of component
* ids used on the page. For situations where only the
* components present is of importance, this may be used
* by implementations of hashCode & equals
* return a string that represents an ordered list of component ids used on
* the page. For situations where only the components present is of
* importance, this may be used by implementations of hashCode & equals
*
* @return
*/
public String getComponentString() {
Iterator it = m_componentMap.keySet().iterator();
/*int hash = 0;
while (it.hasNext()) {
String componentId = (String)it.next();
s_log.debug("component id = " + componentId);
hash = hash | componentId.hashCode();
s_log.debug("hash so far = " + hash);
}*/
while (it.hasNext()) {
String componentId = (String)it.next();
s_log.debug("component id = " + componentId);
hash = hash | componentId.hashCode();
s_log.debug("hash so far = " + hash);
}*/
Date start = new Date();
StringBuffer hashString = new StringBuffer();
@ -1290,7 +1330,7 @@ public class Page extends BlockStylable implements Container {
hashString.append(componentId);
}
s_log.debug("Time to create hashCode for page: " + (new Date().getTime() - start.
getTime()));
getTime()));
return hashString.toString();