Author: ehillenius Date: Wed Jun 6 16:58:59 2007 New Revision: 544999 URL: http://svn.apache.org/viewvc?view=rev&rev=544999 Log: sorted members and minor cleanup
Modified: incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/Component.java Modified: incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/Component.java URL: http://svn.apache.org/viewvc/incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/Component.java?view=diff&rev=544999&r1=544998&r2=544999 ============================================================================== --- incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/Component.java (original) +++ incubator/wicket/trunk/jdk-1.4/wicket/src/main/java/org/apache/wicket/Component.java Wed Jun 6 16:58:59 2007 @@ -264,24 +264,6 @@ } /** - * Undo change for component border property - * - * @author ivaynberg - */ - private class ComponentBorderChange extends Change - { - private static final long serialVersionUID = 1L; - - private final IComponentBorder old = getComponentBorder(); - - public void undo() - { - setComponentBorder(old); - } - - } - - /** * Generic component visitor interface for component traversals. */ public static interface IVisitor @@ -316,11 +298,11 @@ } /** - * Change object for undoing removal of behavior + * Change object for undoing addition of behavior * * @author Igor Vaynberg (ivaynberg) */ - private final class RemovedBehaviorChange extends Change + private final class AddedBehaviorChange extends Change { private static final long serialVersionUID = 1L; @@ -332,33 +314,51 @@ * * @param behavior */ - public RemovedBehaviorChange(IBehavior behavior) + public AddedBehaviorChange(IBehavior behavior) { this.behavior = behavior; } + public String toString() + { + return "[" + getClass().getName() + " behavior=" + behavior.toString() + "]"; + } + public void undo() { - if (behaviors == null) + behaviors.remove(behavior); + if (behaviors.size() == 0) { - behaviors = new ArrayList(1); + behaviors = null; } - behaviors.add(behavior); } - public String toString() + } + + /** + * Undo change for component border property + * + * @author ivaynberg + */ + private class ComponentBorderChange extends Change + { + private static final long serialVersionUID = 1L; + + private final IComponentBorder old = getComponentBorder(); + + public void undo() { - return "[" + getClass().getName() + " behavior=" + behavior.toString() + "]"; + setComponentBorder(old); } } /** - * Change object for undoing addition of behavior + * Change object for undoing removal of behavior * * @author Igor Vaynberg (ivaynberg) */ - private final class AddedBehaviorChange extends Change + private final class RemovedBehaviorChange extends Change { private static final long serialVersionUID = 1L; @@ -370,23 +370,23 @@ * * @param behavior */ - public AddedBehaviorChange(IBehavior behavior) + public RemovedBehaviorChange(IBehavior behavior) { this.behavior = behavior; } - public void undo() + public String toString() { - behaviors.remove(behavior); - if (behaviors.size() == 0) - { - behaviors = null; - } + return "[" + getClass().getName() + " behavior=" + behavior.toString() + "]"; } - public String toString() + public void undo() { - return "[" + getClass().getName() + " behavior=" + behavior.toString() + "]"; + if (behaviors == null) + { + behaviors = new ArrayList(1); + } + behaviors.add(behavior); } } @@ -525,36 +525,59 @@ */ public static final Action RENDER = new Action(Action.RENDER); - /** True when a component is being auto-added */ - private static final int FLAG_AUTO = 0x0001; + /** meta data key for missing body tags logging. */ + private static final MetaDataKey BORDER_KEY = new MetaDataKey(IComponentBorder.class) + { + private static final long serialVersionUID = 1L; + }; - /** Flag for escaping HTML in model strings */ - private static final int FLAG_ESCAPE_MODEL_STRINGS = 0x0002; + /** Basic model IModelComparator implementation for normal object models */ + private static final IModelComparator defaultModelComparator = new IModelComparator() + { + private static final long serialVersionUID = 1L; - /** Flag for escaping HTML in model strings */ - private static final int FLAG_INHERITABLE_MODEL = 0x0004; + public boolean compare(Component component, Object b) + { + final Object a = component.getModelObject(); + if (a == null && b == null) + { + return true; + } + if (a == null || b == null) + { + return false; + } + return a.equals(b); + } + }; - /** Versioning boolean */ - private static final int FLAG_VERSIONED = 0x0008; + private static final int FLAG_AFTER_RENDERING = 0x8000000; - /** Visibility boolean */ - private static final int FLAG_VISIBLE = 0x0010; + /** True when a component is being auto-added */ + private static final int FLAG_AUTO = 0x0001; - /** Render tag boolean */ - private static final int FLAG_RENDER_BODY_ONLY = 0x0020; + private static final int FLAG_BEFORE_RENDERING_SUPER_CALL_VERIFIED = 0x1000000; - /** Ignore attribute modifiers */ - private static final int FLAG_IGNORE_ATTRIBUTE_MODIFIER = 0x0040; + private static final int FLAG_DETACHING = 0x80000000; /** True when a component is enabled for model updates and is reachable. */ private static final int FLAG_ENABLED = 0x0080; + /** Flag for escaping HTML in model strings */ + private static final int FLAG_ESCAPE_MODEL_STRINGS = 0x0002; + /** * Boolean whether this component was rendered at least once for tracking * changes. */ private static final int FLAG_HAS_BEEN_RENDERED = 0x1000; + /** Ignore attribute modifiers */ + private static final int FLAG_IGNORE_ATTRIBUTE_MODIFIER = 0x0040; + + /** Flag for escaping HTML in model strings */ + private static final int FLAG_INHERITABLE_MODEL = 0x0004; + /** * Internal indicator of whether this component may be rendered given the * current context's authorization. It overrides the visible flag in case @@ -578,21 +601,48 @@ private static final int FLAG_PLACEHOLDER = 0x8000; + /** Render tag boolean */ + private static final int FLAG_RENDER_BODY_ONLY = 0x0020; + + private static final int FLAG_RENDERING = 0x2000000; + + /** Versioning boolean */ + private static final int FLAG_VERSIONED = 0x0008; + + /** Visibility boolean */ + private static final int FLAG_VISIBLE = 0x0010; + + /** Log. */ + private static final Logger log = LoggerFactory.getLogger(Component.class); + + /** + * The name of attribute that will hold markup id + */ + private static final String MARKUP_ID_ATTR_NAME = "id"; + + /** + * Metadata key used to store/retrieve markup id + */ + private static MetaDataKey MARKUP_ID_KEY = new MetaDataKey(String.class) + { + + private static final long serialVersionUID = 1L; + + }; + private static final long serialVersionUID = 1L; /** Reserved subclass-definable flag bit */ protected static final int FLAG_RESERVED1 = 0x0100; - /** Reserved subclass-definable flag bit */ protected static final int FLAG_RESERVED2 = 0x0200; /** Reserved subclass-definable flag bit */ protected static final int FLAG_RESERVED3 = 0x0400; - /** Reserved subclass-definable flag bit */ protected static final int FLAG_RESERVED4 = 0x0800; - /** Reserved subclass-definable flag bit */ protected static final int FLAG_RESERVED5 = 0x10000; + /** Reserved subclass-definable flag bit */ protected static final int FLAG_RESERVED6 = 0x20000; @@ -602,31 +652,6 @@ /** Reserved subclass-definable flag bit */ protected static final int FLAG_RESERVED8 = 0x80000; - static final int FLAG_ATTACH_SUPER_CALL_VERIFIED = 0x10000000; - static final int FLAG_ATTACHED = 0x20000000; - static final int FLAG_ATTACHING = 0x40000000; - private static final int FLAG_DETACHING = 0x80000000; - - private static final int FLAG_BEFORE_RENDERING_SUPER_CALL_VERIFIED = 0x1000000; - private static final int FLAG_RENDERING = 0x2000000; - private static final int FLAG_AFTER_RENDERING = 0x8000000; - - - /** meta data key for missing body tags logging. */ - private static final MetaDataKey BORDER_KEY = new MetaDataKey(IComponentBorder.class) - { - private static final long serialVersionUID = 1L; - }; - - /** - * meta data key for line precise error logging for the moment of - * construction. Made package private for access in [EMAIL PROTECTED] Page} - */ - static final MetaDataKey CONSTRUCTED_AT_KEY = new MetaDataKey(String.class) - { - private static final long serialVersionUID = 1L; - }; - /** * Meta data key for line precise error logging for the moment of addition. * Made package private for access in [EMAIL PROTECTED] MarkupContainer} and @@ -637,35 +662,20 @@ private static final long serialVersionUID = 1L; }; - /** Basic model IModelComparator implementation for normal object models */ - private static final IModelComparator defaultModelComparator = new IModelComparator() + /** + * meta data key for line precise error logging for the moment of + * construction. Made package private for access in [EMAIL PROTECTED] Page} + */ + static final MetaDataKey CONSTRUCTED_AT_KEY = new MetaDataKey(String.class) { private static final long serialVersionUID = 1L; - - public boolean compare(Component component, Object b) - { - final Object a = component.getModelObject(); - if (a == null && b == null) - { - return true; - } - if (a == null || b == null) - { - return false; - } - return a.equals(b); - } }; - /** Log. */ - private static final Logger log = LoggerFactory.getLogger(Component.class); + static final int FLAG_ATTACH_SUPER_CALL_VERIFIED = 0x10000000; - /** - * The name of attribute that will hold markup id - */ - private static final String MARKUP_ID_ATTR_NAME = "id"; + static final int FLAG_ATTACHED = 0x20000000; - private static final long serialVersionUID = 1L; + static final int FLAG_ATTACHING = 0x40000000; /** List of behaviors to be applied for this Component */ private ArrayList behaviors = null; @@ -682,9 +692,6 @@ */ private MetaDataEntry[] metaData; - /** The model for this component. */ - IModel model; - /** Any parent container. */ private MarkupContainer parent; @@ -695,6 +702,9 @@ */ int markupIndex = -1; + /** The model for this component. */ + IModel model; + /** * Constructor. All components have names. A component's id cannot be null. * This is the minimal constructor of component. It does not register a @@ -785,38 +795,68 @@ } /** - * Removes behavior from component - * - * @param behavior - * behavior to remove - * - * @return this (to allow method call chaining) + * Called on very component after the page is renderd It will call + * onAfterRender for it self and its childeren. */ - public Component remove(final IBehavior behavior) + public final void afterRender() { - if (behavior == null) + // if the component has been previously attached via attach() + // detach it now + try { - throw new IllegalArgumentException("Argument `behavior` cannot be null"); + setFlag(FLAG_AFTER_RENDERING, true); + onAfterRender(); + getApplication().notifyComponentOnAfterRenderListeners(this); + if (getFlag(FLAG_AFTER_RENDERING)) + { + throw new IllegalStateException( + Component.class.getName() + + " has not been properly detached. Something in the hierarchy of " + + getClass().getName() + + " has not called super.onAfterRender() in the override of onAfterRender() method"); + } + // always detach children because components can be attached + // independently of their parents + onAfterRenderChildren(); } - if (behaviors == null || !behaviors.contains(behavior)) + finally { - throw new IllegalStateException( - "Tried to remove a behavior that was not added to the component. Behavior: " - + behavior.toString()); + // this flag must always be set to false. + setFlag(FLAG_RENDERING, false); } + } - if (!behavior.isTemporary()) - { - addStateChange(new RemovedBehaviorChange(behavior)); - } - behaviors.remove(behavior); + /** + * Attaches the component. This is called when the page is starting to be + * used for rendering or when a component listener call is executed on it. + */ + public final void attach() + { + internalAttach2(); + } - if (behaviors.size() == 0) + /** + * Called for every component when the page is getting to be rendered. it + * will call onBeforeRender for this component and all the child components + */ + public final void beforeRender() + { + if (!getFlag(FLAG_RENDERING)) { - behaviors = null; + setFlag(FLAG_BEFORE_RENDERING_SUPER_CALL_VERIFIED, false); + onBeforeRender(); + getApplication().notifyComponentOnBeforeRenderListeners(this); + if (!getFlag(FLAG_BEFORE_RENDERING_SUPER_CALL_VERIFIED)) + { + throw new IllegalStateException( + Component.class.getName() + + " has not been properly rendered. Something in the hierarchy of " + + getClass().getName() + + " has not called super.onBeforeRender() in the override of onBeforeRender() method"); + } + onBeforeRenderChildren(); + setFlag(FLAG_RENDERING, true); } - - return this; } /** @@ -843,6 +883,77 @@ } /** + * Detaches the component. This is called at the end of the request for all + * the pages that are touched in that request. + */ + public final void detach() + { + // if the component has been previously attached via attach() + // detach it now + setFlag(FLAG_DETACHING, true); + onDetach(); + if (getFlag(FLAG_DETACHING)) + { + throw new IllegalStateException(Component.class.getName() + + " has not been properly detached. Something in the hierarchy of " + + getClass().getName() + + " has not called super.onDetach() in the override of onDetach() method"); + } + setFlag(FLAG_ATTACHED, false); + + // always detach models because they can be attached without the + // component. eg component has a compoundpropertymodel and one of its + // children component's getmodelobject is called + detachModels(); + + // always detach children because components can be attached + // independently of their parents + detachChildren(); + + // reset the model to null when the current model is a IWrapModel and + // the model that created it/wrapped in it is a IComponentInheritedModel + // The model will be created next time. + if (getFlag(FLAG_INHERITABLE_MODEL)) + { + model = null; + setFlag(FLAG_INHERITABLE_MODEL, false); + } + } + + /** + * THIS IS WICKET INTERNAL ONLY. DO NOT USE IT. + * + * Traverses all behaviors and calls detachModel() on them. This is needed + * to cleanup behavior after render. This method is necessary for + * [EMAIL PROTECTED] AjaxRequestTarget} to be able to cleanup component's behaviors + * after header contribution has been done (which is separated from + * component render). + */ + public final void detachBehaviors() + { + if (behaviors != null) + { + for (Iterator i = behaviors.iterator(); i.hasNext();) + { + IBehavior behavior = (IBehavior)i.next(); + if (isBehaviorAccepted(behavior)) + { + /* + * TODO eelco: shouldnt we detach model always, accepted or + * not? what if this method returns true during render, but + * false here - something can go undetached + */ + behavior.detach(this); + } + if (behavior.isTemporary()) + { + i.remove(); + } + } + } + } + + /** * Detaches all models */ public void detachModels() @@ -959,6 +1070,14 @@ } /** + * @return component border assigned to this component, or null if none + */ + public final IComponentBorder getComponentBorder() + { + return (IComponentBorder)getMetaData(BORDER_KEY); + } + + /** * @return nothing, will always throw an exception. Use * [EMAIL PROTECTED] #getConverter(Class)} instead. * @deprecated To be removed. Please use/ override @@ -1011,6 +1130,14 @@ } /** + * @return Innermost model for this component + */ + public final IModel getInnermostModel() + { + return getInnermostModel(getModel()); + } + + /** * Gets the locale for the session holding this component. * * @return The locale for the session holding this component @@ -1085,16 +1212,6 @@ return markupId; } - final boolean hasMarkupIdMetaData() - { - return getMetaData(MARKUP_ID_KEY) != null; - } - - final void setMarkupIdMetaData(String markupId) - { - setMetaData(MARKUP_ID_KEY, markupId); - } - /** * Gets metadata for this component using the given key. * @@ -1185,6 +1302,18 @@ } /** + * Gets whether or not component will output id attribute into the markup. + * id attribute will be set to the value returned from + * [EMAIL PROTECTED] Component#getMarkupId()}. + * + * @return whether or not component will output id attribute into the markup + */ + public final boolean getOutputMarkupId() + { + return getFlag(FLAG_OUTPUT_MARKUP_ID); + } + + /** * Gets the page holding this component. * * @return The page holding this component @@ -1427,6 +1556,24 @@ } /** + * @deprecated + */ + // TODO remove after deprecation release + public final void internalAttach() + { + throw new UnsupportedOperationException(); + } + + /** + * @deprecated + */ + // TODO remove after deprecation release + public final void internalDetach() + { + throw new UnsupportedOperationException(); + } + + /** * Authorizes an action for a component. * * @param action @@ -1495,6 +1642,33 @@ } /** + * Returns if the component is stateless or not. It checks the stateless + * hint if that is false it returns directly false. If that is still true it + * checks all its behaviours if they can be stateless. + * + * @return whether the component is stateless. + */ + public final boolean isStateless() + { + if (!getStatelessHint()) + { + return false; + } + + final Iterator behaviors = getBehaviors().iterator(); + + while (behaviors.hasNext()) + { + IBehavior behavior = (IBehavior)behaviors.next(); + if (!behavior.getStatelessHint(this)) + { + return false; + } + } + return true; + } + + /** * @return True if this component is versioned */ public boolean isVersioned() @@ -1626,6 +1800,7 @@ getPage().getPageMap().redirectToInterceptPage(page); } + /** * Removes this component from its parent. It's important to remember that a * component that is removed cannot be referenced from the markup still. @@ -1641,6 +1816,42 @@ } /** + * Removes behavior from component + * + * @param behavior + * behavior to remove + * + * @return this (to allow method call chaining) + */ + public Component remove(final IBehavior behavior) + { + if (behavior == null) + { + throw new IllegalArgumentException("Argument `behavior` cannot be null"); + } + if (behaviors == null || !behaviors.contains(behavior)) + { + throw new IllegalStateException( + "Tried to remove a behavior that was not added to the component. Behavior: " + + behavior.toString()); + } + + if (!behavior.isTemporary()) + { + addStateChange(new RemovedBehaviorChange(behavior)); + } + behaviors.remove(behavior); + + if (behaviors.size() == 0) + { + behaviors = null; + } + + return this; + } + + + /** * Performs a render of this component as part of a Page level render * process. * <p> @@ -1915,97 +2126,24 @@ } /** - * [EMAIL PROTECTED] IBehavior#afterRender(Component)} Notify all behaviors that are - * assigned to this component that the component has rendered. + * Print to the web response what ever the component wants to contribute to + * the head section. Make sure that all attached behaviors are asked as + * well. + * <p> + * NOT intended for overriding by framework clients. Rather, use + * [EMAIL PROTECTED] IHeaderContributor#renderHead(org.apache.wicket.markup.html.IHeaderResponse)} + * </p> + * + * @param container + * The HtmlHeaderContainer */ - private void notifyBehaviorsComponentRendered() + public void renderHead(final HtmlHeaderContainer container) { - // notify the behaviors that component has been rendered - if (behaviors != null) + if (isVisible()) { - for (Iterator i = behaviors.iterator(); i.hasNext();) + if (this instanceof IHeaderContributor) { - IBehavior behavior = (IBehavior)i.next(); - if (isBehaviorAccepted(behavior)) - { - behavior.afterRender(this); - } - } - } - } - - /** - * [EMAIL PROTECTED] IBehavior#beforeRender(Component)} Notify all behaviors that are - * assigned to this component that the component is about to be rendered. - */ - private void notifyBehaviorsComponentBeforeRender() - { - if (behaviors != null) - { - for (Iterator i = behaviors.iterator(); i.hasNext();) - { - IBehavior behavior = (IBehavior)i.next(); - if (isBehaviorAccepted(behavior)) - { - behavior.beforeRender(this); - } - } - } - } - - /** - * THIS IS WICKET INTERNAL ONLY. DO NOT USE IT. - * - * Traverses all behaviors and calls detachModel() on them. This is needed - * to cleanup behavior after render. This method is necessary for - * [EMAIL PROTECTED] AjaxRequestTarget} to be able to cleanup component's behaviors - * after header contribution has been done (which is separated from - * component render). - */ - public final void detachBehaviors() - { - if (behaviors != null) - { - for (Iterator i = behaviors.iterator(); i.hasNext();) - { - IBehavior behavior = (IBehavior)i.next(); - if (isBehaviorAccepted(behavior)) - { - /* - * TODO eelco: shouldnt we detach model always, accepted or - * not? what if this method returns true during render, but - * false here - something can go undetached - */ - behavior.detach(this); - } - if (behavior.isTemporary()) - { - i.remove(); - } - } - } - } - - - /** - * Print to the web response what ever the component wants to contribute to - * the head section. Make sure that all attached behaviors are asked as - * well. - * <p> - * NOT intended for overriding by framework clients. Rather, use - * [EMAIL PROTECTED] IHeaderContributor#renderHead(org.apache.wicket.markup.html.IHeaderResponse)} - * </p> - * - * @param container - * The HtmlHeaderContainer - */ - public void renderHead(final HtmlHeaderContainer container) - { - if (isVisible()) - { - if (this instanceof IHeaderContributor) - { - ((IHeaderContributor)this).renderHead(container.getHeaderResponse()); + ((IHeaderContributor)this).renderHead(container.getHeaderResponse()); } // Ask all behaviors if they have something to contribute to the @@ -2056,7 +2194,6 @@ parent.replace(replacement); } - /** * @param component * The component to compare with @@ -2090,6 +2227,25 @@ } /** + * Assigns a component border to this component. If called with + * <code>null</code> any previous border will be cleared. + * + * @param border + * componnet border to assign, or <code>null</code> to clear + * any previous + * @return component for chaining + */ + public final Component setComponentBorder(final IComponentBorder border) + { + if (!Objects.equal(getComponentBorder(), border)) + { + addStateChange(new ComponentBorderChange()); + } + setMetaData(BORDER_KEY, border); + return this; + } + + /** * Sets whether this component is enabled. Specific components may decide to * implement special behavior that uses this property, like web form * components that add a disabled='disabled' attribute when enabled is @@ -2246,15 +2402,38 @@ } /** - * Gets whether or not component will output id attribute into the markup. - * id attribute will be set to the value returned from - * [EMAIL PROTECTED] Component#getMarkupId()}. + * Render a placeholder tag when the component is not visible. The tag is of + * form: <componenttag style="display:none;" id="componentid"/>. This + * method will also call <code>setOutputMarkupId(true)</code>. * - * @return whether or not component will output id attribute into the markup + * This is useful, for example, in ajax situations where the component + * starts out invisible and then becomes visible through an ajax update. + * With a placeholder tag already in the markup you do not need to repaint + * this component's parent, instead you can repaint the component directly. + * + * When this method is called with parameter <code>false</code> the + * outputmarkupid flag is not reverted to false. + * + * @param outputTag + * @return this for chaining */ - public final boolean getOutputMarkupId() + public final Component setOutputMarkupPlaceholderTag(final boolean outputTag) { - return getFlag(FLAG_OUTPUT_MARKUP_ID); + if (outputTag != getFlag(FLAG_PLACEHOLDER)) + { + if (outputTag) + { + setOutputMarkupId(true); + setFlag(FLAG_PLACEHOLDER, true); + } + else + { + setFlag(FLAG_PLACEHOLDER, false); + // I think it's better to not setOutputMarkupId to false... + // user can do it if we want + } + } + return this; } /** @@ -2267,6 +2446,7 @@ getRequestCycle().setRedirect(redirect); } + /** * If false the component's tag will be printed as well as its body (which * is default). If true only the body will be printed, but not the @@ -2283,33 +2463,6 @@ } /** - * @return component border assigned to this component, or null if none - */ - public final IComponentBorder getComponentBorder() - { - return (IComponentBorder)getMetaData(BORDER_KEY); - } - - /** - * Assigns a component border to this component. If called with - * <code>null</code> any previous border will be cleared. - * - * @param border - * componnet border to assign, or <code>null</code> to clear - * any previous - * @return component for chaining - */ - public final Component setComponentBorder(final IComponentBorder border) - { - if (!Objects.equal(getComponentBorder(), border)) - { - addStateChange(new ComponentBorderChange()); - } - setMetaData(BORDER_KEY, border); - return this; - } - - /** * Sets the page that will respond to this request * * @param cls @@ -2380,76 +2533,6 @@ return this; } - - /** - * Render a placeholder tag when the component is not visible. The tag is of - * form: <componenttag style="display:none;" id="componentid"/>. This - * method will also call <code>setOutputMarkupId(true)</code>. - * - * This is useful, for example, in ajax situations where the component - * starts out invisible and then becomes visible through an ajax update. - * With a placeholder tag already in the markup you do not need to repaint - * this component's parent, instead you can repaint the component directly. - * - * When this method is called with parameter <code>false</code> the - * outputmarkupid flag is not reverted to false. - * - * @param outputTag - * @return this for chaining - */ - public final Component setOutputMarkupPlaceholderTag(final boolean outputTag) - { - if (outputTag != getFlag(FLAG_PLACEHOLDER)) - { - if (outputTag) - { - setOutputMarkupId(true); - setFlag(FLAG_PLACEHOLDER, true); - } - else - { - setFlag(FLAG_PLACEHOLDER, false); - // I think it's better to not setOutputMarkupId to false... - // user can do it if we want - } - } - return this; - } - - /** - * Traverses all parent components of the given class in this container, - * calling the visitor's visit method at each one. - * - * @param c - * Class - * @param visitor - * The visitor to call at each parent of the given type - * @return First non-null value returned by visitor callback - */ - public final Object visitParents(final Class c, final IVisitor visitor) - { - // Start here - Component current = this; - - // Walk up containment hierarchy - while (current != null) - { - // Is current an instance of this class? - if (c.isInstance(current)) - { - final Object object = visitor.component(current); - if (object != IVisitor.CONTINUE_TRAVERSAL) - { - return object; - } - } - - // Check parent - current = current.getParent(); - } - return null; - } - /** * Gets the string representation of this component. * @@ -2511,18 +2594,19 @@ } /** - * Returns a URL that references the given request target. - * - * @see RequestCycle#urlFor(IRequestTarget) - * - * @param requestTarget - * the request target to reference + * Gets a URL for the listener interface on a behaviour (e.g. + * IBehaviorListener on AjaxPagingNavigationBehavior). * - * @return a URL that references the given request target + * @param behaviour + * The behaviour that the URL should point to + * @param listener + * The listener interface that the URL should call + * @return The URL */ - public final CharSequence urlFor(final IRequestTarget requestTarget) + public final CharSequence urlFor(final IBehavior behaviour, + final RequestListenerInterface listener) { - return getRequestCycle().urlFor(requestTarget); + return getRequestCycle().urlFor(this, behaviour, listener); } /** @@ -2550,31 +2634,30 @@ } /** - * Gets a URL for the listener interface (e.g. ILinkListener). + * Returns a URL that references the given request target. * - * @param listener - * The listener interface that the URL should call - * @return The URL - */ - public final CharSequence urlFor(final RequestListenerInterface listener) - { - return getRequestCycle().urlFor(this, listener); - } + * @see RequestCycle#urlFor(IRequestTarget) + * + * @param requestTarget + * the request target to reference + * + * @return a URL that references the given request target + */ + public final CharSequence urlFor(final IRequestTarget requestTarget) + { + return getRequestCycle().urlFor(requestTarget); + } /** - * Gets a URL for the listener interface on a behaviour (e.g. - * IBehaviorListener on AjaxPagingNavigationBehavior). + * Gets a URL for the listener interface (e.g. ILinkListener). * - * @param behaviour - * The behaviour that the URL should point to * @param listener * The listener interface that the URL should call * @return The URL */ - public final CharSequence urlFor(final IBehavior behaviour, - final RequestListenerInterface listener) + public final CharSequence urlFor(final RequestListenerInterface listener) { - return getRequestCycle().urlFor(this, behaviour, listener); + return getRequestCycle().urlFor(this, listener); } /** @@ -2593,6 +2676,40 @@ } /** + * Traverses all parent components of the given class in this container, + * calling the visitor's visit method at each one. + * + * @param c + * Class + * @param visitor + * The visitor to call at each parent of the given type + * @return First non-null value returned by visitor callback + */ + public final Object visitParents(final Class c, final IVisitor visitor) + { + // Start here + Component current = this; + + // Walk up containment hierarchy + while (current != null) + { + // Is current an instance of this class? + if (c.isInstance(current)) + { + final Object object = visitor.component(current); + if (object != IVisitor.CONTINUE_TRAVERSAL) + { + return object; + } + } + + // Check parent + current = current.getParent(); + } + return null; + } + + /** * Registers a warning feedback message for this component. * * @param message @@ -2604,6 +2721,45 @@ } /** + * [EMAIL PROTECTED] IBehavior#beforeRender(Component)} Notify all behaviors that are + * assigned to this component that the component is about to be rendered. + */ + private void notifyBehaviorsComponentBeforeRender() + { + if (behaviors != null) + { + for (Iterator i = behaviors.iterator(); i.hasNext();) + { + IBehavior behavior = (IBehavior)i.next(); + if (isBehaviorAccepted(behavior)) + { + behavior.beforeRender(this); + } + } + } + } + + /** + * [EMAIL PROTECTED] IBehavior#afterRender(Component)} Notify all behaviors that are + * assigned to this component that the component has rendered. + */ + private void notifyBehaviorsComponentRendered() + { + // notify the behaviors that component has been rendered + if (behaviors != null) + { + for (Iterator i = behaviors.iterator(); i.hasNext();) + { + IBehavior behavior = (IBehavior)i.next(); + if (isBehaviorAccepted(behavior)) + { + behavior.afterRender(this); + } + } + } + } + + /** * Adds state change to page. * * @param change @@ -2668,6 +2824,30 @@ } /** + * Checks whether the hierarchy may be changed at all, and throws an + * exception if this is not the case. + * + * @param component + * the component which is about to be added or removed + */ + protected void checkHierarchyChange(final Component component) + { + // Throw exception if modification is attempted during rendering + if (!component.isAuto() && getFlag(FLAG_RENDERING)) + { + throw new WicketRuntimeException( + "Cannot modify component hierarchy during render phase"); + } + + // Throw exception if modification is attempted during attach + if (getFlag(FLAG_ATTACHING)) + { + throw new WicketRuntimeException( + "Cannot modify component hierarchy during attach phase"); + } + } + + /** * Detaches the model for this component if it is detachable. */ protected void detachModel() @@ -2778,6 +2958,29 @@ } /** + * Finds the innermost IModel object for an IModel that might contain nested + * IModel(s). + * + * @param model + * The model + * @return The innermost (most nested) model + */ + protected final IModel getInnermostModel(final IModel model) + { + IModel nested = model; + while (nested != null && nested instanceof IWrapModel) + { + final IModel next = ((IWrapModel)nested).getWrappedModel(); + if (nested == next) + { + throw new WicketRuntimeException("Model for " + nested + " is self-referential"); + } + nested = next; + } + return nested; + } + + /** * Gets the value defaultModelComparator. Implementations of this interface * can be used in the Component.getComparator() for testing the current * value of the components model data with the new value that is given. @@ -2790,6 +2993,18 @@ } /** + * Returns whether the component can be stateless. Being able to be + * stateless doesn't necessary mean, that the component should be stateless. + * Whether the component should be stateless depends on + * + * @return whether the component can be stateless + */ + protected boolean getStatelessHint() + { + return true; + } + + /** * Called when a null model is about to be retrieved in order to allow a * subclass to provide an initial model. This gives FormComponent, for * example, an opportunity to instantiate a model on the fly using the @@ -2869,6 +3084,14 @@ } /** + * @return true if this component is attached + */ + protected final boolean isAttached() + { + return getFlag(FLAG_ATTACHED); + } + + /** * Components are allowed to reject behavior modifiers. * * @param behavior @@ -2895,227 +3118,10 @@ { return this.getFlag(FLAG_IGNORE_ATTRIBUTE_MODIFIER); } - - /** - * Returns whether the component can be stateless. Being able to be - * stateless doesn't necessary mean, that the component should be stateless. - * Whether the component should be stateless depends on - * - * @return whether the component can be stateless - */ - protected boolean getStatelessHint() - { - return true; - } - - /** - * Returns if the component is stateless or not. It checks the stateless - * hint if that is false it returns directly false. If that is still true it - * checks all its behaviours if they can be stateless. - * - * @return whether the component is stateless. - */ - public final boolean isStateless() - { - if (!getStatelessHint()) - { - return false; - } - - final Iterator behaviors = getBehaviors().iterator(); - - while (behaviors.hasNext()) - { - IBehavior behavior = (IBehavior)behaviors.next(); - if (!behavior.getStatelessHint(this)) - { - return false; - } - } - return true; - } - - /** - * Attaches any child components - * - * This method is here only for [EMAIL PROTECTED] MarkupContainer}. It is broken out - * of [EMAIL PROTECTED] #onBeforeRender()} so we can guarantee that it executes as the - * last in onAttach() chain no matter where user places the - * <code>super.onAttach()</code> call - */ - void internalAttach2() - { - if (!getFlag(FLAG_ATTACHED)) - { - setFlag(FLAG_ATTACHING, true); - setFlag(FLAG_ATTACH_SUPER_CALL_VERIFIED, false); - onAttach(); - if (!getFlag(FLAG_ATTACH_SUPER_CALL_VERIFIED)) - { - throw new IllegalStateException( - "Component " - + this - + " of type " - + getClass().getName() - + " has not been properly attached. " - + "Something in its class hierarchy has failed to call super.onAttach() in an override of onAttach() method"); - } - setFlag(FLAG_ATTACHING, false); - setFlag(FLAG_ATTACHED, true); - } - } - - /** - * Attaches the component. This is called when the page is starting to be - * used for rendering or when a component listener call is executed on it. - */ - public final void attach() - { - internalAttach2(); - } - - /** - * @return true if this component is attached - */ - protected final boolean isAttached() - { - return getFlag(FLAG_ATTACHED); - } - - /** - * Detaches any child components - * - * @see [EMAIL PROTECTED] #attachChildren()} - */ - void detachChildren() - { - - } - - /** - * Detaches the component. This is called at the end of the request for all - * the pages that are touched in that request. - */ - public final void detach() - { - // if the component has been previously attached via attach() - // detach it now - setFlag(FLAG_DETACHING, true); - onDetach(); - if (getFlag(FLAG_DETACHING)) - { - throw new IllegalStateException(Component.class.getName() - + " has not been properly detached. Something in the hierarchy of " - + getClass().getName() - + " has not called super.onDetach() in the override of onDetach() method"); - } - setFlag(FLAG_ATTACHED, false); - - // always detach models because they can be attached without the - // component. eg component has a compoundpropertymodel and one of its - // children component's getmodelobject is called - detachModels(); - - // always detach children because components can be attached - // independently of their parents - detachChildren(); - - // reset the model to null when the current model is a IWrapModel and - // the model that created it/wrapped in it is a IComponentInheritedModel - // The model will be created next time. - if (getFlag(FLAG_INHERITABLE_MODEL)) - { - model = null; - setFlag(FLAG_INHERITABLE_MODEL, false); - } - } - - /** - * Called to allow a component to attach resources for use. - * - * Overrides of this method MUST call the super implementation, the most - * logical place to do this is the first line of the override method. - * - */ - protected void onAttach() - { - setFlag(FLAG_ATTACH_SUPER_CALL_VERIFIED, true); - } - - /** - * Called for every component when the page is getting to be rendered. it - * will call onBeforeRender for this component and all the child components - */ - public final void beforeRender() - { - if (!getFlag(FLAG_RENDERING)) - { - setFlag(FLAG_BEFORE_RENDERING_SUPER_CALL_VERIFIED, false); - onBeforeRender(); - getApplication().notifyComponentOnBeforeRenderListeners(this); - if (!getFlag(FLAG_BEFORE_RENDERING_SUPER_CALL_VERIFIED)) - { - throw new IllegalStateException( - Component.class.getName() - + " has not been properly rendered. Something in the hierarchy of " - + getClass().getName() - + " has not called super.onBeforeRender() in the override of onBeforeRender() method"); - } - onBeforeRenderChildren(); - setFlag(FLAG_RENDERING, true); - } - } - - /** - * Called just before a component is rendered. If you override this, you - * *must* call super.onBeforeRender() within your implementation. - */ - protected void onBeforeRender() - { - setFlag(FLAG_BEFORE_RENDERING_SUPER_CALL_VERIFIED, true); - } - - /** - * This method is here only for [EMAIL PROTECTED] MarkupContainer}. It is broken out - * of [EMAIL PROTECTED] #onBeforeRender()} so we can guarantee that it executes as the - * last in onAttach() chain no matter where user places the - * <code>super.onAttach()</code> call - */ - void onBeforeRenderChildren() - { - // noop - } - - /** - * Called on very component after the page is renderd It will call - * onAfterRender for it self and its childeren. - */ - public final void afterRender() - { - // if the component has been previously attached via attach() - // detach it now - try - { - setFlag(FLAG_AFTER_RENDERING, true); - onAfterRender(); - getApplication().notifyComponentOnAfterRenderListeners(this); - if (getFlag(FLAG_AFTER_RENDERING)) - { - throw new IllegalStateException( - Component.class.getName() - + " has not been properly detached. Something in the hierarchy of " - + getClass().getName() - + " has not called super.onAfterRender() in the override of onAfterRender() method"); - } - // always detach children because components can be attached - // independently of their parents - onAfterRenderChildren(); - } - finally - { - // this flag must always be set to false. - setFlag(FLAG_RENDERING, false); - } + + protected final boolean isRenderAllowed() + { + return getFlag(FLAG_IS_RENDER_ALLOWED); } /** @@ -3126,9 +3132,34 @@ setFlag(FLAG_AFTER_RENDERING, false); } - void onAfterRenderChildren() + /** + * Called to allow a component to attach resources for use. + * + * Overrides of this method MUST call the super implementation, the most + * logical place to do this is the first line of the override method. + * + */ + protected void onAttach() + { + setFlag(FLAG_ATTACH_SUPER_CALL_VERIFIED, true); + } + + /** + * Called just before a component is rendered. If you override this, you + * *must* call super.onBeforeRender() within your implementation. + */ + protected void onBeforeRender() + { + setFlag(FLAG_BEFORE_RENDERING_SUPER_CALL_VERIFIED, true); + } + + /** + * @deprecated use onAttach() instead + */ + // TODO remove after the deprecation release + protected final void onBeginRequest() { - // noop + throw new UnsupportedOperationException(); } /** @@ -3176,6 +3207,15 @@ } /** + * @deprecated use onDetach() instead + */ + // TODO remove after the deprecation release + protected final void onEndRequest() + { + throw new UnsupportedOperationException(); + } + + /** * Called anytime a model is changed after the change has occurred */ protected void onModelChanged() @@ -3302,6 +3342,15 @@ } /** + * @param auto + * True to put component into auto-add mode + */ + protected final void setAuto(final boolean auto) + { + setFlag(FLAG_AUTO, auto); + } + + /** * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT! * * @param flag @@ -3363,6 +3412,32 @@ } /** + * @param model + * The model to wrap if need be + * @return The wrapped model + */ + protected final IModel wrap(final IModel model) + { + if (model instanceof IComponentAssignedModel) + { + return ((IComponentAssignedModel)model).wrapOnAssignment(this); + } + else + { + return model; + } + } + + /** + * Detaches any child components + * + * @see [EMAIL PROTECTED] #attachChildren()} + */ + void detachChildren() + { + } + + /** * Gets the component at the given path. * * @param path @@ -3377,8 +3452,43 @@ return this; } throw new IllegalArgumentException( - exceptionMessage("Component is not a container and so does not contain the path " - + path)); + exceptionMessage("Component is not a container and so does " + + "not contain the path " + path)); + } + + final boolean hasMarkupIdMetaData() + { + return getMetaData(MARKUP_ID_KEY) != null; + } + + /** + * Attaches any child components + * + * This method is here only for [EMAIL PROTECTED] MarkupContainer}. It is broken out + * of [EMAIL PROTECTED] #onBeforeRender()} so we can guarantee that it executes as the + * last in onAttach() chain no matter where user places the + * <code>super.onAttach()</code> call + */ + void internalAttach2() + { + if (!getFlag(FLAG_ATTACHED)) + { + setFlag(FLAG_ATTACHING, true); + setFlag(FLAG_ATTACH_SUPER_CALL_VERIFIED, false); + onAttach(); + if (!getFlag(FLAG_ATTACH_SUPER_CALL_VERIFIED)) + { + throw new IllegalStateException( + "Component " + + this + + " of type " + + getClass().getName() + + " has not been properly attached. " + + "Something in its class hierarchy has failed to call super.onAttach() in an override of onAttach() method"); + } + setFlag(FLAG_ATTACHING, false); + setFlag(FLAG_ATTACHED, true); + } } /** @@ -3397,9 +3507,18 @@ return false; } - protected final boolean isRenderAllowed() + void onAfterRenderChildren() + { + } + + /** + * This method is here only for [EMAIL PROTECTED] MarkupContainer}. It is broken out + * of [EMAIL PROTECTED] #onBeforeRender()} so we can guarantee that it executes as the + * last in onAttach() chain no matter where user places the + * <code>super.onAttach()</code> call + */ + void onBeforeRenderChildren() { - return getFlag(FLAG_IS_RENDER_ALLOWED); } /** @@ -3451,32 +3570,6 @@ } /** - * @param auto - * True to put component into auto-add mode - */ - protected final void setAuto(final boolean auto) - { - setFlag(FLAG_AUTO, auto); - } - - /** - * @param model - * The model to wrap if need be - * @return The wrapped model - */ - protected final IModel wrap(final IModel model) - { - if (model instanceof IComponentAssignedModel) - { - return ((IComponentAssignedModel)model).wrapOnAssignment(this); - } - else - { - return model; - } - } - - /** * Sets the id of this component. This method is private because the only * time a component's id can be set is in its constructor. * @@ -3492,6 +3585,11 @@ this.id = id; } + final void setMarkupIdMetaData(String markupId) + { + setMetaData(MARKUP_ID_KEY, markupId); + } + /** * Sets the parent of a component. * @@ -3505,8 +3603,6 @@ log.debug("Replacing parent " + this.parent + " with " + parent); } this.parent = parent; - // - // resetHeadRendered(); } /** @@ -3517,106 +3613,5 @@ final void setRenderAllowed(boolean renderAllowed) { setFlag(FLAG_IS_RENDER_ALLOWED, renderAllowed); - } - - /** - * Finds the innermost IModel object for an IModel that might contain nested - * IModel(s). - * - * @param model - * The model - * @return The innermost (most nested) model - */ - protected final IModel getInnermostModel(final IModel model) - { - IModel nested = model; - while (nested != null && nested instanceof IWrapModel) - { - final IModel next = ((IWrapModel)nested).getWrappedModel(); - if (nested == next) - { - throw new WicketRuntimeException("Model for " + nested + " is self-referential"); - } - nested = next; - } - return nested; - } - - /** - * @return Innermost model for this component - */ - public final IModel getInnermostModel() - { - return getInnermostModel(getModel()); - } - - /** - * Metadata key used to store/retrieve markup id - */ - private static MetaDataKey MARKUP_ID_KEY = new MetaDataKey(String.class) - { - - private static final long serialVersionUID = 1L; - - }; - - /** - * @deprecated - */ - // TODO remove after deprecation release - public final void internalAttach() - { - throw new UnsupportedOperationException(); - } - - /** - * @deprecated - */ - // TODO remove after deprecation release - public final void internalDetach() - { - throw new UnsupportedOperationException(); - } - - /** - * @deprecated use onAttach() instead - */ - // TODO remove after the deprecation release - protected final void onBeginRequest() - { - throw new UnsupportedOperationException(); - } - - /** - * @deprecated use onDetach() instead - */ - // TODO remove after the deprecation release - protected final void onEndRequest() - { - throw new UnsupportedOperationException(); - } - - /** - * Checks whether the hierarchy may be changed at all, and throws an - * exception if this is not the case. - * - * @param component - * the component which is about to be added or removed - */ - protected void checkHierarchyChange(final Component component) - { - // Throw exception if modification is attempted during rendering - if (!component.isAuto() && getFlag(FLAG_RENDERING)) - { - throw new WicketRuntimeException( - "Cannot modify component hierarchy during render phase"); - } - - // Throw exception if modification is attempted during attach - if (getFlag(FLAG_ATTACHING)) - { - throw new WicketRuntimeException( - "Cannot modify component hierarchy during attach phase"); - } } }