001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.wicket;
018
019import java.io.Serializable;
020import java.util.Arrays;
021import java.util.Iterator;
022import java.util.List;
023import java.util.Locale;
024import java.util.Optional;
025
026import org.apache.wicket.ajax.IAjaxRegionMarkupIdProvider;
027import org.apache.wicket.application.IComponentInstantiationListener;
028import org.apache.wicket.authorization.Action;
029import org.apache.wicket.authorization.AuthorizationException;
030import org.apache.wicket.authorization.IAuthorizationStrategy;
031import org.apache.wicket.authorization.UnauthorizedActionException;
032import org.apache.wicket.authorization.strategies.page.SimplePageAuthorizationStrategy;
033import org.apache.wicket.behavior.Behavior;
034import org.apache.wicket.core.request.handler.BookmarkableListenerRequestHandler;
035import org.apache.wicket.core.request.handler.ListenerRequestHandler;
036import org.apache.wicket.core.request.handler.PageAndComponentProvider;
037import org.apache.wicket.core.util.lang.WicketObjects;
038import org.apache.wicket.core.util.string.ComponentStrings;
039import org.apache.wicket.event.Broadcast;
040import org.apache.wicket.event.IEvent;
041import org.apache.wicket.event.IEventSink;
042import org.apache.wicket.event.IEventSource;
043import org.apache.wicket.feedback.FeedbackDelay;
044import org.apache.wicket.feedback.FeedbackMessage;
045import org.apache.wicket.feedback.FeedbackMessages;
046import org.apache.wicket.feedback.IFeedback;
047import org.apache.wicket.feedback.IFeedbackContributor;
048import org.apache.wicket.markup.ComponentTag;
049import org.apache.wicket.markup.IMarkupFragment;
050import org.apache.wicket.markup.Markup;
051import org.apache.wicket.markup.MarkupCache;
052import org.apache.wicket.markup.MarkupElement;
053import org.apache.wicket.markup.MarkupException;
054import org.apache.wicket.markup.MarkupNotFoundException;
055import org.apache.wicket.markup.MarkupStream;
056import org.apache.wicket.markup.WicketTag;
057import org.apache.wicket.markup.head.IHeaderResponse;
058import org.apache.wicket.markup.head.StringHeaderItem;
059import org.apache.wicket.markup.html.IHeaderContributor;
060import org.apache.wicket.markup.html.form.Form;
061import org.apache.wicket.markup.html.form.FormComponent;
062import org.apache.wicket.markup.html.internal.HtmlHeaderContainer;
063import org.apache.wicket.markup.html.panel.DefaultMarkupSourcingStrategy;
064import org.apache.wicket.markup.html.panel.IMarkupSourcingStrategy;
065import org.apache.wicket.model.CompoundPropertyModel;
066import org.apache.wicket.model.IComponentAssignedModel;
067import org.apache.wicket.model.IComponentInheritedModel;
068import org.apache.wicket.model.IModel;
069import org.apache.wicket.model.IModelComparator;
070import org.apache.wicket.model.IWrapModel;
071import org.apache.wicket.protocol.http.WicketFilter;
072import org.apache.wicket.request.IRequestHandler;
073import org.apache.wicket.request.Request;
074import org.apache.wicket.request.Response;
075import org.apache.wicket.request.component.IRequestableComponent;
076import org.apache.wicket.request.component.IRequestablePage;
077import org.apache.wicket.request.cycle.RequestCycle;
078import org.apache.wicket.request.mapper.parameter.PageParameters;
079import org.apache.wicket.request.resource.ResourceReference;
080import org.apache.wicket.response.LazyStringResponse;
081import org.apache.wicket.settings.DebugSettings;
082import org.apache.wicket.settings.ExceptionSettings;
083import org.apache.wicket.util.IHierarchical;
084import org.apache.wicket.util.convert.IConverter;
085import org.apache.wicket.util.io.IClusterable;
086import org.apache.wicket.util.lang.Args;
087import org.apache.wicket.util.lang.Classes;
088import org.apache.wicket.util.string.PrependingStringBuffer;
089import org.apache.wicket.util.string.Strings;
090import org.apache.wicket.util.value.ValueMap;
091import org.apache.wicket.util.visit.IVisitFilter;
092import org.apache.wicket.util.visit.IVisitor;
093import org.apache.wicket.util.visit.Visit;
094import org.slf4j.Logger;
095import org.slf4j.LoggerFactory;
096
097
098/**
099 * Component serves as the highest level abstract base class for all components.
100 * 
101 * <ul>
102 * <li><b>Identity </b>- All Components must have a non-null id which is retrieved by calling
103 * getId(). The id must be unique within the {@link MarkupContainer} that holds the Component, but
104 * does not have to be globally unique or unique within a Page's component hierarchy.</li>
105 * <li><b>Hierarchy </b>- A component has a parent which can be retrieved with {@link #getParent()}.
106 * If a component is an instance of MarkupContainer, it may have children. In this way it has a
107 * place in the hierarchy of components contained on a given page.
108 * <p>
109 * The path from the Page at the root of the component hierarchy to a given Component is simply the
110 * concatenation with colon separators of each id along the way. For example, the path "a:b:c" would
111 * refer to the component named "c" inside the MarkupContainer named "b" inside the container named
112 * "a". The path to a component can be retrieved by calling {@link #getPath()}. To get a Component
113 * path relative to the page that contains it, you can call {@link #getPageRelativePath()}.</li>
114 * <li><b>LifeCycle </b>- Components participate in the following lifecycle phases:
115 * <ul>
116 * <li><b>Construction </b>- A Component is constructed with the Java language new operator.
117 * Children may be added during construction if the Component is a MarkupContainer.
118 * {@link IComponentInstantiationListener}s are notified of component instantiation.
119 * <p>
120 * {@link #onInitialize()} is called on the component as soon as the component is part of a page's
121 * component tree. At this state the component is able to access its markup.</li>
122 * <li><b>Request Handling </b>- An incoming request is processed by a protocol request handler such
123 * as {@link WicketFilter}. An associated Application object creates {@link Session},
124 * {@link Request} and {@link Response} objects for use by a given Component in updating its model
125 * and rendering a response. These objects are stored inside a container called {@link RequestCycle}
126 * which is accessible via {@link Component#getRequestCycle()}. The convenience methods
127 * {@link Component#getRequest()}, {@link Component#getResponse()} and
128 * {@link Component#getSession()} provide easy access to the contents of this container.</li>
129 * <li><b>Listener Invocation </b>- If the request references an {@link IRequestListener} on an
130 * existing Component (or one of its {@link Behavior}s, see below), that listener is notified,
131 * allowing arbitrary user code to handle events such as link clicks or form submits. Although
132 * arbitrary listeners are supported in Wicket, the need to implement a new class of listener is
133 * unlikely for a web application and even the need to implement a listener interface directly is
134 * highly discouraged. Instead, calls to listeners are routed through logic specific to the event,
135 * resulting in calls to user code through other overridable methods. See {@link Form} for an
136 * example of a component which listens for events via {@link IRequestListener}.</li>
137 * <li><b>Rendering </b>- Before a page or part of a page (in case of Ajax updates) is rendered, all
138 * containing components are able to prepare for rendering via two hook methods:
139 * {@link #onConfigure()} (regardless whether they are visible or not) and {@link #onBeforeRender()}
140 * (if visible only) . <br>
141 * A markup response is generated by the Component via {@link Component#render()}, which calls
142 * subclass implementation code contained in {@link Component#onRender()}. Once this phase begins, a
143 * Component becomes immutable. Attempts to alter the Component will result in a
144 * WicketRuntimeException.</li>
145 * <li><b>Detachment </b>- Each request cycle finishes by detaching all touched components.
146 * Subclasses should clean up their state by overriding {@link #onDetach()} or more specifically
147 * {@link #detachModels()} if they keep references to models beside the default model.</li>
148 * </ul>
149 * </li>
150 * <li><b>Visibility </b>- If a component is not visible (see {@link #setVisible(boolean)}) it will
151 * not render a response (nor will their children).</li>
152 * <li><b>Enabling </b>- Component subclasses take into account their enabled state (see
153 * {@link #setEnabled(boolean)} when rendering, and in case of a {@link FormComponent} will not not
154 * update its model while the request is handled.</li>
155 * <li><b>Models </b>- The primary responsibility of a component is to use its model (an object that
156 * implements {@link IModel}) to render a response in an appropriate markup language, such as HTML.
157 * In addition, {@link FormComponent}s know how to update their models based on request information,
158 * see {@link FormComponent#updateModel()}. Since the IModel interface is a wrapper around another
159 * object, a convenience method {@link Component#getDefaultModelObject()} is provided to retrieve
160 * the object from its IModel wrapper. A further convenience method,
161 * {@link Component#getDefaultModelObjectAsString()}, is provided for the very common operation of
162 * converting the wrapped object to a String. <br>
163 * The component's model can be passed in the constructor or set via
164 * {@link Component#setDefaultModel(IModel)}. In neither case a model can be created on demand with
165 * {@link #initModel()}.<br>
166 * Note that a component can have more models besides its default model.</li>
167 * <li><b>Behaviors </b>- You can add multiple {@link Behavior}s to any component if you need to
168 * dynamically alter the behavior of components, e.g. manipulate attributes of the markup tag to
169 * which a Component is attached. Behaviors take part in the component's lifecycle through various
170 * callback methods.</li>
171 * <li><b>Locale </b>- The Locale for a Component is available through {@link #getLocale()}, which
172 * delegates to its parent's locale, finally consulting the {@link Session}'s locale.</li>
173 * <li><b>Style </b>- The Session's style ("skin") is available through
174 * {@link org.apache.wicket.Component#getStyle()}. Styles are intended to give a particular look to
175 * all components or resources in a session that is independent of its Locale. For example, a style
176 * might be a set of resources, including images and markup files, which gives the design look of
177 * "ocean" to the user. If the Session's style is set to "ocean" and these resources are given names
178 * suffixed with "_ocean", Wicket's resource management logic will prefer these resources to other
179 * resources, such as default resources, which are not as good of a match.</li>
180 * <li><b>Variation </b>- Whereas styles are Session (user) specific, variations are component
181 * specific. E.g. if the Style is "ocean" and {@link #getVariation()} returnss "NorthSea", than the
182 * resources are given the names suffixed with "_ocean_NorthSea".</li>
183 * <li><b>String Resources </b>- Components can have associated String resources via the
184 * Application's Localizer, which is available through the method {@link Component#getLocalizer()}.
185 * The convenience methods {@link Component#getString(String key)} and
186 * {@link Component#getString(String key, IModel model)} wrap the identical methods on the
187 * Application Localizer for easy access in Components.</li>
188 * <li><b>Feedback Messages </b>- The {@link Component#debug(Serializable)},
189 * {@link Component#info(Serializable)}, {@link Component#warn(Serializable)},
190 * {@link Component#error(java.io.Serializable)} and {@link Component#fatal(Serializable)} methods
191 * associate feedback messages with a Component. It is generally not necessary to use these methods
192 * directly since Wicket validators automatically register feedback messages on Components. Feedback
193 * message for a given Component can be retrieved with {@link Component#getFeedbackMessages}.</li>
194 * <li><b>Versioning </b>- Pages are the unit of versioning in Wicket, but fine-grained control of
195 * which Components should participate in versioning is possible via the
196 * {@link Component#setVersioned(boolean)} method. The versioning participation of a given Component
197 * can be retrieved with {@link Component#isVersioned()}.</li>
198 * <li><b>Page </b>- The Page containing any given Component can be retrieved by calling
199 * {@link Component#getPage()}. If the Component is not attached to a Page, an IllegalStateException
200 * will be thrown. An equivalent method, {@link Component#findPage()} is available for special
201 * circumstances where it might be desirable to get a null reference back instead.</li>
202 * <li><b>Application </b>- The {@link #getApplication()} method provides convenient access to the
203 * {@link Application} for a Component.</li>
204 * <li><b>AJAX support</b>- Components can be re-rendered after the whole Page has been rendered at
205 * least once by calling doRender().</li>
206 * <li><b>Security </b>- All components are subject to an {@link IAuthorizationStrategy} which
207 * controls instantiation, visibility and enabling. See {@link SimplePageAuthorizationStrategy} for
208 * a simple implementation.</li>
209 * </ul>
210 * 
211 * @author Jonathan Locke
212 * @author Chris Turner
213 * @author Eelco Hillenius
214 * @author Johan Compagner
215 * @author Juergen Donnerstag
216 * @author Igor Vaynberg (ivaynberg)
217 */
218public abstract class Component
219        implements
220                IClusterable,
221                IConverterLocator,
222                IRequestableComponent,
223                IHeaderContributor,
224                IHierarchical<Component>,
225                IEventSink,
226                IEventSource,
227                IMetadataContext<Serializable, Component>,
228                IFeedbackContributor
229{
230        /** Log. */
231        private static final Logger log = LoggerFactory.getLogger(Component.class);
232
233        private static final long serialVersionUID = 1L;
234
235        /**
236         * Action used with IAuthorizationStrategy to determine whether a component is allowed to be
237         * enabled.
238         * <p>
239         * If enabling is authorized, a component may decide by itself (typically using it's enabled
240         * property) whether it is enabled or not. If enabling is not authorized, the given component is
241         * marked disabled, regardless its enabled property.
242         * <p>
243         * When a component is not allowed to be enabled (in effect disabled through the implementation
244         * of this interface), Wicket will try to prevent model updates too. This is not completely fail
245         * safe, as constructs like:
246         * 
247         * <pre>
248         * 
249         * User u = (User)getModelObject();
250         * u.setName(&quot;got you there!&quot;);
251         * 
252         * </pre>
253         * 
254         * can't be prevented. Indeed it can be argued that any model protection is best dealt with in
255         * your model objects to be completely secured. Wicket will catch all normal framework-directed
256         * use though.
257         */
258        public static final Action ENABLE = new Action(Action.ENABLE);
259
260        /** Separator for component paths */
261        public static final char PATH_SEPARATOR = ':';
262        /** Path segment that represents this component's parent */
263        public static final String PARENT_PATH = "..";
264
265        /**
266         * Action used with IAuthorizationStrategy to determine whether a component and its children are
267         * allowed to be rendered.
268         * <p>
269         * There are two uses for this method:
270         * <ul>
271         * <li>The 'normal' use is for controlling whether a component is rendered without having any
272         * effect on the rest of the processing. If a strategy lets this method return 'false', then the
273         * target component and its children will not be rendered, in the same fashion as if that
274         * component had visibility property 'false'.</li>
275         * <li>The other use is when a component should block the rendering of the whole page. So
276         * instead of 'hiding' a component, what we generally want to achieve here is that we force the
277         * user to logon/give-credentials for a higher level of authorization. For this functionality,
278         * the strategy implementation should throw a {@link AuthorizationException}, which will then be
279         * handled further by the framework.</li>
280         * </ul>
281         * </p>
282         */
283        public static final Action RENDER = new Action(Action.RENDER);
284
285        /** meta data for user specified markup id */
286        private static final MetaDataKey<String> MARKUP_ID_KEY = new MetaDataKey<>()
287        {
288                private static final long serialVersionUID = 1L;
289        };
290
291        /** meta data for user specified markup id */
292        private static final MetaDataKey<FeedbackMessages> FEEDBACK_KEY = new MetaDataKey<>()
293        {
294                private static final long serialVersionUID = 1L;
295        };
296
297
298        /** Basic model IModelComparator implementation for normal object models */
299        private static final IModelComparator defaultModelComparator = new IModelComparator()
300        {
301                private static final long serialVersionUID = 1L;
302
303                @Override
304                public boolean compare(Component component, Object b)
305                {
306                        final Object a = component.getDefaultModelObject();
307                        if (a == null && b == null)
308                        {
309                                return true;
310                        }
311                        if (a == null || b == null)
312                        {
313                                return false;
314                        }
315                        return a.equals(b);
316                }
317        };
318
319        /** True when a component is being auto-added */
320        private static final int FLAG_AUTO = 0x0001;
321
322        /** Flag for escaping HTML in model strings */
323        private static final int FLAG_ESCAPE_MODEL_STRINGS = 0x0002;
324
325        /** Boolean whether this component's model is inheritable. */
326        static final int FLAG_INHERITABLE_MODEL = 0x0004;
327
328        /** Versioning boolean */
329        private static final int FLAG_VERSIONED = 0x0008;
330
331        /** Visibility boolean */
332        private static final int FLAG_VISIBLE = 0x0010;
333
334        /** Render tag boolean */
335        private static final int FLAG_RENDER_BODY_ONLY = 0x0020;
336
337        /** Ignore attribute modifiers */
338        private static final int FLAG_IGNORE_ATTRIBUTE_MODIFIER = 0x0040;
339
340        /** True when a component is enabled for model updates and is reachable. */
341        private static final int FLAG_ENABLED = 0x0080;
342
343        /** Reserved subclass-definable flag bit */
344        protected static final int FLAG_RESERVED1 = 0x0100;
345        /** Reserved subclass-definable flag bit */
346        protected static final int FLAG_RESERVED2 = 0x0200;
347        /** Reserved subclass-definable flag bit */
348        protected static final int FLAG_RESERVED3 = 0x0400;
349        /** Reserved subclass-definable flag bit */
350        protected static final int FLAG_RESERVED4 = 0x0800;
351
352        /** Boolean whether this component was rendered at least once for tracking changes. */
353        private static final int FLAG_HAS_BEEN_RENDERED = 0x1000;
354
355        /**
356         * Internal indicator of whether this component may be rendered given the current context's
357         * authorization. It overrides the visible flag in case this is false. Authorization is done
358         * before trying to render any component (otherwise we would end up with a half rendered page in
359         * the buffer)
360         */
361        private static final int FLAG_IS_RENDER_ALLOWED = 0x2000;
362
363        /** Whether or not the component should print out its markup id into the id attribute */
364        private static final int FLAG_OUTPUT_MARKUP_ID = 0x4000;
365
366        /**
367         * Output a placeholder tag if the component is not visible. This is useful in ajax mode to go
368         * to visible(false) to visible(true) without the overhead of repainting a visible parent
369         * container
370         */
371        private static final int FLAG_PLACEHOLDER = 0x8000;
372
373        /** Reserved subclass-definable flag bit */
374        protected static final int FLAG_RESERVED5 = 0x10000;
375        /** onInitialize called */
376        protected static final int FLAG_INITIALIZED = 0x20000;
377        /** Set when a component is removed from the hierarchy */
378        private static final int FLAG_REMOVED = 0x40000;
379        /** Reserved subclass-definable flag bit */
380        protected static final int FLAG_RESERVED8 = 0x80000;
381
382        /**
383         * Flag that determines whether the model is set. This is necessary because of the way we
384         * represent component state ({@link #data}). We can't distinguish between model and behavior
385         * using instanceof, because one object can implement both interfaces. Thus we need this flag -
386         * when the flag is set, first object in {@link #data} is always model.
387         */
388        private static final int FLAG_MODEL_SET = 0x100000;
389
390        /**
391         * Flag that restricts visibility of a component when set to true. This is usually used when a
392         * component wants to restrict visibility of another component. Calling
393         * {@link #setVisible(boolean)} on a component does not always have the desired effect because
394         * isVisible() can be overwritten thus this flag offers an alternative that should always work.
395         */
396        private static final int FLAG_VISIBILITY_ALLOWED = 0x40000000;
397
398        /**
399         * The name of attribute that will hold markup id
400         */
401        private static final String MARKUP_ID_ATTR_NAME = "id";
402
403        /**
404         * Meta data key for line precise error logging for the moment of addition. Made package private
405         * for access in {@link MarkupContainer} and {@link Page}
406         */
407        static final MetaDataKey<String> ADDED_AT_KEY = new MetaDataKey<>()
408        {
409                private static final long serialVersionUID = 1L;
410        };
411
412        /**
413         * meta data key for line precise error logging for the moment of construction. Made package
414         * private for access in {@link Page}
415         */
416        static final MetaDataKey<String> CONSTRUCTED_AT_KEY = new MetaDataKey<>()
417        {
418                private static final long serialVersionUID = 1L;
419        };
420
421        /** Component flags. See FLAG_* for possible non-exclusive flag values. */
422        private int flags = FLAG_VISIBLE | FLAG_ESCAPE_MODEL_STRINGS | FLAG_VERSIONED | FLAG_ENABLED |
423                FLAG_IS_RENDER_ALLOWED | FLAG_VISIBILITY_ALLOWED | FLAG_RESERVED5 /* page's stateless hint */;
424
425        // @formatter:off       
426        private static final short RFLAG_ENABLED_IN_HIERARCHY_VALUE        = 0x1;
427        private static final short RFLAG_ENABLED_IN_HIERARCHY_SET          = 0x2;
428        private static final short RFLAG_VISIBLE_IN_HIERARCHY_VALUE        = 0x4;
429        private static final short RFLAG_VISIBLE_IN_HIERARCHY_SET          = 0x8;
430        /** onconfigure has been called */
431        private static final short RFLAG_CONFIGURED                        = 0x10;
432        private static final short RFLAG_BEFORE_RENDER_SUPER_CALL_VERIFIED = 0x20;
433        private static final short RFLAG_INITIALIZE_SUPER_CALL_VERIFIED    = 0x40;
434        protected static final short RFLAG_CONTAINER_DEQUEING              = 0x80;
435        private static final short RFLAG_ON_RE_ADD_SUPER_CALL_VERIFIED     = 0x100;
436        /**
437         * Flag that makes we are in before-render callback phase Set after component.onBeforeRender is
438         * invoked (right before invoking beforeRender on children)
439         */
440        private static final short RFLAG_RENDERING                         = 0x200;
441        private static final short RFLAG_PREPARED_FOR_RENDER               = 0x400;
442        private static final short RFLAG_AFTER_RENDER_SUPER_CALL_VERIFIED  = 0x800;
443        private static final short RFLAG_DETACHING                         = 0x1000;
444        /** True when a component is being removed from the hierarchy */
445        private static final short RFLAG_REMOVING_FROM_HIERARCHY           = 0x2000;
446        /**
447         * This flag tracks if removals have been set on this component. Clearing this key is an
448         * expensive operation. With this flag this expensive call can be avoided.
449         */
450        protected static final short RFLAG_CONTAINER_HAS_REMOVALS          = 0x4000;
451        private static final short RFLAG_ON_CONFIGURE_SUPER_CALL_VERIFIED  = (short) 0x8000;
452        // @formatter:on
453
454        /**
455         * Flags that only keep their value during the request. Useful for cache markers, etc. At the
456         * end of the request the value of this variable is reset to 0
457         */
458        private transient short requestFlags = 0;
459
460        /** Component id. */
461        private final String id;
462
463        /** Any parent container. */
464        private MarkupContainer parent;
465
466        /**
467         * Instead of remembering the whole markupId, we just remember the number for this component so
468         * we can "reconstruct" the markupId on demand. While this could be part of {@link #data},
469         * profiling showed that having it as separate property consumes less memory.
470         */
471        int generatedMarkupId = -1;
472
473        /** Must only be used by auto components */
474        private transient IMarkupFragment markup;
475
476        /**
477         * Will be re-created instead of persisted when session is replicated. Markup sourcing strategy
478         * are typically stateless (but don't have to).
479         */
480        private transient IMarkupSourcingStrategy markupSourcingStrategy;
481
482        /**
483         * The object that holds the component state.
484         * <p>
485         * What's stored here depends on what attributes are set on component. Data can contains
486         * combination of following attributes:
487         * <ul>
488         * <li>Model (indicated by {@link #FLAG_MODEL_SET})
489         * <li>MetaDataEntry (optionally {@link MetaDataEntry}[] if more metadata entries are present) *
490         * <li>{@link Behavior}(s) added to component. The behaviors are not stored in separate array,
491         * they are part of the {@link #data} array (this is in order to save the space of the pointer
492         * to an empty array as most components have no behaviours). - FIXME - explain why - is this
493         * correct?
494         * </ul>
495         * If there is only one attribute set (i.e. model or MetaDataEntry([]) or one behavior), the
496         * #data object points directly to value of that attribute. Otherwise the data is of type
497         * Object[] where the attributes are ordered as specified above.
498         * <p>
499         */
500        Object data = null;
501
502        final int data_start()
503        {
504                return getFlag(FLAG_MODEL_SET) ? 1 : 0;
505        }
506
507        final int data_length()
508        {
509                if (data == null)
510                {
511                        return 0;
512                }
513                else if (data instanceof Object[] && !(data instanceof MetaDataEntry<?>[]))
514                {
515                        return ((Object[])data).length;
516                }
517                else
518                {
519                        return 1;
520                }
521        }
522
523        final Object data_get(int index)
524        {
525                if (data == null)
526                {
527                        return null;
528                }
529                else if (data instanceof Object[] && !(data instanceof MetaDataEntry<?>[]))
530                {
531                        Object[] array = (Object[])data;
532                        return index < array.length ? array[index] : null;
533                }
534                else if (index == 0)
535                {
536                        return data;
537                }
538                else
539                {
540                        return null;
541                }
542        }
543
544        final void data_set(int index, Object object)
545        {
546                if (index > data_length() - 1)
547                {
548                        throw new IndexOutOfBoundsException("can not set data at " + index +
549                                " when data_length() is " + data_length());
550                }
551                else if (index == 0 && !(data instanceof Object[] && !(data instanceof MetaDataEntry<?>[])))
552                {
553                        data = object;
554                }
555                else
556                {
557                        Object[] array = (Object[])data;
558                        array[index] = object;
559                }
560        }
561
562        final void data_add(Object object)
563        {
564                data_insert(-1, object);
565        }
566
567        final void data_insert(int position, Object object)
568        {
569                int currentLength = data_length();
570                if (position == -1)
571                {
572                        position = currentLength;
573                }
574                if (position > currentLength)
575                {
576                        throw new IndexOutOfBoundsException("can not insert data at " + position +
577                                " when data_length() is " + currentLength);
578                }
579                if (currentLength == 0)
580                {
581                        data = object;
582                }
583                else if (currentLength == 1)
584                {
585                        Object[] array = new Object[2];
586                        if (position == 0)
587                        {
588                                array[0] = object;
589                                array[1] = data;
590                        }
591                        else
592                        {
593                                array[0] = data;
594                                array[1] = object;
595                        }
596                        data = array;
597                }
598                else
599                {
600                        Object[] array = new Object[currentLength + 1];
601                        Object[] current = (Object[])data;
602                        int after = currentLength - position;
603                        if (position > 0)
604                        {
605                                System.arraycopy(current, 0, array, 0, position);
606                        }
607                        array[position] = object;
608                        if (after > 0)
609                        {
610                                System.arraycopy(current, position, array, position + 1, after);
611                        }
612                        data = array;
613                }
614        }
615
616        final void data_remove(int position)
617        {
618                int currentLength = data_length();
619
620                if (position > currentLength - 1)
621                {
622                        throw new IndexOutOfBoundsException();
623                }
624                else if (currentLength == 1)
625                {
626                        data = null;
627                }
628                else if (currentLength == 2)
629                {
630                        Object[] current = (Object[])data;
631                        if (position == 0)
632                        {
633                                data = current[1];
634                        }
635                        else
636                        {
637                                data = current[0];
638                        }
639                }
640                else
641                {
642                        Object[] current = (Object[])data;
643                        data = new Object[currentLength - 1];
644
645                        if (position > 0)
646                        {
647                                System.arraycopy(current, 0, data, 0, position);
648                        }
649                        if (position != currentLength - 1)
650                        {
651                                final int left = currentLength - position - 1;
652                                System.arraycopy(current, position + 1, data, position, left);
653                        }
654                }
655        }
656
657        /**
658         * Constructor. All components have names. A component's id cannot be null. This is the minimal
659         * constructor of component. It does not register a model.
660         * 
661         * @param id
662         *            The non-null id of this component
663         * @throws WicketRuntimeException
664         *             Thrown if the component has been given a null id.
665         */
666        public Component(final String id)
667        {
668                this(id, null);
669        }
670
671        /**
672         * Constructor. All components have names. A component's id cannot be null. This constructor
673         * includes a model.
674         * 
675         * @param id
676         *            The non-null id of this component
677         * @param model
678         *            The component's model
679         * 
680         * @throws WicketRuntimeException
681         *             Thrown if the component has been given a null id.
682         */
683        public Component(final String id, final IModel<?> model)
684        {
685                checkId(id);
686                this.id = id;
687
688                init();
689
690                Application application = getApplication();
691                application.getComponentInstantiationListeners().onInstantiation(this);
692
693                final DebugSettings debugSettings = application.getDebugSettings();
694                if (debugSettings.isLinePreciseReportingOnNewComponentEnabled() && debugSettings.getComponentUseCheck())
695                {
696                        setMetaData(CONSTRUCTED_AT_KEY,
697                                ComponentStrings.toString(this, new MarkupException("constructed")));
698                }
699
700                if (model != null)
701                {
702                        setModelImpl(wrap(model));
703                }
704        }
705
706        /**
707         * Let subclasses initialize this instance, before constructors are executed. <br>
708         * This method is intentionally <b>not</b> declared protected, to limit overriding to classes in
709         * this package.
710         */
711        void init()
712        {
713        }
714
715        /**
716         * Get the Markup associated with the Component. If not subclassed, the parent container is
717         * asked to return the markup of this child component.
718         * <p/>
719         * Components like Panel and Border should return the "calling" markup fragment, e.g.
720         * <code>&lt;span wicket:id="myPanel"&gt;body&lt;/span&gt;</code>. You may use
721         * Panel/Border/Enclosure.getMarkup(null) to return the associated markup file. And
722         * Panel/Border/Enclosure.getMarkup(child) will search the child in the appropriate markup
723         * fragment.
724         * 
725         * @see MarkupContainer#getMarkup(Component)
726         * 
727         * @return The markup fragment
728         */
729        public IMarkupFragment getMarkup()
730        {
731                // Markup already determined or preset?
732                if (markup != null)
733                {
734                        return markup;
735                }
736
737                // No parent, than check associated markup files
738                if (parent == null)
739                {
740                        // Must be a MarkupContainer to have associated markup file
741                        if (this instanceof MarkupContainer)
742                        {
743                                MarkupContainer container = (MarkupContainer)this;
744                                Markup associatedMarkup = container.getAssociatedMarkup();
745                                if (associatedMarkup != null)
746                                {
747                                        markup = associatedMarkup;
748                                        return markup;
749                                }
750                        }
751
752                        // Don't know how to find the markup
753                        throw new MarkupNotFoundException(
754                                "Can not determine Markup. Component is not yet connected to a parent. " +
755                                        toString());
756                }
757
758                // Ask the parent for find the markup for me
759                markup = parent.getMarkup(this);
760                return markup;
761        }
762
763        /**
764         * @return The 'id' attribute from the associated markup tag
765         */
766        public final String getMarkupIdFromMarkup()
767        {
768                ComponentTag tag = getMarkupTag();
769                if (tag != null)
770                {
771                        String id = tag.getAttribute("id");
772                        if (Strings.isEmpty(id) == false)
773                        {
774                                return id.trim();
775                        }
776                }
777
778                return null;
779        }
780
781        /**
782         * Set the markup for the component. Note that the component's markup variable is transient and
783         * thus must only be used for one render cycle. E.g. auto-component are using it. You may also
784         * it if you subclassed getMarkup().
785         * 
786         * @param markup
787         */
788        public final Component setMarkup(final IMarkupFragment markup)
789        {
790                this.markup = markup;
791                return this;
792        }
793
794        /**
795         * Called on all components before any component is rendered. This method
796         * should be used to configure such things as visibility and enabled flags.
797         * <p>
798         * Overrides must call {@code super.onConfigure()}, usually before any other code
799         * <p>
800         * NOTE: Component hierarchy should not be modified inside this method, instead it should be
801         * done in {@link #onBeforeRender()}
802         * <p>
803         * NOTE: Why this method is preferrable to directly overriding {@link #isVisible()} and
804         * {@link #isEnabled()}? Because those methods are called multiple times even for processing of
805         * a single request. If they contain expensive logic they can slow down the response time of the
806         * entire page. Further, overriding those methods directly on form components may lead to
807         * inconsistent or unexpected state depending on when those methods are called in the form
808         * processing workflow. It is a better practice to push changes to state rather than pull.
809         * <p>
810         * NOTE: If component's visibility or another property depends on another component you may call
811         * {@code other.configure()} followed by {@code other.isVisible()} as mentioned in
812         * {@link #configure()} javadoc.
813         * <p>
814         * NOTE: Why should {@link #onBeforeRender()} not be used for this? Because if a component's
815         * visibility is controlled inside {@link #onBeforeRender()}, once invisible the component will
816         * never become visible again.
817         */
818        protected void onConfigure()
819        {
820                setRequestFlag(RFLAG_ON_CONFIGURE_SUPER_CALL_VERIFIED, true);
821        }
822
823        /**
824         * This method is meant to be used as an alternative to initialize components. Usually the
825         * component's constructor is used for this task, but sometimes a component cannot be
826         * initialized in isolation, it may need to access its parent component or its markup in order
827         * to fully initialize. This method is invoked once per component's lifecycle when a path exists
828         * from this component to the {@link Page} thus providing the component with an atomic callback
829         * when the component's environment is built out.
830         * <p>
831         * Overrides must call super#{@link #onInitialize()}. Usually this should be the first thing an
832         * override does, much like a constructor.
833         * </p>
834         * <p>
835         * Parent containers are guaranteed to be initialized before their children
836         * </p>
837         * 
838         * <p>
839         * It is safe to use {@link #getPage()} in this method
840         * </p>
841         * 
842         * <p>
843         * NOTE:The timing of this call is not precise, the contract is that it is called sometime
844         * before {@link Component#onBeforeRender()}.
845         * </p>
846         * 
847         */
848        protected void onInitialize()
849        {
850                setRequestFlag(RFLAG_INITIALIZE_SUPER_CALL_VERIFIED, true);
851        }
852
853        /**
854         * Checks if the component has been initialized - {@link #onInitialize()} has been called
855         * 
856         * @return {@code true} if component has been initialized
857         */
858        public final boolean isInitialized()
859        {
860                return getFlag(FLAG_INITIALIZED);
861        }
862
863        /**
864         * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT!
865         * 
866         * Used to call {@link #onInitialize()}
867         */
868        public void internalInitialize()
869        {
870                fireInitialize();
871        }
872
873        /**
874         * Used to call {@link #onInitialize()}
875         */
876        final void fireInitialize()
877        {
878                if (!getFlag(FLAG_INITIALIZED))
879                {
880                        setFlag(FLAG_INITIALIZED, true);
881
882                        setRequestFlag(RFLAG_INITIALIZE_SUPER_CALL_VERIFIED, false);
883                        onInitialize();
884                        verifySuperCall("onInitialize", RFLAG_INITIALIZE_SUPER_CALL_VERIFIED);
885
886                        getApplication().getComponentInitializationListeners().onInitialize(this);
887                }
888                else if (getFlag(FLAG_REMOVED))
889                {
890                        setFlag(FLAG_REMOVED, false);
891                        
892                        setRequestFlag(RFLAG_ON_RE_ADD_SUPER_CALL_VERIFIED, false);
893                        onReAdd();
894                        verifySuperCall("onReAdd", RFLAG_ON_RE_ADD_SUPER_CALL_VERIFIED);
895                }
896        }
897
898        /**
899         * Called on every component after the page is rendered. Calls hook {@link #onAfterRender()}.
900         */
901        final void afterRender()
902        {
903                setRequestFlag(RFLAG_PREPARED_FOR_RENDER, false);
904                
905                try
906                {
907                        setRequestFlag(RFLAG_AFTER_RENDER_SUPER_CALL_VERIFIED, false);
908
909                        onAfterRender();
910                        getApplication().getComponentOnAfterRenderListeners().onAfterRender(this);
911                        verifySuperCall("onAfterRender", RFLAG_AFTER_RENDER_SUPER_CALL_VERIFIED);
912                }
913                finally
914                {
915                        // this flag must always be set to false.
916                        setRequestFlag(RFLAG_RENDERING, false);
917                }
918        }
919
920        /**
921         * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT!
922         * 
923         * Called on all components before any component is rendered. Calls hooks
924         * {@link #configure()} and (if visible) {@link #onBeforeRender()}
925         * and delegates to {@link #beforeRender()} of all child components.
926         */
927        public final void beforeRender()
928        {
929                if (this instanceof IFeedback)
930                {
931                        Optional<FeedbackDelay> delay = FeedbackDelay.get(getRequestCycle());
932                        if (delay.isPresent()) {
933                                delay.get().postpone((IFeedback)this);
934                                return;
935                        }
936                }
937
938                configure();
939
940                if ((determineVisibility()) && !getRequestFlag(RFLAG_RENDERING) &&
941                        !getRequestFlag(RFLAG_PREPARED_FOR_RENDER))
942                {
943                        try {
944                                setRequestFlag(RFLAG_BEFORE_RENDER_SUPER_CALL_VERIFIED, false);
945
946                                Application application = getApplication();
947                                application.getComponentPreOnBeforeRenderListeners().onBeforeRender(this);
948
949                                onBeforeRender();
950                                application.getComponentPostOnBeforeRenderListeners().onBeforeRender(this);
951
952                                verifySuperCall("onBeforeRender", RFLAG_BEFORE_RENDER_SUPER_CALL_VERIFIED);
953                        } catch (RuntimeException ex) {
954                                setRequestFlag(RFLAG_PREPARED_FOR_RENDER, false);
955                                throw ex;
956                        }
957                }
958        }
959
960        /**
961         * Triggers {@link #onConfigure()} to be invoked on this component if it has not already during
962         * this request.
963         * <p>
964         * This method should be invoked before any calls to {@link #isVisible()} or
965         * {@link #isEnabled()}. Usually this method will be called by the framework before the
966         * component is rendered and so users should not need to call it; however, in cases where
967         * visibility or enabled or other state of one component depends on the state of another this
968         * method should be manually invoked on the other component by the user. EG to link visiliby of
969         * two markup containers the following should be done:
970         * 
971         * <pre>
972         * final WebMarkupContainer source=new WebMarkupContainer("a") {
973         *      protected void onConfigure() {
974         *    setVisible(Math.rand()&gt;0.5f);
975         *  }
976         * };
977         * 
978         * WebMarkupContainer linked=new WebMarkupContainer("b") {
979         *      protected void onConfigure() {
980         *              source.configure(); // make sure source is configured
981         *              setVisible(source.isVisible());
982         *  }
983         * }
984         * </pre>
985         * 
986         * </p>
987         */
988        public final void configure()
989        {
990                if (!getRequestFlag(RFLAG_CONFIGURED))
991                {
992                        clearEnabledInHierarchyCache();
993                        clearVisibleInHierarchyCache();
994                        
995                        setRequestFlag(RFLAG_ON_CONFIGURE_SUPER_CALL_VERIFIED, false);
996                        onConfigure();
997                        verifySuperCall("onConfigure", RFLAG_ON_CONFIGURE_SUPER_CALL_VERIFIED);
998                        
999                        for (Behavior behavior : getBehaviors())
1000                        {
1001                                if (isBehaviorAccepted(behavior))
1002                                {
1003                                        behavior.onConfigure(this);
1004                                }
1005                        }
1006
1007                        // check authorization
1008                        setRenderAllowed();
1009
1010                        internalOnAfterConfigure();
1011
1012                        getApplication().getComponentOnConfigureListeners().onConfigure(this);
1013
1014                        setRequestFlag(RFLAG_CONFIGURED, true);
1015                }
1016        }
1017
1018        /**
1019         * Verify super calls of an overridden hook method.
1020         */
1021        private final void verifySuperCall(String method, short flag)
1022        {
1023                if (!getRequestFlag(flag))
1024                {
1025                        throw new IllegalStateException(String.format("%s() in the hierarchy of %s has not called super.%s()", method, getClass().getName(), method));
1026                }
1027                
1028                setRequestFlag(flag, false);
1029        }
1030
1031        /**
1032         * Called after the {@link #onConfigure()}, but before {@link #onBeforeRender()}
1033         */
1034        void internalOnAfterConfigure()
1035        {
1036        }
1037
1038        /**
1039         * Redirects to any intercept page previously specified by a call to {@link #redirectToInterceptPage(Page)}.
1040         * The redirect is done by throwing an exception. If there is no intercept page no exception
1041         * will be thrown and the program flow will continue uninterrupted.
1042         * 
1043         * Example:
1044         * 
1045         * <pre>
1046         * add(new Link(&quot;login&quot;)
1047         * {
1048         *      protected void onClick()
1049         *      {
1050         *              if (authenticate())
1051         *              {
1052         *                      continueToOriginalDestination();
1053         *                      // if we reach this line there was no intercept page, so go to home page
1054         *                      setResponsePage(WelcomePage.class);
1055         *              }
1056         *      }
1057         * });
1058         * 
1059         * @see Component#redirectToInterceptPage(Page)
1060         */
1061        public final void continueToOriginalDestination()
1062        {
1063                RestartResponseAtInterceptPageException.continueToOriginalDestination();
1064        }
1065
1066        /**
1067         * Clears any data about previously intercepted page.
1068         */
1069        public final void clearOriginalDestination()
1070        {
1071                RestartResponseAtInterceptPageException.clearOriginalDestination();
1072        }
1073
1074        /**
1075         * Registers a debug feedback message for this component
1076         * 
1077         * @param message
1078         *            The feedback message
1079         */
1080        @Override
1081        public final void debug(final Serializable message)
1082        {
1083                getFeedbackMessages().debug(this, message);
1084                addStateChange();
1085        }
1086
1087        /**
1088         * Signals this Component that it is removed from the Component hierarchy.
1089         */
1090        final void internalOnRemove()
1091        {
1092                setRequestFlag(RFLAG_REMOVING_FROM_HIERARCHY, true);
1093                onRemove();
1094                setFlag(FLAG_REMOVED, true);
1095                if (getRequestFlag(RFLAG_REMOVING_FROM_HIERARCHY))
1096                {
1097                        throw new IllegalStateException(Component.class.getName() +
1098                                " has not been properly removed from hierarchy. Something in the hierarchy of " +
1099                                getClass().getName() +
1100                                " has not called super.onRemove() in the override of onRemove() method");
1101                }
1102                Behaviors.onRemove(this);
1103                removeChildren();
1104        }
1105
1106        /**
1107         * Detaches the component. This is called at the end of the request for all the pages that are
1108         * touched in that request.
1109         */
1110        @Override
1111        public final void detach()
1112        {
1113                try
1114                {
1115                        setRequestFlag(RFLAG_DETACHING, true);
1116                        onDetach();
1117                        if (getRequestFlag(RFLAG_DETACHING))
1118                        {
1119                                throw new IllegalStateException(Component.class.getName() +
1120                                                " has not been properly detached. Something in the hierarchy of " +
1121                                                getClass().getName() +
1122                                                " has not called super.onDetach() in the override of onDetach() method");
1123                        }
1124
1125                        // always detach models because they can be attached without the
1126                        // component. eg component has a compoundpropertymodel and one of its
1127                        // children component's getmodelobject is called
1128                        detachModels();
1129
1130                        // detach any behaviors
1131                        Behaviors.detach(this);
1132                }
1133                catch (Exception x)
1134                {
1135                        throw new WicketRuntimeException("An error occurred while detaching component: " + toString(true), x);
1136                }
1137
1138                // always detach children because components can be attached
1139                // independently of their parents
1140                detachChildren();
1141
1142                // reset the model to null when the current model is a IWrapModel and
1143                // the model that created it/wrapped in it is a IComponentInheritedModel
1144                // The model will be created next time.
1145                if (getFlag(FLAG_INHERITABLE_MODEL))
1146                {
1147                        setModelImpl(null);
1148                        setFlag(FLAG_INHERITABLE_MODEL, false);
1149                }
1150
1151                clearEnabledInHierarchyCache();
1152                clearVisibleInHierarchyCache();
1153
1154                // clear request flags but keep super call verifications WICKET-5417
1155                requestFlags &= (RFLAG_INITIALIZE_SUPER_CALL_VERIFIED | RFLAG_ON_CONFIGURE_SUPER_CALL_VERIFIED | RFLAG_BEFORE_RENDER_SUPER_CALL_VERIFIED);
1156
1157                detachFeedback();
1158
1159                internalDetach();
1160
1161                // notify any detach listener
1162                IDetachListener detachListener = getApplication().getFrameworkSettings()
1163                        .getDetachListener();
1164                if (detachListener != null)
1165                {
1166                        detachListener.onDetach(this);
1167                }
1168        }
1169
1170        private void detachFeedback()
1171        {
1172                FeedbackMessages feedback = getMetaData(FEEDBACK_KEY);
1173                if (feedback != null)
1174                {
1175                        feedback.clear(getApplication().getApplicationSettings()
1176                                .getFeedbackMessageCleanupFilter());
1177
1178                        if (feedback.isEmpty())
1179                        {
1180                                setMetaData(FEEDBACK_KEY, null);
1181                        }
1182                        else
1183                        {
1184                                feedback.detach();
1185                        }
1186                }
1187        }
1188
1189        /**
1190         * Removes the cached markup at the end of the request. For the next request it will be get
1191         * either from the parent's markup or from {@link MarkupCache}.
1192         */
1193        private void internalDetach()
1194        {
1195                markup = null;
1196        }
1197
1198        /**
1199         * Detaches all models
1200         */
1201        public void detachModels()
1202        {
1203                // Detach any detachable model from this component
1204                detachModel();
1205        }
1206
1207        /**
1208         * Registers an error feedback message for this component
1209         * 
1210         * @param message
1211         *            The feedback message
1212         */
1213        @Override
1214        public final void error(final Serializable message)
1215        {
1216                getFeedbackMessages().error(this, message);
1217                addStateChange();
1218        }
1219
1220        /**
1221         * Registers a fatal feedback message for this component
1222         * 
1223         * @param message
1224         *            The feedback message
1225         */
1226        @Override
1227        public final void fatal(final Serializable message)
1228        {
1229                getFeedbackMessages().fatal(this, message);
1230                addStateChange();
1231        }
1232
1233        /**
1234         * Finds the first container parent of this component of the given class.
1235         * 
1236         * @param <Z>
1237         *            type of parent
1238         * 
1239         * 
1240         * @param c
1241         *            MarkupContainer class to search for
1242         * @return First container parent that is an instance of the given class, or null if none can be
1243         *         found
1244         */
1245        public final <Z> Z findParent(final Class<Z> c)
1246        {
1247                // Start with immediate parent
1248                MarkupContainer current = parent;
1249
1250                // Walk up containment hierarchy
1251                while (current != null)
1252                {
1253                        // Is current an instance of this class?
1254                        if (c.isInstance(current))
1255                        {
1256                                return c.cast(current);
1257                        }
1258
1259                        // Check parent
1260                        current = current.getParent();
1261                }
1262
1263                // Failed to find component
1264                return null;
1265        }
1266
1267        /**
1268         * @return The nearest markup container with associated markup
1269         */
1270        public final MarkupContainer findParentWithAssociatedMarkup()
1271        {
1272                MarkupContainer container = parent;
1273                while (container != null)
1274                {
1275                        if (container.getAssociatedMarkup() != null)
1276                        {
1277                                return container;
1278                        }
1279                        container = container.getParent();
1280                }
1281
1282                // This should never happen since Page always has associated markup
1283                throw new WicketRuntimeException("Unable to find parent with associated markup");
1284        }
1285
1286        /**
1287         * Gets interface to application that this component is a part of.
1288         * 
1289         * @return The application associated with the session that this component is in.
1290         * @see Application
1291         */
1292        public final Application getApplication()
1293        {
1294                return Application.get();
1295        }
1296
1297        /**
1298         * @return A path of the form [page-class-name]:[page-relative-path]
1299         * @see Component#getPageRelativePath()
1300         */
1301        public final String getClassRelativePath()
1302        {
1303                return getClass().getName() + PATH_SEPARATOR + getPageRelativePath();
1304        }
1305
1306        /**
1307         * Get the converter that should be used by this component, delegates to
1308         * {@link #createConverter(Class)} and then to the application's
1309         * {@link IConverterLocator}.
1310         *
1311         * @param type
1312         *            The type to convert to
1313         *
1314         * @return The converter that should be used by this component
1315         */
1316        @SuppressWarnings("unchecked")
1317        @Override
1318        public <C> IConverter<C> getConverter(Class<C> type) {
1319                IConverter<?> converter = createConverter(type);
1320                if (converter != null) {
1321                        return (IConverter<C>) converter;
1322                }
1323                return getApplication().getConverterLocator().getConverter(type);
1324        }
1325
1326        /**
1327         * Factory method for converters to be used by this component,
1328         * returns {@code null} by default.
1329         *
1330         * @param type
1331         *            The type to convert to
1332         *
1333         * @return a converter to be used by this component
1334         */
1335        protected IConverter<?> createConverter(Class<?> type) {
1336                return null;
1337        }
1338
1339        /**
1340         * Gets whether model strings should be escaped.
1341         * 
1342         * @return Returns whether model strings should be escaped
1343         */
1344        public final boolean getEscapeModelStrings()
1345        {
1346                return getFlag(FLAG_ESCAPE_MODEL_STRINGS);
1347        }
1348
1349        /**
1350         * Gets the id of this component.
1351         * 
1352         * @return The id of this component
1353         */
1354        @Override
1355        public String getId()
1356        {
1357                return id;
1358        }
1359
1360        /**
1361         * @return Innermost model for this component
1362         */
1363        public final IModel<?> getInnermostModel()
1364        {
1365                return getInnermostModel(getDefaultModel());
1366        }
1367
1368        /**
1369         * Gets the locale for this component. By default, it searches its parents for a locale. If no
1370         * parents (it's a recursive search) returns a locale, it gets one from the session.
1371         * 
1372         * @return The locale to be used for this component
1373         * @see Session#getLocale()
1374         */
1375        public Locale getLocale()
1376        {
1377                if (parent != null)
1378                {
1379                        return parent.getLocale();
1380                }
1381                return getSession().getLocale();
1382        }
1383
1384        /**
1385         * Convenience method to provide easy access to the localizer object within any component.
1386         * 
1387         * @return The localizer object
1388         */
1389        public final Localizer getLocalizer()
1390        {
1391                return getApplication().getResourceSettings().getLocalizer();
1392        }
1393
1394        /**
1395         * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT!
1396         * 
1397         * Get the first component tag in the associated markup
1398         * 
1399         * @return first component tag
1400         */
1401        protected final ComponentTag getMarkupTag()
1402        {
1403                IMarkupFragment markup = getMarkup();
1404                if (markup != null)
1405                {
1406                        for (int i = 0; i < markup.size(); i++)
1407                        {
1408                                MarkupElement elem = markup.get(i);
1409                                if (elem instanceof ComponentTag)
1410                                {
1411                                        return (ComponentTag)elem;
1412                                }
1413                        }
1414                }
1415                return null;
1416        }
1417
1418        /**
1419         * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT!
1420         * 
1421         * Get a copy of the markup's attributes which are associated with the component.
1422         * <p>
1423         * Modifications to the map returned don't change the tags attributes. It is just a copy.
1424         * <p>
1425         * Note: The component must have been added (directly or indirectly) to a container with an
1426         * associated markup file (Page, Panel or Border).
1427         * 
1428         * @return markup attributes
1429         */
1430        public final ValueMap getMarkupAttributes()
1431        {
1432                ComponentTag tag = getMarkupTag();
1433                if (tag != null)
1434                {
1435                        ValueMap attrs = new ValueMap(tag.getAttributes());
1436                        attrs.makeImmutable();
1437                        return attrs;
1438                }
1439                return ValueMap.EMPTY_MAP;
1440        }
1441
1442        /**
1443         * Get the markupId
1444         * 
1445         * @return MarkupId
1446         */
1447        public final Object getMarkupIdImpl()
1448        {
1449                if (generatedMarkupId != -1)
1450                {
1451                        return generatedMarkupId;
1452                }
1453
1454                String id = getMetaData(MARKUP_ID_KEY);
1455
1456                // if still no markup id is found, and the component has been attached to a page, try to
1457                // retrieve the id from the markup file.
1458                if (id == null && findPage() != null)
1459                {
1460                        id = getMarkupIdFromMarkup();
1461                }
1462                return id;
1463        }
1464
1465        /**
1466         * Retrieves id by which this component is represented within the markup. This is either the id
1467         * attribute set explicitly via a call to {@link #setMarkupId(String)}, id attribute defined in
1468         * the markup, or an automatically generated id - in that order.
1469         * <p>
1470         * If no id is set and <code>createIfDoesNotExist</code> is false, this method will return null.
1471         * Otherwise it will generate an id value which by default will be unique in the page. This is
1472         * the preferred way as there is no chance of id collision. This will also enable
1473         * {@link #setOutputMarkupId(boolean)}.
1474         * <p>
1475         * 
1476         * <p>
1477         * Note: This method should only be called after the component or its parent have been added to
1478         * the page.
1479         * 
1480         * @param createIfDoesNotExist
1481         *            When there is no existing markup id, determines whether it should be generated or
1482         *            whether <code>null</code> should be returned.
1483         * 
1484         * @return markup id of the component
1485         */
1486        public String getMarkupId(boolean createIfDoesNotExist)
1487        {
1488                IMarkupIdGenerator markupIdGenerator = getApplication().getMarkupSettings().getMarkupIdGenerator();
1489                String markupId = markupIdGenerator.generateMarkupId(this, createIfDoesNotExist);
1490                return markupId;
1491        }
1492
1493        /**
1494         * Retrieves id by which this component is represented within the markup. This is either the id
1495         * attribute set explicitly via a call to {@link #setMarkupId(String)}, id attribute defined in
1496         * the markup, or an automatically generated id - in that order.
1497         * <p>
1498         * If no explicit id is set this function will generate an id value that will be unique in the
1499         * page. This is the preferred way as there is no chance of id collision. This will also enable
1500         * {@link #setOutputMarkupId(boolean)}.
1501         * <p>
1502         * Note: This method should only be called after the component or its parent have been added to
1503         * the page.
1504         * 
1505         * @return markup id of the component
1506         */
1507        public String getMarkupId()
1508        {
1509                return getMarkupId(true);
1510        }
1511
1512        /**
1513         * Gets metadata for this component using the given key.
1514         * 
1515         * @param <M>
1516         *            The type of the metadata.
1517         * 
1518         * @param key
1519         *            The key for the data
1520         * @return The metadata or null of no metadata was found for the given key
1521         * @see MetaDataKey
1522         */
1523        @Override
1524        public final <M extends Serializable> M getMetaData(final MetaDataKey<M> key)
1525        {
1526                return key.get(getMetaData());
1527        }
1528
1529        /**
1530         * Gets the meta data entries for this component as an array of {@link MetaDataEntry} objects.
1531         *
1532         * @return the meta data entries for this component
1533         */
1534        private MetaDataEntry<?>[] getMetaData()
1535        {
1536                MetaDataEntry<?>[] metaData = null;
1537
1538                // index where we should expect the entry
1539                int index = getFlag(FLAG_MODEL_SET) ? 1 : 0;
1540
1541                int length = data_length();
1542
1543                if (index < length)
1544                {
1545                        Object object = data_get(index);
1546                        if (object instanceof MetaDataEntry<?>[])
1547                        {
1548                                metaData = (MetaDataEntry<?>[])object;
1549                        }
1550                        else if (object instanceof MetaDataEntry)
1551                        {
1552                                metaData = new MetaDataEntry[] { (MetaDataEntry<?>)object };
1553                        }
1554                }
1555
1556                return metaData;
1557        }
1558
1559        /**
1560         * Gets the model. It returns the object that wraps the backing model.
1561         * 
1562         * @return The model
1563         */
1564        public final IModel<?> getDefaultModel()
1565        {
1566                IModel<?> model = getModelImpl();
1567                // If model is null
1568                if (model == null)
1569                {
1570                        // give subclass a chance to lazy-init model
1571                        model = initModel();
1572                        setModelImpl(model);
1573                }
1574
1575                return model;
1576        }
1577
1578        /**
1579         * Gets the backing model object. Unlike getDefaultModel().getObject(), this method returns null
1580         * for a null model.
1581         * 
1582         * @return The backing model object
1583         */
1584        public final Object getDefaultModelObject()
1585        {
1586                final IModel<?> model = getDefaultModel();
1587                if (model != null)
1588                {
1589                        try
1590                        {
1591                                // Get model value for this component.
1592                                return model.getObject();
1593                        }
1594                        catch (Exception ex)
1595                        {
1596                                // wrap the exception so that it brings info about the component
1597                                WicketRuntimeException rex = new WicketRuntimeException(
1598                                        "An error occurred while getting the model object for Component: " +
1599                                                this.toString(true), ex);
1600                                throw rex;
1601                        }
1602                }
1603                return null;
1604        }
1605
1606        /**
1607         * Gets a model object as a string. Depending on the "escape model strings" flag of the
1608         * component, the string is either HTML escaped or not. "HTML escaped" meaning that only HTML
1609         * sensitive chars are escaped but not all none-ascii chars. Proper HTML encoding should be used
1610         * instead. In case you really need a fully escaped model string you may call
1611         * {@link Strings#escapeMarkup(CharSequence, boolean, boolean)} on the model string returned.
1612         * 
1613         * @see Strings#escapeMarkup(CharSequence, boolean, boolean)
1614         * @see #getEscapeModelStrings()
1615         * 
1616         * @return Model object for this component as a string
1617         */
1618        public final String getDefaultModelObjectAsString()
1619        {
1620                return getDefaultModelObjectAsString(getDefaultModelObject());
1621        }
1622
1623        /**
1624         * Gets a model object as a string. Depending on the "escape model strings" flag of the
1625         * component, the string is either HTML escaped or not. "HTML escaped" meaning that only HTML
1626         * sensitive chars are escaped but not all none-ascii chars. Proper HTML encoding should be used
1627         * instead. In case you really need a fully escaped model string you may call
1628         * {@link Strings#escapeMarkup(CharSequence, boolean, boolean)} on the model string returned.
1629         * 
1630         * @see Strings#escapeMarkup(CharSequence, boolean, boolean)
1631         * @see #getEscapeModelStrings()
1632         * 
1633         * @param modelObject
1634         *            Model object to convert to string
1635         * @return The string
1636         */
1637        @SuppressWarnings({ "rawtypes", "unchecked" })
1638        public final String getDefaultModelObjectAsString(final Object modelObject)
1639        {
1640                if (modelObject != null)
1641                {
1642                        // Get converter
1643                        final Class<?> objectClass = modelObject.getClass();
1644
1645                        final IConverter converter = getConverter(objectClass);
1646
1647                        // Model string from property
1648                        final String modelString = converter.convertToString(modelObject, getLocale());
1649
1650                        if (modelString != null)
1651                        {
1652                                // If we should escape the markup
1653                                if (getFlag(FLAG_ESCAPE_MODEL_STRINGS))
1654                                {
1655                                        // Escape HTML sensitive characters only. Not all none-ascii chars
1656                                        return Strings.escapeMarkup(modelString, false, false).toString();
1657                                }
1658                                return modelString;
1659                        }
1660                }
1661                return "";
1662        }
1663
1664        /**
1665         * Gets whether or not component will output id attribute into the markup. id attribute will be
1666         * set to the value returned from {@link Component#getMarkupId()}.
1667         * 
1668         * @return whether or not component will output id attribute into the markup
1669         */
1670        public final boolean getOutputMarkupId()
1671        {
1672                return getFlag(FLAG_OUTPUT_MARKUP_ID);
1673        }
1674
1675        /**
1676         * Gets whether or not an invisible component will render a placeholder tag.
1677         * 
1678         * @return true if a placeholder tag should be rendered
1679         */
1680        public final boolean getOutputMarkupPlaceholderTag()
1681        {
1682                return getFlag(FLAG_PLACEHOLDER);
1683        }
1684
1685        /**
1686         * Gets the page holding this component.
1687         * 
1688         * @return The page holding this component
1689         * @throws WicketRuntimeException
1690         *             Thrown if component is not yet attached to a Page.
1691         * @see #findPage()
1692         */
1693        @Override
1694        public final Page getPage()
1695        {
1696                // Search for nearest Page
1697                final Page page = findPage();
1698
1699                // If no Page was found
1700                if (page == null)
1701                {
1702                        // Give up with a nice exception
1703                        throw new WicketRuntimeException("No Page found for component: " + this.toString(true)
1704                                        + ". You probably forgot to add it to its parent component.");
1705                }
1706
1707                return page;
1708        }
1709
1710        /**
1711         * Gets the path to this component relative to its containing page, i.e. without leading page
1712         * id.
1713         * 
1714         * @return The path to this component relative to the page it is in
1715         */
1716        @Override
1717        public final String getPageRelativePath()
1718        {
1719                return Strings.afterFirstPathComponent(getPath(), PATH_SEPARATOR);
1720        }
1721
1722        /**
1723         * Gets any parent container, or null if there is none.
1724         * 
1725         * @return Any parent container, or null if there is none
1726         */
1727        @Override
1728        public final MarkupContainer getParent()
1729        {
1730                return parent;
1731        }
1732
1733        /**
1734         * Gets this component's path.
1735         * 
1736         * @return Colon separated path to this component in the component hierarchy
1737         */
1738        public final String getPath()
1739        {
1740                final PrependingStringBuffer buffer = new PrependingStringBuffer(32);
1741                for (Component c = this; c != null; c = c.getParent())
1742                {
1743                        if (buffer.length() > 0)
1744                        {
1745                                buffer.prepend(PATH_SEPARATOR);
1746                        }
1747                        buffer.prepend(c.getId());
1748                }
1749                return buffer.toString();
1750        }
1751
1752        /**
1753         * If false the component's tag will be printed as well as its body (which is default). If true
1754         * only the body will be printed, but not the component's tag.
1755         * 
1756         * @return If true, the component tag will not be printed
1757         */
1758        public final boolean getRenderBodyOnly()
1759        {
1760                return getFlag(FLAG_RENDER_BODY_ONLY);
1761        }
1762
1763        /**
1764         * @return The request for this component's active request cycle
1765         */
1766        public final Request getRequest()
1767        {
1768                RequestCycle requestCycle = getRequestCycle();
1769                if (requestCycle == null)
1770                {
1771                        // Happens often with WicketTester when one forgets to call
1772                        // createRequestCycle()
1773                        throw new WicketRuntimeException("No RequestCycle is currently set!");
1774                }
1775                return requestCycle.getRequest();
1776        }
1777
1778        /**
1779         * Gets the active request cycle for this component
1780         * 
1781         * @return The request cycle
1782         */
1783        public final RequestCycle getRequestCycle()
1784        {
1785                return RequestCycle.get();
1786        }
1787
1788        /**
1789         * @return The response for this component's active request cycle
1790         */
1791        public final Response getResponse()
1792        {
1793                return getRequestCycle().getResponse();
1794        }
1795
1796        /**
1797         * Gets the current Session object.
1798         * 
1799         * @return The Session that this component is in
1800         */
1801        public Session getSession()
1802        {
1803                return Session.get();
1804        }
1805
1806        /**
1807         * @return Size of this Component in bytes. Returns {@code 0} - if the size cannot be calculated for some reason
1808         */
1809        public long getSizeInBytes()
1810        {
1811                final MarkupContainer originalParent = parent;
1812                parent = null;
1813                long size = 0;
1814                try
1815                {
1816                        size = WicketObjects.sizeof(this);
1817                }
1818                catch (Exception e)
1819                {
1820                        log.error("Exception getting size for component " + this, e);
1821                }
1822                parent = originalParent;
1823                return size;
1824        }
1825
1826        /**
1827         * @param key
1828         *            Key of string resource in property file
1829         * @return The String
1830         * @see Localizer
1831         */
1832        public final String getString(final String key)
1833        {
1834                return getString(key, null);
1835        }
1836
1837        /**
1838         * @param key
1839         *            The resource key
1840         * @param model
1841         *            The model
1842         * @return The formatted string
1843         * @see Localizer
1844         */
1845        public final String getString(final String key, final IModel<?> model)
1846        {
1847                return getLocalizer().getString(key, this, model);
1848        }
1849
1850        /**
1851         * @param key
1852         *            The resource key
1853         * @param model
1854         *            The model
1855         * @param defaultValue
1856         *            A default value if the string cannot be found
1857         * @return The formatted string
1858         * @see Localizer
1859         */
1860        public final String getString(final String key, final IModel<?> model, final String defaultValue)
1861        {
1862                return getLocalizer().getString(key, this, model, defaultValue);
1863        }
1864
1865        /**
1866         * A convenience method to access the Sessions's style.
1867         * 
1868         * @return The style of this component respectively the style of the Session.
1869         * 
1870         * @see org.apache.wicket.Session#getStyle()
1871         */
1872        public final String getStyle()
1873        {
1874                Session session = getSession();
1875                if (session == null)
1876                {
1877                        throw new WicketRuntimeException("Wicket Session object not available");
1878                }
1879                return session.getStyle();
1880        }
1881
1882        /**
1883         * Gets the variation string of this component that will be used to look up markup for this
1884         * component. Subclasses can override this method to define by an instance what markup variation
1885         * should be picked up. By default it will return null or the value of a parent.
1886         * 
1887         * @return The variation of this component.
1888         */
1889        public String getVariation()
1890        {
1891                if (parent != null)
1892                {
1893                        return parent.getVariation();
1894                }
1895                return null;
1896        }
1897
1898        /**
1899         * Gets whether this component was rendered at least once.
1900         * 
1901         * @return true if the component has been rendered before, false if it is merely constructed
1902         */
1903        public final boolean hasBeenRendered()
1904        {
1905                return getFlag(FLAG_HAS_BEEN_RENDERED);
1906        }
1907
1908        /**
1909         * Gets feedback messages for this component. This method will instantiate a
1910         * {@link FeedbackMessages} instance and add it to the component metadata, even when called on a
1911         * component that has no feedback messages, to avoid the overhead use
1912         * {@link #hasFeedbackMessage()}
1913         * 
1914         * @return feedback messages instance
1915         */
1916        public FeedbackMessages getFeedbackMessages()
1917        {
1918                FeedbackMessages messages = getMetaData(FEEDBACK_KEY);
1919                if (messages == null)
1920                {
1921                        messages = new FeedbackMessages();
1922                        setMetaData(FEEDBACK_KEY, messages);
1923                }
1924                return messages;
1925        }
1926
1927        /**
1928         * @return True if this component has an error message
1929         */
1930        public final boolean hasErrorMessage()
1931        {
1932                FeedbackMessages messages = getMetaData(FEEDBACK_KEY);
1933                if (messages == null)
1934                {
1935                        return false;
1936                }
1937                return messages.hasMessage(FeedbackMessage.ERROR);
1938        }
1939
1940        /**
1941         * @return True if this component has some kind of feedback message
1942         * 
1943         */
1944        public final boolean hasFeedbackMessage()
1945        {
1946                FeedbackMessages messages = getMetaData(FEEDBACK_KEY);
1947                if (messages == null)
1948                {
1949                        return false;
1950                }
1951                return messages.size() > 0;
1952        }
1953
1954        /**
1955         * Registers an informational feedback message for this component
1956         * 
1957         * @param message
1958         *            The feedback message
1959         */
1960        @Override
1961        public final void info(final Serializable message)
1962        {
1963                getFeedbackMessages().info(this, message);
1964                addStateChange();
1965        }
1966
1967        /**
1968         * Registers an success feedback message for this component
1969         * 
1970         * @param message
1971         *            The feedback message
1972         */
1973        @Override
1974        public final void success(final Serializable message)
1975        {
1976                getFeedbackMessages().success(this, message);
1977                addStateChange();
1978        }
1979
1980        /**
1981         * Authorizes an action for a component.
1982         * 
1983         * @param action
1984         *            The action to authorize
1985         * @return True if the action is allowed
1986         * @throws AuthorizationException
1987         *             Can be thrown by implementation if action is unauthorized
1988         */
1989        public final boolean isActionAuthorized(Action action)
1990        {
1991                IAuthorizationStrategy authorizationStrategy = getSession().getAuthorizationStrategy();
1992                if (authorizationStrategy != null)
1993                {
1994                        return authorizationStrategy.isActionAuthorized(this, action);
1995                }
1996                return true;
1997        }
1998
1999        /**
2000         * @return true if this component is authorized to be enabled, false otherwise
2001         */
2002        public final boolean isEnableAllowed()
2003        {
2004                return isActionAuthorized(ENABLE);
2005        }
2006
2007        /**
2008         * Gets whether this component is enabled. Specific components may decide to implement special
2009         * behavior that uses this property, like web form components that add a disabled='disabled'
2010         * attribute when enabled is false.
2011         * 
2012         * @return Whether this component is enabled.
2013         */
2014        public boolean isEnabled()
2015        {
2016                return getFlag(FLAG_ENABLED);
2017        }
2018
2019        /**
2020         * Checks the security strategy if the {@link Component#RENDER} action is allowed on this
2021         * component
2022         * 
2023         * @return true if {@link Component#RENDER} action is allowed, false otherwise
2024         */
2025        public final boolean isRenderAllowed()
2026        {
2027                return getFlag(FLAG_IS_RENDER_ALLOWED);
2028        }
2029
2030        /**
2031         * Returns if the component is stateless or not. It checks the stateless hint if that is false
2032         * it returns directly false. If that is still true it checks all its behaviors if they can be
2033         * stateless.
2034         * 
2035         * @return whether the component is stateless.
2036         */
2037        public final boolean isStateless()
2038        {
2039                if ((isVisibleInHierarchy() && isEnabledInHierarchy()) == false && canCallListener() == false)
2040                {
2041                        // the component is either invisible or disabled and it can't call listeners
2042                        // then pretend the component is stateless
2043                        return true;
2044                }
2045
2046                if (!getStatelessHint())
2047                {
2048                        return false;
2049                }
2050
2051                for (Behavior behavior : getBehaviors())
2052                {
2053                        if (!behavior.getStatelessHint(this))
2054                        {
2055                                return false;
2056                        }
2057                }
2058                return true;
2059        }
2060
2061        /**
2062         * @return {@code true} if this component should notify its holding page about changes in its
2063         *         state. If a {@link Page} is not versioned then it wont track changes in its
2064         *         components and will use the same {@link Page#getPageId()} during its lifetime
2065         */
2066        public boolean isVersioned()
2067        {
2068                // Is the component itself versioned?
2069                if (!getFlag(FLAG_VERSIONED))
2070                {
2071                        return false;
2072                }
2073                else
2074                {
2075                        // If there's a parent and this component is versioned
2076                        if (parent != null)
2077                        {
2078                                // Check if the parent is unversioned. If any parent
2079                                // (recursively) is unversioned, then this component is too
2080                                if (!parent.isVersioned())
2081                                {
2082                                        return false;
2083                                }
2084                        }
2085                        return true;
2086                }
2087        }
2088
2089        /**
2090         * Gets whether this component and any children are visible.
2091         * <p>
2092         * WARNING: this method can be called multiple times during a request. If you override this
2093         * method, it is a good idea to keep it cheap in terms of processing. Alternatively, you can
2094         * call {@link #setVisible(boolean)}.
2095         * <p>
2096         * 
2097         * @return True if component and any children are visible
2098         */
2099        public boolean isVisible()
2100        {
2101                return getFlag(FLAG_VISIBLE);
2102        }
2103
2104        /**
2105         * Checks if the component itself and all its parents are visible.
2106         * 
2107         * @return true if the component and all its parents are visible.
2108         */
2109        public final boolean isVisibleInHierarchy()
2110        {
2111                if (getRequestFlag(RFLAG_VISIBLE_IN_HIERARCHY_SET))
2112                {
2113                        return getRequestFlag(RFLAG_VISIBLE_IN_HIERARCHY_VALUE);
2114                }
2115
2116                final boolean state;
2117                Component parent = getParent();
2118                if (parent != null && !parent.isVisibleInHierarchy())
2119                {
2120                        state = false;
2121                }
2122                else
2123                {
2124                        state = determineVisibility();
2125                }
2126
2127                setRequestFlag(RFLAG_VISIBLE_IN_HIERARCHY_SET, true);
2128                setRequestFlag(RFLAG_VISIBLE_IN_HIERARCHY_VALUE, state);
2129                return state;
2130        }
2131
2132        /**
2133         * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT!
2134         * 
2135         * Sets the RENDERING flag and removes the PREPARED_FOR_RENDER flag on component and it's
2136         * children.
2137         * 
2138         * @param setRenderingFlag
2139         *            if this is false only the PREPARED_FOR_RENDER flag is removed from component, the
2140         *            RENDERING flag is not set.
2141         */
2142        public final void markRendering(boolean setRenderingFlag)
2143        {
2144                internalMarkRendering(setRenderingFlag);
2145        }
2146
2147        /**
2148         * Called to indicate that the model content for this component has been changed
2149         */
2150        public final void modelChanged()
2151        {
2152                // Call user code
2153                internalOnModelChanged();
2154                onModelChanged();
2155        }
2156
2157        /**
2158         * Called to indicate that the model content for this component is about to change
2159         */
2160        public final void modelChanging()
2161        {
2162                checkHierarchyChange(this);
2163
2164                // Call user code
2165                onModelChanging();
2166
2167                // Tell the page that our model changed
2168                final Page page = findPage();
2169                if (page != null)
2170                {
2171                        page.componentModelChanging(this);
2172                }
2173        }
2174
2175        /**
2176         * Redirects browser to an intermediate page such as a sign-in page. The current request's URL
2177         * is saved for future use by method {@link #continueToOriginalDestination()}; only use this method when
2178         * you plan to continue to the current URL at some later time; otherwise just set a new response page.
2179         * 
2180         * @param page
2181         *            The sign in page
2182         *
2183         * @see #setResponsePage(Class)
2184         * @see #setResponsePage(IRequestablePage)
2185         * @see #setResponsePage(Class, PageParameters)
2186         * @see Component#continueToOriginalDestination()
2187         */
2188        public final void redirectToInterceptPage(final Page page)
2189        {
2190                throw new RestartResponseAtInterceptPageException(page);
2191        }
2192
2193        /**
2194         * Removes this component from its parent. It's important to remember that a component that is
2195         * removed cannot be referenced from the markup still.
2196         * <p>
2197         * You must not use this method in your callback to any of the
2198         * {@link MarkupContainer#visitChildren(IVisitor)} methods. See <a
2199         * href="https://issues.apache.org/jira/browse/WICKET-3229">WICKET-3329</a>.
2200         */
2201        public final void remove()
2202        {
2203                if (parent == null)
2204                {
2205                        throw new IllegalStateException("Cannot remove " + this + " from null parent!");
2206                }
2207                parent.remove(this);
2208        }
2209
2210        /**
2211         * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT!
2212         * <p>
2213         * Renders this component as a part of a response - the caller has to
2214         * make sure that this component is prepared for render.
2215         * 
2216         * @see #beforeRender()
2217         */
2218        public final void renderPart() {
2219                Page page = getPage();
2220
2221                page.startComponentRender(this);
2222
2223                markRendering(true);
2224
2225                render();
2226                
2227                page.endComponentRender(this);
2228        }
2229
2230        /**
2231         * Render this component and all its children. Always calls hook {@link #onAfterRender()}
2232         * regardless of any exception.
2233         */
2234        public final void render()
2235        {
2236                if (isAuto())
2237                {
2238                        // auto components are prepared when rendered
2239                        beforeRender();
2240                }
2241
2242                // Do the render
2243                RuntimeException exception = null;
2244                try
2245                {
2246                        setRequestFlag(RFLAG_RENDERING, true);
2247                        
2248                        internalRender();
2249                }
2250                catch (final RuntimeException ex)
2251                {
2252                        // Remember it as the originating exception
2253                        exception = ex;
2254                }
2255                finally
2256                {
2257                        try
2258                        {
2259                                // Cleanup
2260                                afterRender();
2261                        }
2262                        catch (RuntimeException ex2)
2263                        {
2264                                // Only remember it if not already another exception happened
2265                                if (exception == null)
2266                                {
2267                                        exception = ex2;
2268                                }
2269                        }
2270                }
2271
2272                // Re-throw if needed
2273                if (exception != null)
2274                {
2275                        throw exception;
2276                }
2277        }
2278
2279        /**
2280         * Performs a render of this component as part of a Page level render process.
2281         */
2282        private void internalRender()
2283        {
2284                // Make sure there is a markup available for the Component
2285                IMarkupFragment markup = getMarkup();
2286                if (markup == null)
2287                {
2288                        throw new MarkupNotFoundException("Markup not found for Component: " + toString());
2289                }
2290
2291                // MarkupStream is an Iterator for the markup
2292                MarkupStream markupStream = new MarkupStream(markup);
2293
2294                MarkupElement elem = markup.get(0);
2295                if (elem instanceof ComponentTag)
2296                {
2297                        // Guarantee that the markupStream is set and determineVisibility not yet tested
2298                        // See WICKET-2049
2299                        ((ComponentTag)elem).onBeforeRender(this, markupStream);
2300                }
2301
2302                // Determine if component is visible using it's authorization status
2303                // and the isVisible property.
2304                if (determineVisibility())
2305                {
2306                        setFlag(FLAG_HAS_BEEN_RENDERED, true);
2307
2308                        // Rendering is beginning
2309                        if (log.isDebugEnabled())
2310                        {
2311                                log.debug("Begin render {}", this);
2312                        }
2313
2314                        try
2315                        {
2316                                notifyBehaviorsComponentBeforeRender();
2317                                onRender();
2318                                notifyBehaviorsComponentRendered();
2319
2320                                // Component has been rendered
2321                                rendered();
2322                        }
2323                        catch (RuntimeException ex)
2324                        {
2325                                onException(ex);
2326                        }
2327
2328                        if (log.isDebugEnabled())
2329                        {
2330                                log.debug("End render {}", this);
2331                        }
2332                }
2333                // elem is null when rendering a page
2334                else if ((elem != null) && (elem instanceof ComponentTag))
2335                {
2336                        if (getFlag(FLAG_PLACEHOLDER))
2337                        {
2338                                renderPlaceholderTag(((ComponentTag)elem).mutable(), getResponse());
2339                        }
2340                }
2341        }
2342
2343        /**
2344         * Called when a runtime exception is caught during the render process
2345         * 
2346         * @param ex
2347         *            The exception caught.
2348         */
2349        private void onException(final RuntimeException ex)
2350        {
2351                // Call each behaviors onException() to allow the
2352                // behavior to clean up
2353                for (Behavior behavior : getBehaviors())
2354                {
2355                        if (isBehaviorAccepted(behavior))
2356                        {
2357                                try
2358                                {
2359                                        behavior.onException(this, ex);
2360                                }
2361                                catch (Exception ex2)
2362                                {
2363                                        log.error("Error while cleaning up after exception", ex2);
2364                                }
2365                        }
2366                }
2367
2368                // Re-throw the exception
2369                throw ex;
2370        }
2371
2372        /**
2373         * Renders a placeholder tag for the component when it is invisible and
2374         * {@link #setOutputMarkupPlaceholderTag(boolean)} has been called with <code>true</code>.
2375         * 
2376         * @param tag
2377         *            component tag
2378         * @param response
2379         *            response
2380         */
2381        protected void renderPlaceholderTag(final ComponentTag tag, final Response response)
2382        {
2383                String name = Strings.isEmpty(tag.getNamespace()) ? tag.getName()
2384                        : tag.getNamespace() + ':' + tag.getName();
2385                
2386                // prefer concatenation over String#format() for performance 
2387                response.write(
2388                        "<" + name + " id=\"" + getAjaxRegionMarkupId() +
2389                                "\" hidden=\"\" data-wicket-placeholder=\"\"></" + name + ">");
2390        }
2391
2392
2393        /**
2394         * Returns the id of the markup region that will be updated via ajax. This can be different to
2395         * the markup id of the component if a {@link IAjaxRegionMarkupIdProvider} behavior has been
2396         * added.
2397         * 
2398         * @return the markup id of the region to be updated via ajax.
2399         */
2400        public final String getAjaxRegionMarkupId()
2401        {
2402                String markupId = null;
2403                for (Behavior behavior : getBehaviors())
2404                {
2405                        if (behavior instanceof IAjaxRegionMarkupIdProvider && behavior.isEnabled(this))
2406                        {
2407                                markupId = ((IAjaxRegionMarkupIdProvider)behavior).getAjaxRegionMarkupId(this);
2408                                break;
2409                        }
2410                }
2411                if (markupId == null)
2412                {
2413                        if (this instanceof IAjaxRegionMarkupIdProvider)
2414                        {
2415                                markupId = ((IAjaxRegionMarkupIdProvider)this).getAjaxRegionMarkupId(this);
2416                        }
2417                }
2418                if (markupId == null)
2419                {
2420                        markupId = getMarkupId();
2421                }
2422                return markupId;
2423        }
2424
2425
2426        /**
2427         * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT!
2428         * <p>
2429         * Renders the component at the current position in the given markup stream. The method
2430         * onComponentTag() is called to allow the component to mutate the start tag. The method
2431         * onComponentTagBody() is then called to permit the component to render its body.
2432         */
2433        protected final void internalRenderComponent()
2434        {
2435                final IMarkupFragment markup = getMarkup();
2436                if (markup == null)
2437                {
2438                        throw new MarkupException("Markup not found. Component: " + toString());
2439                }
2440
2441                final MarkupStream markupStream = new MarkupStream(markup);
2442
2443                // Get mutable copy of next tag
2444                final ComponentTag openTag = markupStream.getTag();
2445                final ComponentTag tag = openTag.mutable();
2446
2447                // call application-wide tag listeners
2448                getApplication().getOnComponentTagListeners().onComponentTag(this, tag);
2449
2450                // Call any tag handler
2451                onComponentTag(tag);
2452
2453                // If we're an openclose tag
2454                if (!tag.isOpenClose() && !tag.isOpen())
2455                {
2456                        // We were something other than <tag> or <tag/>
2457                        markupStream.throwMarkupException("Method renderComponent called on bad markup element: " +
2458                                tag);
2459                }
2460
2461                if (tag.isOpenClose() && openTag.isOpen())
2462                {
2463                        markupStream.throwMarkupException("You can not modify a open tag to open-close: " + tag);
2464                }
2465
2466                try
2467                {
2468                        // Render open tag
2469                        boolean renderBodyOnly = getRenderBodyOnly();
2470                        if (renderBodyOnly)
2471                        {
2472                                ExceptionSettings.NotRenderableErrorStrategy notRenderableErrorStrategy = ExceptionSettings.NotRenderableErrorStrategy.LOG_WARNING;
2473                                if (Application.exists())
2474                                {
2475                                        notRenderableErrorStrategy = getApplication().getExceptionSettings().getNotRenderableErrorStrategy();
2476                                }
2477
2478                                if (getFlag(FLAG_OUTPUT_MARKUP_ID))
2479                                {
2480                                        String message = String.format("Markup id set on a component that renders its body only. " +
2481                                                                       "Markup id: %s, component id: %s, type: %s, path: %s",
2482                                                        getMarkupId(), getId(), getClass(), getPage().getPageClass() + ":" + getPageRelativePath());
2483                                        if (notRenderableErrorStrategy == ExceptionSettings.NotRenderableErrorStrategy.THROW_EXCEPTION)
2484                                        {
2485                                                throw new IllegalStateException(message);
2486                                        }
2487                                        log.warn(message);
2488                                }
2489                                if (getFlag(FLAG_PLACEHOLDER))
2490                                {
2491                                        String message = String.format("Placeholder tag set on a component that renders its body only. " +
2492                                                                       "Component id: %s, type: %s, path: %s\", ",
2493                                                        getId(), getClass(), getPage().getPageClass() + ":" + getPageRelativePath());
2494                                        if (notRenderableErrorStrategy == ExceptionSettings.NotRenderableErrorStrategy.THROW_EXCEPTION)
2495                                        {
2496                                                throw new IllegalStateException(message);
2497                                        }
2498                                        log.warn(message);
2499                                }
2500                        }
2501                        else
2502                        {
2503                                renderComponentTag(tag);
2504                        }
2505                        markupStream.next();
2506
2507                        // Render the body only if open-body-close. Do not render if open-close.
2508                        if (tag.isOpen())
2509                        {
2510                                // Render the body. The default strategy will simply call the component's
2511                                // onComponentTagBody() implementation.
2512                                getMarkupSourcingStrategy().onComponentTagBody(this, markupStream, tag);
2513
2514                                // Render close tag
2515                                if (openTag.isOpen())
2516                                {
2517                                        renderClosingComponentTag(markupStream, tag, renderBodyOnly);
2518                                }
2519                                else if (renderBodyOnly == false)
2520                                {
2521                                        if (needToRenderTag(openTag))
2522                                        {
2523                                                // Close the manually opened tag. And since the user might have changed the
2524                                                // tag name ...
2525                                                tag.writeSyntheticCloseTag(getResponse());
2526                                        }
2527                                }
2528                        }
2529                }
2530                catch (WicketRuntimeException wre)
2531                {
2532                        throw wre;
2533                }
2534                catch (RuntimeException re)
2535                {
2536                        throw new WicketRuntimeException("Exception in rendering component: " + this, re);
2537                }
2538        }
2539
2540        /**
2541         * 
2542         * @param openTag
2543         * @return true, if the tag shall be rendered
2544         */
2545        private boolean needToRenderTag(final ComponentTag openTag)
2546        {
2547                // If a open-close tag has been modified to be open-body-close then a
2548                // synthetic close tag must be rendered.
2549                boolean renderTag = (openTag != null && !(openTag instanceof WicketTag));
2550                if (renderTag == false)
2551                {
2552                        renderTag = !getApplication().getMarkupSettings().getStripWicketTags();
2553                }
2554                return renderTag;
2555        }
2556
2557        /**
2558         * Called to indicate that a component has been rendered. This method should only very rarely be
2559         * called at all. Some components may render its children without calling render() on them.
2560         * These components need to call rendered() to indicate that its child components were actually
2561         * rendered, the framework would think they had never been rendered, and in development mode
2562         * this would result in a runtime exception.
2563         */
2564        public final void rendered()
2565        {
2566                Page page = findPage();
2567                if (page != null)
2568                {
2569                        // Tell the page that the component rendered
2570                        page.componentRendered(this);
2571                }
2572                else
2573                {
2574                        log.error("Component is not connected to a Page. Cannot register the component as being rendered. Component: " +
2575                                toString());
2576                }
2577        }
2578
2579        /**
2580         * Get the markup sourcing strategy for the component. If null,
2581         * {@link #newMarkupSourcingStrategy()} will be called.
2582         * 
2583         * @return Markup sourcing strategy
2584         */
2585        protected final IMarkupSourcingStrategy getMarkupSourcingStrategy()
2586        {
2587                if (markupSourcingStrategy == null)
2588                {
2589                        markupSourcingStrategy = newMarkupSourcingStrategy();
2590
2591                        // If not strategy by provided, than we use a default one.
2592                        if (markupSourcingStrategy == null)
2593                        {
2594                                markupSourcingStrategy = DefaultMarkupSourcingStrategy.get();
2595                        }
2596                }
2597                return markupSourcingStrategy;
2598        }
2599
2600        /**
2601         * If {@link #getMarkupSourcingStrategy()} returns null, this method will be called. By default
2602         * it returns null, which means that a default markup strategy will be attached to the
2603         * component.
2604         * <p>
2605         * Please note that markup source strategies are not persisted. Instead they get re-created by
2606         * calling this method again. That's ok since markup sourcing strategies usually do not maintain
2607         * a state.
2608         * 
2609         * @return Markup sourcing strategy
2610         */
2611        protected IMarkupSourcingStrategy newMarkupSourcingStrategy()
2612        {
2613                return null;
2614        }
2615
2616        /**
2617         * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT!
2618         * 
2619         * Print to the web response what ever the component wants to contribute to the head section.
2620         * Make sure that all attached behaviors are asked as well.
2621         * <p>
2622         * NOT intended for overriding by framework clients. Rather, use
2623         * {@link Component#renderHead(org.apache.wicket.markup.head.IHeaderResponse)}
2624         * </p>
2625         * 
2626         * @param container
2627         *            The HtmlHeaderContainer
2628         */
2629        public void internalRenderHead(final HtmlHeaderContainer container)
2630        {
2631                if (isVisibleInHierarchy() && isRenderAllowed())
2632                {
2633                        if (log.isDebugEnabled())
2634                        {
2635                                log.debug("internalRenderHead: {}", toString(false));
2636                        }
2637
2638                        IHeaderResponse response = container.getHeaderResponse();
2639
2640                        // Allow component to contribute
2641                        boolean wasRendered = response.wasRendered(this);
2642                        if (wasRendered == false)
2643                        {
2644                                LazyStringResponse markupHeaderResponse = new LazyStringResponse();
2645                                Response oldResponse = getResponse();
2646                                RequestCycle.get().setResponse(markupHeaderResponse);
2647                                try
2648                                {
2649                                        // Make sure the markup source strategy contributes to the header first
2650                                        // to be backward compatible. WICKET-3761
2651                                        getMarkupSourcingStrategy().renderHead(this, container);
2652                                        CharSequence headerContribution = markupHeaderResponse.getBuffer();
2653                                        if (Strings.isEmpty(headerContribution) == false)
2654                                        {
2655                                                response.render(StringHeaderItem.forString(headerContribution));
2656                                        }
2657                                }
2658                                finally
2659                                {
2660                                        RequestCycle.get().setResponse(oldResponse);
2661                                }
2662                                // Then let the component itself to contribute to the header
2663                                renderHead(response);
2664                        }
2665
2666                        // Then ask all behaviors
2667                        for (Behavior behavior : getBehaviors())
2668                        {
2669                                if (isBehaviorAccepted(behavior))
2670                                {
2671                                        List<IClusterable> pair = List.of(this, behavior);
2672                                        if (!response.wasRendered(pair))
2673                                        {
2674                                                behavior.renderHead(this, response);
2675                                                response.markRendered(pair);
2676                                        }
2677                                }
2678                        }
2679                        
2680                        if (wasRendered == false)
2681                        {
2682                                response.markRendered(this);
2683                        }
2684                }
2685        }
2686
2687        /**
2688         * Replaces this component with another. The replacing component must have the same component id
2689         * as this component. This method serves as a shortcut to
2690         * 
2691         * <code>this.getParent().replace(replacement)</code>
2692         * 
2693         * and provides a better context for errors.
2694         * <p>
2695         * Usage: <code>component = component.replaceWith(replacement);</code>
2696         * </p>
2697         * 
2698         * @since 1.2.1
2699         * 
2700         * @param replacement
2701         *            component to replace this one
2702         * @return the component which replaced this one
2703         */
2704        public Component replaceWith(Component replacement)
2705        {
2706                Args.notNull(replacement, "replacement");
2707
2708                if (!getId().equals(replacement.getId()))
2709                {
2710                        throw new IllegalArgumentException(
2711                                "Replacement component must have the same id as the component it will replace. Replacement id [[" +
2712                                        replacement.getId() + "]], replaced id [[" + getId() + "]].");
2713                }
2714                if (parent == null)
2715                {
2716                        throw new IllegalStateException(
2717                                "This method can only be called on a component that has already been added to its parent.");
2718                }
2719                parent.replace(replacement);
2720                return replacement;
2721        }
2722
2723        /**
2724         * @param component
2725         *            The component to compare with
2726         * @return True if the given component's model is the same as this component's model.
2727         */
2728        public final boolean sameInnermostModel(final Component component)
2729        {
2730                return sameInnermostModel(component.getDefaultModel());
2731        }
2732
2733        /**
2734         * @param model
2735         *            The model to compare with
2736         * @return True if the given component's model is the same as this component's model.
2737         */
2738        public final boolean sameInnermostModel(final IModel<?> model)
2739        {
2740                // Get the two models
2741                IModel<?> thisModel = getDefaultModel();
2742
2743                // If both models are non-null they could be the same
2744                if (thisModel != null && model != null)
2745                {
2746                        return getInnermostModel(thisModel) == getInnermostModel(model);
2747                }
2748
2749                return false;
2750        }
2751
2752        /**
2753         * Sets whether this component is enabled. Specific components may decide to implement special
2754         * behavior that uses this property, like web form components that add a disabled='disabled'
2755         * attribute when enabled is false. If it is not enabled, it will not be allowed to call any
2756         * listener method on it (e.g. Link.onClick) and the model object will be protected (for the
2757         * common use cases, not for programmer's misuse)
2758         * 
2759         * @param enabled
2760         *            whether this component is enabled
2761         * @return This
2762         */
2763        public final Component setEnabled(final boolean enabled)
2764        {
2765                // Is new enabled state a change?
2766                if (enabled != getFlag(FLAG_ENABLED))
2767                {
2768                        // Tell the page that this component's enabled was changed
2769                        if (isVersioned())
2770                        {
2771                                final Page page = findPage();
2772                                if (page != null)
2773                                {
2774                                        addStateChange();
2775                                }
2776                        }
2777
2778                        // Change visibility
2779                        setFlag(FLAG_ENABLED, enabled);
2780                        onEnabledStateChanged();
2781                }
2782                return this;
2783        }
2784
2785        void clearEnabledInHierarchyCache()
2786        {
2787                setRequestFlag(RFLAG_ENABLED_IN_HIERARCHY_SET, false);
2788        }
2789
2790        void onEnabledStateChanged()
2791        {
2792                clearEnabledInHierarchyCache();
2793        }
2794
2795        /**
2796         * Sets whether model strings should be escaped.
2797         * 
2798         * @param escapeMarkup
2799         *            True is model strings should be escaped
2800         * @return This
2801         */
2802        public final Component setEscapeModelStrings(final boolean escapeMarkup)
2803        {
2804                setFlag(FLAG_ESCAPE_MODEL_STRINGS, escapeMarkup);
2805                return this;
2806        }
2807
2808        /**
2809         * Set markup ID, which must be String or Integer
2810         * 
2811         * @param markupId
2812         */
2813        public final void setMarkupIdImpl(Object markupId)
2814        {
2815                if (markupId != null && !(markupId instanceof String) && !(markupId instanceof Integer))
2816                {
2817                        throw new IllegalArgumentException("markupId must be String or Integer");
2818                }
2819
2820                setOutputMarkupId(true);
2821                if (markupId instanceof Integer)
2822                {
2823                        generatedMarkupId = (Integer)markupId;
2824                        setMetaData(MARKUP_ID_KEY, null);
2825                        return;
2826                }
2827
2828                generatedMarkupId = -1;
2829                setMetaData(MARKUP_ID_KEY, (String)markupId);
2830
2831        }
2832
2833        /**
2834         * Copy markupId
2835         * 
2836         * @param comp
2837         */
2838        final void setMarkupId(Component comp)
2839        {
2840                Args.notNull(comp, "comp");
2841
2842                generatedMarkupId = comp.generatedMarkupId;
2843                setMetaData(MARKUP_ID_KEY, comp.getMetaData(MARKUP_ID_KEY));
2844                if (comp.getOutputMarkupId())
2845                {
2846                        setOutputMarkupId(true);
2847                }
2848        }
2849
2850        /**
2851         * Sets this component's markup id to a user defined value. It is up to the user to ensure this
2852         * value is unique.
2853         * <p>
2854         * The recommended way is to let wicket generate the value automatically, this method is here to
2855         * serve as an override for that value in cases where a specific id must be used.
2856         * <p>
2857         * If null is passed in the user defined value is cleared and markup id value will fall back on
2858         * automatically generated value
2859         * 
2860         * @see #getMarkupId()
2861         * 
2862         * @param markupId
2863         *            markup id value or null to clear any previous user defined value
2864         * @return this for chaining
2865         */
2866        public Component setMarkupId(String markupId)
2867        {
2868                Args.notEmpty(markupId, "markupId");
2869
2870                // TODO check if an automatic id has already been generated or getmarkupid() called
2871                // previously and throw an illegalstateexception because something else might be depending
2872                // on previous id
2873
2874                setMarkupIdImpl(markupId);
2875                return this;
2876        }
2877
2878        /**
2879         * Sets the metadata for this component using the given key. If the metadata object is not of
2880         * the correct type for the metadata key, an IllegalArgumentException will be thrown. For
2881         * information on creating MetaDataKeys, see {@link MetaDataKey}.
2882         * 
2883         * @param <M>
2884         *            The type of the metadata
2885         * 
2886         * @param key
2887         *            The singleton key for the metadata
2888         * @param object
2889         *            The metadata object
2890         * @throws IllegalArgumentException
2891         * @see MetaDataKey
2892         */
2893        @Override
2894        public final <M extends Serializable> Component setMetaData(final MetaDataKey<M> key, final M object)
2895        {
2896                MetaDataEntry<?>[] old = getMetaData();
2897
2898                Object metaData = null;
2899                MetaDataEntry<?>[] metaDataArray = key.set(old, object);
2900                if (metaDataArray != null && metaDataArray.length > 0)
2901                {
2902                        metaData = (metaDataArray.length > 1) ? metaDataArray : metaDataArray[0];
2903                }
2904
2905                int index = getFlag(FLAG_MODEL_SET) ? 1 : 0;
2906
2907                if (old == null && metaData != null)
2908                {
2909                        data_insert(index, metaData);
2910                }
2911                else if (old != null && metaData != null)
2912                {
2913                        data_set(index, metaData);
2914                }
2915                else if (old != null && metaData == null)
2916                {
2917                        data_remove(index);
2918                }
2919                return this;
2920        }
2921
2922        /**
2923         * Sets the given model.
2924         * <p>
2925         * WARNING: DO NOT OVERRIDE THIS METHOD UNLESS YOU HAVE A VERY GOOD REASON FOR IT. OVERRIDING
2926         * THIS MIGHT OPEN UP SECURITY LEAKS AND BREAK BACK-BUTTON SUPPORT.
2927         * </p>
2928         * 
2929         * @param model
2930         *            The model
2931         * @return This
2932         */
2933        public Component setDefaultModel(final IModel<?> model)
2934        {
2935                IModel<?> prevModel = getModelImpl();
2936
2937                IModel<?> wrappedModel = prevModel;
2938                if (prevModel instanceof IWrapModel)
2939                {
2940                        wrappedModel = ((IWrapModel<?>)prevModel).getWrappedModel();
2941                }
2942
2943                // Change model
2944                if (wrappedModel != model)
2945                {
2946                        // Detach the old/current model
2947                        if (prevModel != null)
2948                        {
2949                                prevModel.detach();
2950                        }
2951
2952                        modelChanging();
2953                        setModelImpl(wrap(model));
2954                        modelChanged();
2955
2956                        // WICKET-3413 reset 'inherited model' when model is explicitely set
2957                        setFlag(FLAG_INHERITABLE_MODEL, false);
2958                }
2959
2960                return this;
2961        }
2962
2963        /**
2964         * @return model
2965         */
2966        IModel<?> getModelImpl()
2967        {
2968                if (getFlag(FLAG_MODEL_SET))
2969                {
2970                        return (IModel<?>)data_get(0);
2971                }
2972                return null;
2973        }
2974
2975        /**
2976         * 
2977         * @param model
2978         */
2979        void setModelImpl(IModel<?> model)
2980        {
2981                if (getFlag(FLAG_MODEL_SET))
2982                {
2983                        if (model != null)
2984                        {
2985                                data_set(0, model);
2986                        }
2987                        else
2988                        {
2989                                data_remove(0);
2990                                setFlag(FLAG_MODEL_SET, false);
2991                        }
2992                }
2993                else
2994                {
2995                        if (model != null)
2996                        {
2997                                data_insert(0, model);
2998                                setFlag(FLAG_MODEL_SET, true);
2999                        }
3000                }
3001        }
3002
3003        /**
3004         * Sets the backing model object. Unlike <code>getDefaultModel().setObject(object)</code>, this
3005         * method checks authorisation and model comparator, and invokes <code>modelChanging</code> and
3006         * <code>modelChanged</code> if the value really changes.
3007         * 
3008         * @param object
3009         *            The object to set
3010         * @return This
3011         * @throws IllegalStateException If the component has neither its own model nor any of its
3012         * parents uses {@link IComponentInheritedModel}
3013         */
3014        @SuppressWarnings("unchecked")
3015        public final Component setDefaultModelObject(final Object object)
3016        {
3017                final IModel<Object> model = (IModel<Object>)getDefaultModel();
3018
3019                // Check whether anything can be set at all
3020                if (model == null)
3021                {
3022                        throw new IllegalStateException(
3023                                "Attempt to set a model object on a component without a model! " +
3024                                "Either pass an IModel to the constructor or use #setDefaultModel(new SomeModel(object)). " +
3025                                "Component: " + getPageRelativePath());
3026                }
3027
3028                // Check authorization
3029                if (!isActionAuthorized(ENABLE))
3030                {
3031                        throw new UnauthorizedActionException(this, ENABLE);
3032                }
3033
3034                // Check whether this will result in an actual change
3035                if (!getModelComparator().compare(this, object))
3036                {
3037                        modelChanging();
3038                        try
3039                        {
3040                                model.setObject(object);
3041                        }
3042                        catch (UnsupportedOperationException uox)
3043                        {
3044                                throw new WicketRuntimeException("You need to use writeable IModel for component " + getPageRelativePath(), uox);
3045                        }
3046                        modelChanged();
3047                }
3048
3049                return this;
3050        }
3051
3052        /**
3053         * Sets whether or not component will output id attribute into the markup. id attribute will be
3054         * set to the value returned from {@link Component#getMarkupId()}.
3055         * 
3056         * @param output
3057         *            True if the component will output the id attribute into markup. Please note that
3058         *            the default behavior is to use the same id as the component. This means that your
3059         *            component must begin with [a-zA-Z] in order to generate a valid markup id
3060         *            according to: http://www.w3.org/TR/html401/types.html#type-name
3061         * 
3062         * @return this for chaining
3063         */
3064        public final Component setOutputMarkupId(final boolean output)
3065        {
3066                setFlag(FLAG_OUTPUT_MARKUP_ID, output);
3067                return this;
3068        }
3069
3070        /**
3071         * Render a placeholder tag when the component is not visible. The tag is of form:
3072         * &lt;componenttag hidden="" id="markupid"/&gt;. This method will also call
3073         * <code>setOutputMarkupId(true)</code>.
3074         * 
3075         * This is useful, for example, in ajax situations where the component starts out invisible and
3076         * then becomes visible through an ajax update. With a placeholder tag already in the markup you
3077         * do not need to repaint this component's parent, instead you can repaint the component
3078         * directly.
3079         * 
3080         * When this method is called with parameter <code>false</code> the outputmarkupid flag is not
3081         * reverted to false.
3082         * 
3083         * @param outputTag
3084         * @return this for chaining
3085         */
3086        public final Component setOutputMarkupPlaceholderTag(final boolean outputTag)
3087        {
3088                if (outputTag != getFlag(FLAG_PLACEHOLDER))
3089                {
3090                        if (outputTag)
3091                        {
3092                                setOutputMarkupId(true);
3093                                setFlag(FLAG_PLACEHOLDER, true);
3094                        }
3095                        else
3096                        {
3097                                setFlag(FLAG_PLACEHOLDER, false);
3098                                // I think it's better to not setOutputMarkupId to false...
3099                                // user can do it if she want
3100                        }
3101                }
3102                return this;
3103        }
3104
3105        /**
3106         * If false the component's tag will be printed as well as its body (which is default). If true
3107         * only the body will be printed, but not the component's tag.
3108         * 
3109         * @param renderTag
3110         *            If true, the component tag will not be printed
3111         * @return This
3112         */
3113        public final Component setRenderBodyOnly(final boolean renderTag)
3114        {
3115                setFlag(FLAG_RENDER_BODY_ONLY, renderTag);
3116                return this;
3117        }
3118
3119        /**
3120         * Sets the page that will respond to this request
3121         * 
3122         * @param <C>
3123         * 
3124         * @param cls
3125         *            The response page class
3126         * @see RequestCycle#setResponsePage(Class)
3127         */
3128        public final <C extends IRequestablePage> void setResponsePage(final Class<C> cls)
3129        {
3130                getRequestCycle().setResponsePage(cls, (PageParameters)null);
3131        }
3132
3133        /**
3134         * Sets the page class and its parameters that will respond to this request
3135         * 
3136         * @param <C>
3137         * 
3138         * @param cls
3139         *            The response page class
3140         * @param parameters
3141         *            The parameters for this bookmarkable page.
3142         * @see RequestCycle#setResponsePage(Class, PageParameters)
3143         */
3144        public final <C extends IRequestablePage> void setResponsePage(final Class<C> cls,
3145                PageParameters parameters)
3146        {
3147                getRequestCycle().setResponsePage(cls, parameters);
3148        }
3149
3150        /**
3151         * Sets the page that will respond to this request
3152         * 
3153         * @param page
3154         *            The response page
3155         * 
3156         * @see RequestCycle#setResponsePage(org.apache.wicket.request.component.IRequestablePage)
3157         */
3158        public final void setResponsePage(final IRequestablePage page)
3159        {
3160                getRequestCycle().setResponsePage(page);
3161        }
3162
3163        /**
3164         * @param versioned
3165         *            True to turn on versioning for this component, false to turn it off for this
3166         *            component and any children.
3167         * @return This
3168         */
3169        public Component setVersioned(boolean versioned)
3170        {
3171                setFlag(FLAG_VERSIONED, versioned);
3172                return this;
3173        }
3174
3175        /**
3176         * Sets whether this component and any children are visible.
3177         * 
3178         * @param visible
3179         *            True if this component and any children should be visible
3180         * @return This
3181         */
3182        public final Component setVisible(final boolean visible)
3183        {
3184                // Is new visibility state a change?
3185                if (visible != getFlag(FLAG_VISIBLE))
3186                {
3187                        // record component's visibility change
3188                        addStateChange();
3189
3190                        // Change visibility
3191                        setFlag(FLAG_VISIBLE, visible);
3192                        onVisibleStateChanged();
3193                }
3194                return this;
3195        }
3196
3197        void clearVisibleInHierarchyCache()
3198        {
3199                setRequestFlag(RFLAG_VISIBLE_IN_HIERARCHY_SET, false);
3200        }
3201
3202        void onVisibleStateChanged()
3203        {
3204                clearVisibleInHierarchyCache();
3205        }
3206
3207
3208        /**
3209         * Gets the string representation of this component.
3210         * 
3211         * @return The path to this component
3212         */
3213        @Override
3214        public String toString()
3215        {
3216                return toString(false);
3217        }
3218
3219        /**
3220         * @param detailed
3221         *            True if a detailed string is desired
3222         * @return The string
3223         */
3224        public String toString(final boolean detailed)
3225        {
3226                try
3227                {
3228                        final StringBuilder buffer = new StringBuilder();
3229                        buffer.append("[Component id = ").append(getId());
3230
3231                        if (detailed)
3232                        {
3233                                final Page page = findPage();
3234                                if (page == null)
3235                                {
3236                                        buffer.append(", page = <No Page>, path = ")
3237                                                .append(getPath())
3238                                                .append('.')
3239                                                .append(Classes.simpleName(getClass()));
3240                                }
3241                                else
3242                                {
3243                                        buffer.append(", page = ")
3244                                                .append(Classes.name(getPage().getPageClass()))
3245                                                .append(", path = ")
3246                                                .append(getPageRelativePath())
3247                                                .append(", type = ")
3248                                                .append(Classes.name(getClass()))
3249                                                .append(", isVisible = ")
3250                                                .append((determineVisibility()))
3251                                                .append(", isVersioned = ")
3252                                                .append(isVersioned());
3253                                }
3254
3255                                if (markup != null)
3256                                {
3257                                        buffer.append(", markup = ").append(new MarkupStream(getMarkup()).toString());
3258                                }
3259                        }
3260
3261                        buffer.append(']');
3262
3263                        return buffer.toString();
3264                }
3265                catch (Exception e)
3266                {
3267                        log.warn("Error while building toString()", e);
3268                        return String.format(
3269                                "[Component id = %s <attributes are not available because exception %s was thrown during toString()>]",
3270                                getId(), e.getClass().getName());
3271                }
3272        }
3273
3274        /**
3275         * Returns a bookmarkable URL that references a given page class using a given set of page
3276         * parameters. Since the URL which is returned contains all information necessary to instantiate
3277         * and render the page, it can be stored in a user's browser as a stable bookmark.
3278         * 
3279         * @param <C>
3280         * 
3281         * @see RequestCycle#urlFor(Class, org.apache.wicket.request.mapper.parameter.PageParameters)
3282         * 
3283         * @param pageClass
3284         *            Class of page
3285         * @param parameters
3286         *            Parameters to page
3287         * @return Bookmarkable URL to page
3288         */
3289        public final <C extends Page> CharSequence urlFor(final Class<C> pageClass,
3290                final PageParameters parameters)
3291        {
3292                return getRequestCycle().urlFor(pageClass, parameters);
3293        }
3294
3295        /**
3296         * Gets a URL for the listener interface on a behavior (e.g. {@link IRequestListener} on
3297         * {@link org.apache.wicket.ajax.markup.html.navigation.paging.AjaxPagingNavigationBehavior}).
3298         * 
3299         * @param behaviour
3300         *            The behavior that the URL should point to
3301         * @param parameters
3302         *            The parameters that should be rendered into the urls
3303         * @return The URL
3304         */
3305        public final CharSequence urlForListener(final Behavior behaviour, final PageParameters parameters)
3306        {
3307                int id = getBehaviorId(behaviour);
3308                IRequestHandler handler = createRequestHandler(parameters, id);
3309                return getRequestCycle().urlFor(handler);
3310        }
3311
3312        /**
3313         * Create a suitable request handler depending whether the page is stateless or bookmarkable.
3314         */
3315        private IRequestHandler createRequestHandler(PageParameters parameters, Integer id)
3316        {
3317                Page page = getPage();
3318
3319                PageAndComponentProvider provider = new PageAndComponentProvider(page, this, parameters);
3320
3321                if (page.isPageStateless()
3322                        || (page.isBookmarkable() && page.wasCreatedBookmarkable()))
3323                {
3324                        return new BookmarkableListenerRequestHandler(provider, id);
3325                }
3326                else
3327                {
3328                        return new ListenerRequestHandler(provider, id);
3329                }
3330        }
3331
3332        /**
3333         * Returns a URL that references the given request target.
3334         * 
3335         * @see RequestCycle#urlFor(IRequestHandler)
3336         * 
3337         * @param requestHandler
3338         *            the request target to reference
3339         * 
3340         * @return a URL that references the given request target
3341         */
3342        public final CharSequence urlFor(final IRequestHandler requestHandler)
3343        {
3344                return getRequestCycle().urlFor(requestHandler);
3345        }
3346
3347        /**
3348         * Gets a URL for this {@link IRequestListener}.
3349         * 
3350         * @see RequestCycle#urlFor(IRequestHandler)
3351         * 
3352         * @param parameters
3353         *            The parameters that should be rendered into the URL
3354         * @return The URL
3355         */
3356        public final CharSequence urlForListener(final PageParameters parameters)
3357        {
3358                IRequestHandler handler = createRequestHandler(parameters, null);
3359                return getRequestCycle().urlFor(handler);
3360        }
3361
3362        /**
3363         * Returns a URL that references a shared resource through the provided resource reference.
3364         * 
3365         * @see RequestCycle#urlFor(IRequestHandler)
3366         * 
3367         * @param resourceReference
3368         *            The resource reference
3369         * @param parameters
3370         *            parameters or {@code null} if none
3371         * @return The url for the shared resource
3372         */
3373        public final CharSequence urlFor(final ResourceReference resourceReference,
3374                PageParameters parameters)
3375        {
3376                return getRequestCycle().urlFor(resourceReference, parameters);
3377        }
3378
3379        /**
3380         * Traverses all parent components of the given class in this parentClass, calling the visitor's
3381         * visit method at each one.
3382         * 
3383         * @param <R>
3384         *            the type of the result object
3385         * @param parentClass
3386         *            Class
3387         * @param visitor
3388         *            The visitor to call at each parent of the given type
3389         * @return First non-null value returned by visitor callback
3390         */
3391        public final <R, C extends MarkupContainer> R visitParents(final Class<C> parentClass,
3392                final IVisitor<C, R> visitor)
3393        {
3394                return visitParents(parentClass, visitor, IVisitFilter.ANY);
3395        }
3396
3397        /**
3398         * Traverses all parent components of the given class in this parentClass, calling the visitor's
3399         * visit method at each one.
3400         * 
3401         * @param <R>
3402         *            the type of the result object
3403         * @param parentClass
3404         *            the class of the parent component
3405         * @param visitor
3406         *            The visitor to call at each parent of the given type
3407         * @param filter
3408         *            a filter that adds an additional logic to the condition whether a parent container
3409         *            matches
3410         * @return First non-null value returned by visitor callback
3411         */
3412        @SuppressWarnings("unchecked")
3413        public final <R, C extends MarkupContainer> R visitParents(final Class<C> parentClass,
3414                final IVisitor<C, R> visitor, IVisitFilter filter)
3415        {
3416                Args.notNull(filter, "filter");
3417
3418                // Start here
3419                MarkupContainer current = getParent();
3420
3421                Visit<R> visit = new Visit<R>();
3422
3423                // Walk up containment hierarchy
3424                while (current != null)
3425                {
3426                        // Is current an instance of this class?
3427                        if (parentClass.isInstance(current) && filter.visitObject(current))
3428                        {
3429                                visitor.component((C)current, visit);
3430                                if (visit.isStopped())
3431                                {
3432                                        return visit.getResult();
3433                                }
3434                        }
3435
3436                        // Check parent
3437                        current = current.getParent();
3438                }
3439                return null;
3440        }
3441
3442        /**
3443         * Registers a warning feedback message for this component.
3444         * 
3445         * @param message
3446         *            The feedback message
3447         */
3448        @Override
3449        public final void warn(final Serializable message)
3450        {
3451                getFeedbackMessages().warn(this, message);
3452                addStateChange();
3453        }
3454
3455        /**
3456         * {@link Behavior#beforeRender(Component)} Notify all behaviors that are assigned to this
3457         * component that the component is about to be rendered.
3458         */
3459        private void notifyBehaviorsComponentBeforeRender()
3460        {
3461                for (Behavior behavior : getBehaviors())
3462                {
3463                        if (isBehaviorAccepted(behavior))
3464                        {
3465                                behavior.beforeRender(this);
3466                        }
3467                }
3468        }
3469
3470        /**
3471         * {@link Behavior#afterRender(Component)} Notify all behaviors that are assigned to this
3472         * component that the component has rendered.
3473         */
3474        private void notifyBehaviorsComponentRendered()
3475        {
3476                // notify the behaviors that component has been rendered
3477                for (Behavior behavior : getBehaviors())
3478                {
3479                        if (isBehaviorAccepted(behavior))
3480                        {
3481                                behavior.afterRender(this);
3482                        }
3483                }
3484        }
3485
3486        /**
3487         * TODO WICKET-NG rename to something more useful - like componentChanged(), this method used to
3488         * be called with a Change object
3489         * 
3490         * Adds state change to page.
3491         */
3492        protected final void addStateChange()
3493        {
3494                checkHierarchyChange(this);
3495                final Page page = findPage();
3496                if (page != null)
3497                {
3498                        page.componentStateChanging(this);
3499                }
3500        }
3501
3502        /**
3503         * Checks whether the given type has the expected name.
3504         * 
3505         * @param tag
3506         *            The tag to check
3507         * @param name
3508         *            The expected tag name
3509         * @throws MarkupException
3510         *             Thrown if the tag is not of the right name
3511         */
3512        protected final void checkComponentTag(final ComponentTag tag, final String name)
3513        {
3514                if (!tag.getName().equalsIgnoreCase(name))
3515                {
3516                        String msg = String.format("Component [%s] (path = [%s]) must be "
3517                                + "applied to a tag of type [%s], not: %s", getId(), getPath(), name,
3518                                tag.toUserDebugString());
3519
3520                        findMarkupStream().throwMarkupException(msg);
3521                }
3522        }
3523
3524        /**
3525         * Checks that a given tag has a required attribute value.
3526         * 
3527         * @param tag
3528         *            The tag
3529         * @param key
3530         *            The attribute key
3531         * @param values
3532         *            The required value for the attribute key
3533         * @throws MarkupException
3534         *             Thrown if the tag does not have the required attribute value
3535         */
3536        protected final void checkComponentTagAttribute(final ComponentTag tag, final String key,
3537                final String... values)
3538        {
3539                if (key != null)
3540                {
3541                        final String tagAttributeValue = tag.getAttributes().getString(key);
3542
3543                        boolean found = false;
3544                        if (tagAttributeValue != null)
3545                        {
3546                                for (String value : values)
3547                                {
3548                                        if (value.equalsIgnoreCase(tagAttributeValue))
3549                                        {
3550                                                found = true;
3551                                                break;
3552                                        }
3553                                }
3554                        }
3555
3556                        if (found == false)
3557                        {
3558                                String msg = String.format("Component [%s] (path = [%s]) must be applied to a tag "
3559                                                + "with [%s] attribute matching any of %s, not [%s]", getId(), getPath(), key,
3560                                                Arrays.toString(values), tagAttributeValue);
3561
3562                                findMarkupStream().throwMarkupException(msg);
3563                        }
3564                }
3565        }
3566
3567        /**
3568         * Checks whether the hierarchy may be changed at all, and throws an exception if this is not
3569         * the case.
3570         * 
3571         * @param component
3572         *            the component which is about to be added or removed
3573         */
3574        protected void checkHierarchyChange(final Component component)
3575        {
3576                // Throw exception if modification is attempted during rendering
3577                if (getRequestFlag(RFLAG_RENDERING) && !component.isAuto())
3578                {
3579                        throw new WicketRuntimeException(
3580                                "Cannot modify component hierarchy after render phase has started (page version cant change then anymore)");
3581                }
3582        }
3583
3584        /**
3585         * Detaches the model for this component if it is detachable.
3586         */
3587        protected void detachModel()
3588        {
3589                IModel<?> model = getModelImpl();
3590                if (model != null)
3591                {
3592                        model.detach();
3593                }
3594                // also detach the wrapped model of a component assigned wrap (not
3595                // inherited)
3596                if (model instanceof IWrapModel && !getFlag(FLAG_INHERITABLE_MODEL))
3597                {
3598                        ((IWrapModel<?>)model).getWrappedModel().detach();
3599                }
3600        }
3601
3602        /**
3603         * Suffixes an exception message with useful information about this. component.
3604         * 
3605         * @param message
3606         *            The message
3607         * @return The modified message
3608         */
3609        protected final String exceptionMessage(final String message)
3610        {
3611                return message + ":\n" + toString();
3612        }
3613
3614        /**
3615         * Finds the markup stream for this component.
3616         * 
3617         * @return The markup stream for this component. Since a Component cannot have a markup stream,
3618         *         we ask this component's parent to search for it.
3619         */
3620        protected final MarkupStream findMarkupStream()
3621        {
3622                return new MarkupStream(getMarkup());
3623        }
3624
3625        /**
3626         * If this Component is a Page, returns self. Otherwise, searches for the nearest Page parent in
3627         * the component hierarchy. If no Page parent can be found, {@code null} is returned.
3628         * 
3629         * @return The Page or {@code null} if none can be found
3630         */
3631        protected final Page findPage()
3632        {
3633                // Search for page
3634                return (Page)(this instanceof Page ? this : findParent(Page.class));
3635        }
3636
3637        /**
3638         * Gets the subset of the currently coupled {@link Behavior}s that are of the provided type as
3639         * an unmodifiable list. Returns an empty list if there are no behaviors coupled to this
3640         * component.
3641         * 
3642         * @param type
3643         *            The type or null for all
3644         * @return The subset of the currently coupled behaviors that are of the provided type as an
3645         *         unmodifiable list
3646         * @param <M>
3647         *            A class derived from Behavior
3648         */
3649        public <M extends Behavior> List<M> getBehaviors(Class<M> type)
3650        {
3651                return Behaviors.getBehaviors(this, type);
3652        }
3653
3654        /**
3655         * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT!
3656         * 
3657         * @param flag
3658         *            The flag to test
3659         * @return True if the flag is set
3660         */
3661        protected final boolean getFlag(final int flag)
3662        {
3663                return (flags & flag) != 0;
3664        }
3665
3666        /**
3667         * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT!
3668         * 
3669         * @param flag
3670         *            The flag to test
3671         * @return True if the flag is set
3672         */
3673        protected final boolean getRequestFlag(final short flag)
3674        {
3675                return (requestFlags & flag) != 0;
3676        }
3677
3678        /**
3679         * Finds the innermost IModel object for an IModel that might contain nested IModel(s).
3680         * 
3681         * @param model
3682         *            The model
3683         * @return The innermost (most nested) model
3684         */
3685        protected final IModel<?> getInnermostModel(final IModel<?> model)
3686        {
3687                IModel<?> nested = model;
3688                while (nested != null && nested instanceof IWrapModel)
3689                {
3690                        final IModel<?> next = ((IWrapModel<?>)nested).getWrappedModel();
3691                        if (nested == next)
3692                        {
3693                                throw new WicketRuntimeException("Model for " + nested + " is self-referential");
3694                        }
3695                        nested = next;
3696                }
3697                return nested;
3698        }
3699
3700        /**
3701         * Gets the component's current model comparator. Implementations can be used for testing the
3702         * current value of the components model data with the new value that is given.
3703         * 
3704         * @return the value defaultModelComparator
3705         */
3706        public IModelComparator getModelComparator()
3707        {
3708                return defaultModelComparator;
3709        }
3710
3711        /**
3712         * Returns whether the component can be stateless. Also the component behaviors must be
3713         * stateless, otherwise the component will be treat as stateful. In order for page to be
3714         * stateless (and not to be stored in session), all components (and component behaviors) must be
3715         * stateless.
3716         * 
3717         * @return whether the component can be stateless
3718         */
3719        protected boolean getStatelessHint()
3720        {
3721                return true;
3722        }
3723
3724        /**
3725         * Called when a null model is about to be retrieved in order to allow a subclass to provide an
3726         * initial model.
3727         * <p>
3728         * By default this implementation looks components in the parent chain owning a
3729         * {@link IComponentInheritedModel} to provide a model for this component via
3730         * {@link IComponentInheritedModel#wrapOnInheritance(Component)}.
3731         * <p>
3732         * For example a {@link FormComponent} has the opportunity to instantiate a model on the fly
3733         * using its {@code id} and the containing {@link Form}'s model, if the form holds a
3734         * {@link CompoundPropertyModel}.
3735         * 
3736         * @return The model
3737         */
3738        protected IModel<?> initModel()
3739        {
3740                IModel<?> foundModel = null;
3741                // Search parents for IComponentInheritedModel (i.e. CompoundPropertyModel)
3742                for (Component current = getParent(); current != null; current = current.getParent())
3743                {
3744                        // Get model
3745                        // Don't call the getModel() that could initialize many in between
3746                        // completely useless models.
3747                        // IModel model = current.getDefaultModel();
3748                        IModel<?> model = current.getModelImpl();
3749
3750                        if (model instanceof IWrapModel && !(model instanceof IComponentInheritedModel))
3751                        {
3752                                model = ((IWrapModel<?>)model).getWrappedModel();
3753                        }
3754
3755                        if (model instanceof IComponentInheritedModel)
3756                        {
3757                                // return the shared inherited
3758                                foundModel = ((IComponentInheritedModel<?>)model).wrapOnInheritance(this);
3759                                setFlag(FLAG_INHERITABLE_MODEL, true);
3760                                break;
3761                        }
3762                }
3763
3764                // No model for this component!
3765                return foundModel;
3766        }
3767
3768        /**
3769         * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT CALL OR OVERRIDE.
3770         * 
3771         * <p>
3772         * Called anytime a model is changed via setModel or setModelObject.
3773         * </p>
3774         */
3775        protected void internalOnModelChanged()
3776        {
3777        }
3778
3779        /**
3780         * Components are allowed to reject behavior modifiers.
3781         * 
3782         * @param behavior
3783         * @return False, if the component should not apply this behavior
3784         */
3785        protected boolean isBehaviorAccepted(final Behavior behavior)
3786        {
3787                // Ignore AttributeModifiers when FLAG_IGNORE_ATTRIBUTE_MODIFIER is set
3788                if ((behavior instanceof AttributeModifier) &&
3789                        (getFlag(FLAG_IGNORE_ATTRIBUTE_MODIFIER) != false))
3790                {
3791                        return false;
3792                }
3793
3794                return behavior.isEnabled(this);
3795        }
3796
3797        /**
3798         * If true, all attribute modifiers will be ignored
3799         * 
3800         * @return True, if attribute modifiers are to be ignored
3801         */
3802        protected final boolean isIgnoreAttributeModifier()
3803        {
3804                return getFlag(FLAG_IGNORE_ATTRIBUTE_MODIFIER);
3805        }
3806
3807        /**
3808         * Called immediately after a component and all its children have been rendered,
3809         * regardless of any exception.
3810         */
3811        protected void onAfterRender()
3812        {
3813                setRequestFlag(RFLAG_AFTER_RENDER_SUPER_CALL_VERIFIED, true);
3814        }
3815
3816        /**
3817         * Called on all visible components before any component is rendered.
3818         * <p>
3819         * <strong>NOTE</strong>: If you override this, you *must* call super.onBeforeRender() within
3820         * your implementation.
3821         * 
3822         * Because this method is responsible for cascading {@link #onBeforeRender()} call to its
3823         * children it is strongly recommended that super call is made at the end of the override.
3824         * </p>
3825         *
3826         * Changes to the component tree can be made only <strong>before</strong> calling
3827         * super.onBeforeRender().
3828         *
3829         * @see org.apache.wicket.MarkupContainer#addOrReplace(Component...) 
3830         */
3831        protected void onBeforeRender()
3832        {
3833                setRequestFlag(RFLAG_PREPARED_FOR_RENDER, true);
3834                onBeforeRenderChildren();
3835                setRequestFlag(RFLAG_BEFORE_RENDER_SUPER_CALL_VERIFIED, true);
3836        }
3837
3838        /**
3839         * Processes the component tag.
3840         * 
3841         * Overrides of this method most likely should call the super implementation.
3842         * 
3843         * @param tag
3844         *            Tag to modify
3845         */
3846        protected void onComponentTag(final ComponentTag tag)
3847        {
3848                // We can't try to get the ID from markup. This could be different than
3849                // id returned from getMarkupId() prior first rendering the component
3850                // (due to transparent resolvers and borders which break the 1:1
3851                // component <-> markup relation)
3852                if (getFlag(FLAG_OUTPUT_MARKUP_ID))
3853                {
3854                        tag.putInternal(MARKUP_ID_ATTR_NAME, getMarkupId());
3855                }
3856
3857                DebugSettings debugSettings = getApplication().getDebugSettings();
3858                String componentPathAttributeName = debugSettings.getComponentPathAttributeName();
3859                if (Strings.isEmpty(componentPathAttributeName) == false)
3860                {
3861                        String path = getPageRelativePath();
3862                        path = path.replace("_", "__");
3863                        path = path.replace(':', '_');
3864                        tag.put(componentPathAttributeName, path);
3865                }
3866
3867                // The markup sourcing strategy may also want to work on the tag
3868                getMarkupSourcingStrategy().onComponentTag(this, tag);
3869        }
3870
3871        /**
3872         * Processes the body.
3873         * 
3874         * @param markupStream
3875         *            The markup stream
3876         * @param openTag
3877         *            The open tag for the body
3878         */
3879        public void onComponentTagBody(final MarkupStream markupStream, final ComponentTag openTag)
3880        {
3881        }
3882
3883        /**
3884         * Called to allow a component to detach resources after use.
3885         * 
3886         * Overrides of this method MUST call the super implementation, the most logical place to do
3887         * this is the last line of the override method.
3888         */
3889        protected void onDetach()
3890        {
3891                setRequestFlag(RFLAG_DETACHING, false);
3892        }
3893
3894        /**
3895         * Called to notify the component it is being removed from the component hierarchy
3896         * 
3897         * Overrides of this method MUST call the super implementation, the most logical place to do
3898         * this is the last line of the override method.
3899         */
3900        protected void onRemove()
3901        {
3902                setRequestFlag(RFLAG_REMOVING_FROM_HIERARCHY, false);
3903        }
3904
3905        /**
3906         * Called anytime a model is changed after the change has occurred
3907         */
3908        protected void onModelChanged()
3909        {
3910        }
3911
3912        /**
3913         * Called anytime a model is changed, but before the change actually occurs
3914         */
3915        protected void onModelChanging()
3916        {
3917        }
3918
3919        /**
3920         * Implementation that renders this component.
3921         */
3922        protected abstract void onRender();
3923
3924        /**
3925         * Writes a simple tag out to the response stream. Any components that might be referenced by
3926         * the tag are ignored. Also undertakes any tag attribute modifications if they have been added
3927         * to the component.
3928         * 
3929         * @param tag
3930         *            The tag to write
3931         */
3932        protected final void renderComponentTag(ComponentTag tag)
3933        {
3934                if (needToRenderTag(tag))
3935                {
3936                        // apply behaviors that are attached to the component tag.
3937                        if (tag.hasBehaviors())
3938                        {
3939                                Iterator<? extends Behavior> tagBehaviors = tag.getBehaviors();
3940                                while (tagBehaviors.hasNext())
3941                                {
3942                                        final Behavior behavior = tagBehaviors.next();
3943                                        if (behavior.isEnabled(this))
3944                                        {
3945                                                behavior.onComponentTag(this, tag);
3946                                        }
3947                                        behavior.detach(this);
3948                                }
3949                        }
3950
3951                        // Apply behavior modifiers
3952                        List<? extends Behavior> behaviors = getBehaviors();
3953                        if ((behaviors != null) && !behaviors.isEmpty() && !tag.isClose() &&
3954                                (isIgnoreAttributeModifier() == false))
3955                        {
3956                                tag = tag.mutable();
3957                                for (Behavior behavior : behaviors)
3958                                {
3959                                        // Components may reject some behavior components
3960                                        if (isBehaviorAccepted(behavior))
3961                                        {
3962                                                behavior.onComponentTag(this, tag);
3963                                        }
3964                                }
3965                        }
3966
3967                        if ((tag instanceof WicketTag) && !tag.isClose() &&
3968                                !getFlag(FLAG_IGNORE_ATTRIBUTE_MODIFIER))
3969                        {
3970                                ExceptionSettings.NotRenderableErrorStrategy notRenderableErrorStrategy = ExceptionSettings.NotRenderableErrorStrategy.LOG_WARNING;
3971                                if (Application.exists())
3972                                {
3973                                        notRenderableErrorStrategy = getApplication().getExceptionSettings().getNotRenderableErrorStrategy();
3974                                }
3975
3976                                String tagName = tag.getNamespace() + ":" + tag.getName();
3977                                String componentId = getId();
3978                                if (getFlag(FLAG_OUTPUT_MARKUP_ID))
3979                                {
3980                                        String message = String.format("Markup id set on a component that is usually not rendered into markup. " +
3981                                                                       "Markup id: %s, component id: %s, component tag: %s.",
3982                                                                       getMarkupId(), componentId, tagName);
3983                                        if (notRenderableErrorStrategy == ExceptionSettings.NotRenderableErrorStrategy.THROW_EXCEPTION)
3984                                        {
3985                                                throw new IllegalStateException(message);
3986                                        }
3987                                        log.warn(message);
3988                                }
3989                                if (getFlag(FLAG_PLACEHOLDER))
3990                                {
3991                                        String message = String.format(
3992                                                        "Placeholder tag set on a component that is usually not rendered into markup. " +
3993                                                        "Component id: %s, component tag: %s.", componentId, tagName);
3994                                        if (notRenderableErrorStrategy == ExceptionSettings.NotRenderableErrorStrategy.THROW_EXCEPTION)
3995                                        {
3996                                                throw new IllegalStateException(message);
3997                                        }
3998                                        log.warn(message);
3999                                }
4000                        }
4001
4002                        // Write the tag
4003                        tag.writeOutput(getResponse(), !needToRenderTag(null),
4004                                getMarkup().getMarkupResourceStream().getWicketNamespace());
4005                }
4006        }
4007
4008        /**
4009         * Replaces the body with the given one.
4010         * 
4011         * @param markupStream
4012         *            The markup stream to replace the tag body in
4013         * @param tag
4014         *            The tag
4015         * @param body
4016         *            The new markup
4017         */
4018        protected final void replaceComponentTagBody(final MarkupStream markupStream,
4019                final ComponentTag tag, final CharSequence body)
4020        {
4021                // The tag might have been changed from open-close to open. Hence
4022                // we'll need what was in the markup itself
4023                ComponentTag markupOpenTag = null;
4024
4025                // If tag has a body
4026                if (tag.isOpen())
4027                {
4028                        // Get what tag was in the markup; not what the user it might
4029                        // have changed it to.
4030                        markupOpenTag = markupStream.getPreviousTag();
4031
4032                        // If it was an open tag in the markup as well, than ...
4033                        if (markupOpenTag.isOpen())
4034                        {
4035                                // skip any raw markup in the body
4036                                markupStream.skipRawMarkup();
4037                        }
4038                }
4039
4040                if (body != null)
4041                {
4042                        // Write the new body
4043                        getResponse().write(body);
4044                }
4045
4046                // If we had an open tag (and not an openclose tag) and we found a
4047                // close tag, we're good
4048                if (tag.isOpen())
4049                {
4050                        // If it was an open tag in the markup, than there must be
4051                        // a close tag as well.
4052                        if ((markupOpenTag != null) && markupOpenTag.isOpen() && !markupStream.atCloseTag())
4053                        {
4054                                // There must be a component in this discarded body
4055                                markupStream.throwMarkupException("Expected close tag for '" + markupOpenTag +
4056                                        "' Possible attempt to embed component(s) '" + markupStream.get() +
4057                                        "' in the body of this component which discards its body");
4058                        }
4059                }
4060        }
4061
4062        /**
4063         * @param auto
4064         *            True to put component into auto-add mode
4065         */
4066        protected final Component setAuto(final boolean auto)
4067        {
4068                setFlag(FLAG_AUTO, auto);
4069                return this;
4070        }
4071
4072        /**
4073         * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT!
4074         * 
4075         * @param flag
4076         *            The flag to set
4077         * @param set
4078         *            True to turn the flag on, false to turn it off
4079         */
4080        protected final Component setFlag(final int flag, final boolean set)
4081        {
4082                if (set)
4083                {
4084                        flags |= flag;
4085                }
4086                else
4087                {
4088                        flags &= ~flag;
4089                }
4090                return this;
4091        }
4092
4093        /**
4094         * @param flag
4095         *            The flag to set
4096         * @param set
4097         *            True to turn the flag on, false to turn it off
4098         */
4099        final Component setRequestFlag(final short flag, final boolean set)
4100        {
4101                if (set)
4102                {
4103                        requestFlags |= flag;
4104                }
4105                else
4106                {
4107                        requestFlags &= ~flag;
4108                }
4109                return this;
4110        }
4111
4112        /**
4113         * If true, all attribute modifiers will be ignored
4114         * 
4115         * @param ignore
4116         *            If true, all attribute modifiers will be ignored
4117         * @return This
4118         */
4119        protected final Component setIgnoreAttributeModifier(final boolean ignore)
4120        {
4121                setFlag(FLAG_IGNORE_ATTRIBUTE_MODIFIER, ignore);
4122                return this;
4123        }
4124
4125        /**
4126         * @param <V>
4127         *            The model type
4128         * @param model
4129         *            The model to wrap if need be
4130         * @return The wrapped model
4131         */
4132        protected final <V> IModel<V> wrap(final IModel<V> model)
4133        {
4134                if (model instanceof IComponentAssignedModel)
4135                {
4136                        return ((IComponentAssignedModel<V>)model).wrapOnAssignment(this);
4137                }
4138                return model;
4139        }
4140
4141        /**
4142         * Detaches any child components
4143         */
4144        void detachChildren()
4145        {
4146        }
4147
4148        /**
4149         * Signals this components removal from hierarchy to all its children.
4150         */
4151        void removeChildren()
4152        {
4153        }
4154
4155        /**
4156         * Gets the component at the given path.
4157         * 
4158         * @param path
4159         *            Path to component
4160         * @return The component at the path
4161         */
4162        @Override
4163        public Component get(final String path)
4164        {
4165                // Path to this component is an empty path
4166                if (path.length() == 0)
4167                {
4168                        return this;
4169                }
4170                throw new IllegalArgumentException(
4171                        exceptionMessage("Component is not a container and so does not contain the path " +
4172                                path));
4173        }
4174
4175        /**
4176         * @param setRenderingFlag
4177         *            rendering flag
4178         */
4179        void internalMarkRendering(boolean setRenderingFlag)
4180        {
4181                // WICKET-5460 no longer prepared for render
4182                setRequestFlag(RFLAG_PREPARED_FOR_RENDER, false);
4183
4184                setRequestFlag(RFLAG_RENDERING, setRenderingFlag);
4185        }
4186
4187        /**
4188         * @return True if this component or any of its parents is in auto-add mode
4189         */
4190        public final boolean isAuto()
4191        {
4192                // Search up hierarchy for FLAG_AUTO
4193                for (Component current = this; current != null; current = current.getParent())
4194                {
4195                        if (current.getFlag(FLAG_AUTO))
4196                        {
4197                                return true;
4198                        }
4199                }
4200                return false;
4201        }
4202
4203        /**
4204         * 
4205         * @return <code>true</code> if component has been prepared for render
4206         */
4207        boolean isPreparedForRender()
4208        {
4209                return getRequestFlag(RFLAG_PREPARED_FOR_RENDER);
4210        }
4211
4212        /**
4213         * This method is here for {@link MarkupContainer}. It is broken out of
4214         * {@link #onBeforeRender()} so we can guarantee that it executes as the last in
4215         * onBeforeRender() chain no matter where user places the <code>super.onBeforeRender()</code>
4216         * call.
4217         */
4218        void onBeforeRenderChildren()
4219        {
4220        }
4221
4222        /**
4223         * Renders the close tag at the current position in the markup stream.
4224         * 
4225         * @param markupStream
4226         *            the markup stream
4227         * @param openTag
4228         *            the tag to render
4229         * @param renderBodyOnly
4230         *            if true, the tag will not be written to the output
4231         */
4232        final void renderClosingComponentTag(final MarkupStream markupStream,
4233                final ComponentTag openTag, final boolean renderBodyOnly)
4234        {
4235                // Tag should be open tag and not openclose tag
4236                if (openTag.isOpen())
4237                {
4238                        // If we found a close tag and it closes the open tag, we're good
4239                        if (markupStream.atCloseTag() && markupStream.getTag().closes(openTag))
4240                        {
4241                                // Render the close tag
4242                                if ((renderBodyOnly == false) && needToRenderTag(openTag))
4243                                {
4244                                        openTag.writeSyntheticCloseTag(getResponse());
4245                                }
4246                        }
4247                        else if (openTag.requiresCloseTag())
4248                        {
4249                                // Missing close tag. Some tags, e.g. <p> are handled like <p/> by most browsers and
4250                                // thus will not throw an exception.
4251                                markupStream.throwMarkupException("Expected close tag for " + openTag);
4252                        }
4253                }
4254        }
4255
4256        /**
4257         * Sets the id of this component.
4258         * 
4259         * @param id
4260         *            The non-null id of this component
4261         */
4262        private void checkId(final String id)
4263        {
4264                if (!(this instanceof Page))
4265                {
4266                        if (Strings.isEmpty(id))
4267                        {
4268                                throw new WicketRuntimeException("Null or empty component ID's are not allowed.");
4269                        }
4270                }
4271
4272                if ((id != null) && (id.indexOf(':') != -1 || id.indexOf('~') != -1))
4273                {
4274                        throw new WicketRuntimeException("The component ID must not contain ':' or '~' chars.");
4275                }
4276        }
4277
4278        /**
4279         * THIS IS A WICKET INTERNAL API. DO NOT USE IT.
4280         * 
4281         * Sets the parent of a component. Typically what you really want is parent.add(child).
4282         * <p/>
4283         * Note that calling setParent() and not parent.add() will connect the child to the parent, but
4284         * the parent will not know the child. This might not be a problem in some cases, but e.g.
4285         * child.onDetach() will not be invoked (since the parent doesn't know it is his child).
4286         * 
4287         * @param parent
4288         *            The parent container
4289         */
4290        public final void setParent(final MarkupContainer parent)
4291        {
4292                if (this.parent != null && log.isDebugEnabled())
4293                {
4294                        log.debug("Replacing parent " + this.parent + " with " + parent);
4295                }
4296                this.parent = parent;
4297        }
4298
4299        /**
4300         * Sets the render allowed flag.
4301         * 
4302         * @param renderAllowed
4303         */
4304        final void setRenderAllowed(boolean renderAllowed)
4305        {
4306                setFlag(FLAG_IS_RENDER_ALLOWED, renderAllowed);
4307        }
4308
4309        /**
4310         * Sets the render allowed flag.
4311         * 
4312         * Visit all this page's children (overridden in MarkupContainer) to check rendering
4313         * authorization, as appropriate. We set any result; positive or negative as a temporary boolean
4314         * in the components, and when a authorization exception is thrown it will block the rendering
4315         * of this page
4316         */
4317        void setRenderAllowed()
4318        {
4319                setRenderAllowed(isActionAuthorized(RENDER));
4320        }
4321
4322        /**
4323         * Sets whether or not this component is allowed to be visible. This method is meant to be used
4324         * by components to control visibility of other components. A call to
4325         * {@link #setVisible(boolean)} will not always have a desired effect because that component may
4326         * have {@link #isVisible()} overridden. Both {@link #setVisibilityAllowed(boolean)} and
4327         * {@link #isVisibilityAllowed()} are <code>final</code> so their contract is enforced always.
4328         * 
4329         * @param allowed
4330         * @return <code>this</code> for chaining
4331         */
4332        public final Component setVisibilityAllowed(boolean allowed)
4333        {
4334                if (allowed != getFlag(FLAG_VISIBILITY_ALLOWED))
4335                {
4336                        setFlag(FLAG_VISIBILITY_ALLOWED, allowed);
4337                        onVisibleStateChanged();
4338                }
4339                return this;
4340        }
4341
4342        /**
4343         * Gets whether or not visibility is allowed on this component. See
4344         * {@link #setVisibilityAllowed(boolean)} for details.
4345         * 
4346         * @return true if this component is allowed to be visible, false otherwise.
4347         */
4348        public final boolean isVisibilityAllowed()
4349        {
4350                return getFlag(FLAG_VISIBILITY_ALLOWED);
4351        }
4352
4353        /**
4354         * Determines whether or not a component should be visible, taking into account all the factors:
4355         * {@link #isVisible()}, {@link #isVisibilityAllowed()}, {@link #isRenderAllowed()}
4356         * 
4357         * @return <code>true</code> if the component should be visible, <code>false</code> otherwise
4358         */
4359        public final boolean determineVisibility()
4360        {
4361                return isVisible() && isRenderAllowed() && isVisibilityAllowed();
4362        }
4363
4364
4365        /**
4366         * Calculates enabled state of the component taking its hierarchy into account. A component is
4367         * enabled iff it is itself enabled ({@link #isEnabled()} and {@link #isEnableAllowed()} both
4368         * return <code>true</code>), and all of its parents are enabled.
4369         * 
4370         * @return <code>true</code> if this component is enabled</code>
4371         */
4372        public boolean isEnabledInHierarchy()
4373        {
4374                if (getRequestFlag(RFLAG_ENABLED_IN_HIERARCHY_SET))
4375                {
4376                        return getRequestFlag(RFLAG_ENABLED_IN_HIERARCHY_VALUE);
4377                }
4378
4379                final boolean state;
4380                Component parent = getParent();
4381                if (parent != null && !parent.isEnabledInHierarchy())
4382                {
4383                        state = false;
4384                }
4385                else
4386                {
4387                        state = isEnabled() && isEnableAllowed();
4388                }
4389
4390                setRequestFlag(RFLAG_ENABLED_IN_HIERARCHY_SET, true);
4391                setRequestFlag(RFLAG_ENABLED_IN_HIERARCHY_VALUE, state);
4392                return state;
4393        }
4394        
4395        /**
4396         * Says if the component is rendering currently.
4397         * 
4398         * @return true if this component is rendering, false otherwise.
4399         */
4400        public final boolean isRendering()
4401        {
4402                return getRequestFlag(RFLAG_PREPARED_FOR_RENDER) || getRequestFlag(RFLAG_RENDERING);
4403        }
4404
4405        /**
4406         * Checks whether or not an {@link IRequestListener} can be invoked on this component. Usually components
4407         * deny these invocations if they are either invisible or disabled in hierarchy.
4408         * <p>
4409         * WARNING: be careful when overriding this method because it may open security holes - such as
4410         * allowing a user to click on a link that should be disabled.
4411         * </p>
4412         * <p>
4413         * Example usecase for overriding: Suppose you are building an component that displays images.
4414         * The component generates a callback to itself using {@link IRequestListener} interface and
4415         * uses this callback to stream image data. If such a component is placed inside a disabled
4416         * {@code WebMarkupContainer} we still want to allow the invocation of the request listener callback
4417         * method so that image data can be streamed. Such a component would override this method and
4418         * return {@literal true}.
4419         * </p>
4420         * 
4421         * @return {@literal true} iff the listener method can be invoked on this component
4422         */
4423        public boolean canCallListener()
4424        {
4425                return isEnabledInHierarchy() && isVisibleInHierarchy();
4426        }
4427
4428        /**
4429         * Render to the web response whatever the component wants to contribute to the head section.
4430         * 
4431         * @param response
4432         *            Response object
4433         */
4434        @Override
4435        public void renderHead(IHeaderResponse response)
4436        {
4437                // noop
4438        }
4439
4440        /** {@inheritDoc} */
4441        @Override
4442        public void onEvent(IEvent<?> event)
4443        {
4444        }
4445
4446        /** {@inheritDoc} */
4447        @Override
4448        public final <T> void send(IEventSink sink, Broadcast type, T payload)
4449        {
4450                // if there are no event dispatchers then don't even try to send event
4451                if (getApplication().getFrameworkSettings().hasAnyEventDispatchers())
4452                {
4453                        new ComponentEventSender(this, getApplication().getFrameworkSettings()).send(sink, type,
4454                                        payload);
4455                }
4456        }
4457
4458        /**
4459         * Removes behavior from component
4460         * 
4461         * @param behaviors
4462         *            behaviors to remove
4463         * 
4464         * @return this (to allow method call chaining)
4465         */
4466        public Component remove(final Behavior... behaviors)
4467        {
4468                for (Behavior behavior : behaviors)
4469                {
4470                        Behaviors.remove(this, behavior);
4471                }
4472                return this;
4473        }
4474
4475        /** {@inheritDoc} */
4476        @Override
4477        public final Behavior getBehaviorById(int id)
4478        {
4479                return Behaviors.getBehaviorById(this, id);
4480        }
4481
4482        /** {@inheritDoc} */
4483        @Override
4484        public final int getBehaviorId(Behavior behavior)
4485        {
4486                if (behavior.isTemporary(this))
4487                {
4488                        throw new IllegalArgumentException(
4489                                "Cannot get a stable id for temporary behavior " + behavior);
4490                }
4491                return Behaviors.getBehaviorId(this, behavior);
4492        }
4493
4494        /**
4495         * Adds a behavior modifier to the component.
4496         * 
4497         * @param behaviors
4498         *            The behavior modifier(s) to be added
4499         * @return this (to allow method call chaining)
4500         */
4501        public Component add(final Behavior... behaviors)
4502        {
4503                Behaviors.add(this, behaviors);
4504                return this;
4505        }
4506
4507        /**
4508         * Gets the currently coupled {@link Behavior}s as an unmodifiable list. Returns an empty list
4509         * rather than null if there are no behaviors coupled to this component.
4510         * 
4511         * @return The currently coupled behaviors as an unmodifiable list
4512         */
4513        public final List<? extends Behavior> getBehaviors()
4514        {
4515                return getBehaviors(null);
4516        }
4517
4518        @Override
4519        public boolean canCallListenerAfterExpiry()
4520        {
4521                return getApplication().getPageSettings()
4522                        .getCallListenerAfterExpiry() || isStateless();
4523        }
4524        /**
4525         * This method is called whenever a component is re-added to the page's component tree, if it
4526         * had been removed at some earlier time, i.e., if it is already initialized
4527         * (see {@link org.apache.wicket.Component#isInitialized()}).
4528         *
4529         * This is similar to onInitialize, but only comes after the component has been removed and
4530         * then added again:
4531         *
4532         * <ul>
4533         * <li>onInitialize is only called the very first time a component is added</li>
4534         * <li>onReAdd is not called the first time, but every time it is re-added after having been
4535         * removed</li>
4536         * </ul>
4537         *
4538         * You can think of it as the opposite of onRemove. A component that was once removed will
4539         * not be re-initialized but only re-added.
4540         *
4541         * Subclasses that override this must call super.onReAdd().
4542         */
4543        protected void onReAdd()
4544        {
4545                setRequestFlag(RFLAG_ON_RE_ADD_SUPER_CALL_VERIFIED, true);
4546        }
4547}