All Downloads are FREE. Search and download functionalities are using the official Maven repository.

javax.faces.view.ViewDeclarationLanguage Maven / Gradle / Ivy

The newest version!
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-2016 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */

package javax.faces.view;

import static javax.faces.application.ResourceVisitOption.TOP_LEVEL_VIEWS_ONLY;

import java.beans.BeanInfo;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

import javax.faces.application.Resource;
import javax.faces.application.ViewVisitOption;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;

/**
 * 

The contract that a view declaration * language must implement to interact with the JSF runtime. An * implementation of this class must be thread-safe.

* *
* *

Instances of this class are application scoped and must be * obtained from the {@link ViewDeclarationLanguageFactory}.

*
* * @since 2.0 * */ public abstract class ViewDeclarationLanguage { /** *

Identifier for the JSP view declaration * language.

* * @since 2.1 */ public final static String JSP_VIEW_DECLARATION_LANGUAGE_ID = "java.faces.JSP"; /** *

Identifier for the Facelets view * declaration language.

* * @since 2.1 */ public final static String FACELETS_VIEW_DECLARATION_LANGUAGE_ID = "java.faces.Facelets"; /** *

Restore a UIViewRoot * from a previously created view. See section JSF.7.7.2 for the * specification of the default implementation.

* * @param context the FacesContext for this request. * @param viewId the identifier for a previously rendered view. * * @throws NullPointerException if any of the arguments are * null * * @return the restored view */ public abstract UIViewRoot restoreView(FacesContext context, String viewId); /** *

Return a reference to the view * metadata for the view represented by the argument * viewId, or null if the metadata cannot * be found. See section JSF.7.7.2 for the specification of the * default implementation. Facelets for JSF 2 implementation must * return non-null. JSP implementations must return * null.

* * @param context The FacesContext for this request. * @param viewId the view id from whith to extract the metadata * @since 2.0 * * @throws NullPointerException if any of the arguments are * null. * * @throws javax.faces.FacesException if there is an error in * obtaining the metadata * * @return the view metadata */ public abstract ViewMetadata getViewMetadata(FacesContext context, String viewId); /** *

Create * a UIViewRoot from the VDL contained in the artifact referenced by the argument * viewId. See section JSF.7.7.2 for the specification of * the default implementation.

* * @param context the FacesContext for this request. * @param viewId the identifier of an artifact that contains the VDL * syntax that describes this view. * * @throws NullPointerException if any of the arguments are * null * * @since 2.0 * * @return the newly created view root */ public abstract UIViewRoot createView(FacesContext context, String viewId); /** *

Take any actions specific to * this VDL implementation to cause the argument * UIViewRoot which must have been created via a call * to {@link #createView}, to be populated with children.

*
*

The Facelets implementation must insure that markup comprising * the view must be executed, with the {@link * javax.faces.component.UIComponent} instances in the view being * encountered in the same depth-first order as in other lifecycle * methods defined on UIComponent, and added to the * view (but not rendered) during the traversal. The runtime must * guarantee that the view must be fully populated before any of the * following happen.

*
    * *
  • The {@link javax.faces.event.PhaseListener#afterPhase} * method of any PhaseListeners attached to the * application is called

  • *
  • The {@link javax.faces.component.UIViewRoot} phase * listener installed via {@link * javax.faces.component.UIViewRoot#setAfterPhaseListener} or {@link * javax.faces.component.UIViewRoot#addPhaseListener} are called.

  • * *
*

If the root is * already populated with children, the view must still be re-built, * but care must be taken to ensure that the existing components are * correctly paired up with their VDL counterparts in the VDL page. * Also, any system events that would normally be generated during * the adding or removing of components from the view must be * temporarily disabled during the creation of the view and then * re-enabled when the view has been built.

*
* * @param context the FacesContext for this request * @param root the UIViewRoot to populate with children * using techniques specific to this VDL implementation. * * @throws IOException if view cannot be built for any reason */ public abstract void buildView(FacesContext context, UIViewRoot root) throws IOException; /** *

Render a view rooted at * argumentview. See section JSF.7.7.2 for the * specification of the default implementation.

* * @param context the FacesContext for this request. * @param view the UIViewRoot from an early call to * {@link #createView} or {@link #restoreView}. * * @throws NullPointerException if any of the arguments are * null * * @throws IOException if the view cannot be rendered for any reason */ public abstract void renderView(FacesContext context, UIViewRoot view) throws IOException; /** *

Return a reference to the component * metadata for the composite component represented by the argument * componentResource, or null if the * metadata cannot be found. See section JSF.7.7.2 for the * specification of the default implementation. JSP implementations * must throw UnsupportedOperationException.

* * @param context The FacesContext for this request. * @param componentResource The Resource that represents the component. * @since 2.0 * * @throws NullPointerException if any of the arguments are * null. * * @throws javax.faces.FacesException if there is an error in * obtaining the metadata * * @throws UnsupportedOperationException if this is a JSP VDL * implementation. * * @return the component metadata */ public abstract BeanInfo getComponentMetadata(FacesContext context, Resource componentResource); /** *

Take implementation specific action * to discover a Resource given the argument * componentResource. See section JSF.7.7.2 for the * specification of the default implementation. JSP implementations * must throw UnsupportedOperationException.

* * @param context The FacesContext for this request. * @param componentResource The Resource that represents the component. * @since 2.0 * * @throws NullPointerException if any of the arguments are * null. * * @throws javax.faces.FacesException if there is an error in * obtaining the script component resource * @throws UnsupportedOperationException if this is a JSP VDL * implementation. * * @return the {@link Resource} corresponding to the argument {@code * componentResource} */ public abstract Resource getScriptComponentResource(FacesContext context, Resource componentResource); /** *

Create a component given a * {@link ViewDeclarationLanguage} specific * tag library URI and tag name. The runtime must support this method operating * for the Facelets VDL. * Other kinds of {@code ViewDeclarationLanguage} may be supported but are not * required to be supported. For backward compatibility * with decorated {@code ViewDeclrationLanguage} implementations that do * not override this method, a default implementation is provided that returns * {@code null}. However, any implementation that is compliant with the * version of the specification in which this method was introduced must * implement this method. *

* * @param context the {@link FacesContext} for this request * @param taglibURI the fully qualified tag library URI that contains the component * @param tagName the name of the tag within that library that exposes the component * @param attributes any name=value pairs that would otherwise have been * given on the markup that would cause the creation of this component or * {@code null} if no attributes need be given. * * @throws NullPointerException if {@code context}, {@code taglibURI}, or * {@code tagName} are {@code null} * * @since 2.2 * * @return the newly created component */ public UIComponent createComponent(FacesContext context, String taglibURI, String tagName, Map attributes) { return null; } /** *

Assuming the component * metadata for argument topLevelComponent has been * made available by an earlier call to {@link * ViewDeclarationLanguage#getComponentMetadata}, leverage the * component metadata for the purpose of re-targeting attached * objects from the top level composite component to the individual * {@link AttachedObjectTarget} instances inside the composite * component. This method must be called by the {@link * ViewDeclarationLanguage} implementation when creating the * UIComponent tree when a composite component usage is * encountered.

* *
* *

An algorithm semantically equivalent to the following must be * implemented.

* *
    * *
  • Obtain the metadata for the composite component. *Currently this entails getting the value of the {@link *UIComponent#BEANINFO_KEY} component attribute, which will be *an instance of BeanInfo. If the metadata cannot *be found, log an error message and return.

  • * *
  • Get the BeanDescriptor from the *BeanInfo.

  • * *
  • Get the value of the {@link *AttachedObjectTarget#ATTACHED_OBJECT_TARGETS_KEY} from the *BeanDescriptor's getValue() method. *This will be a List<{@link *AttachedObjectTarget}>. Let this be *targetList.

  • * *
  • For each curHandler entry in the argument *handlers

    * *
      * *
    • Let forAttributeValue be the return from *{@link AttachedObjectHandler#getFor}.

    • * *
    • For each curTarget entry in *targetList, the first of the following items that *causes a match will take this action:

      * *

      For each UIComponent in the *list returned from curTarget.getTargets(), call *curHandler.applyAttachedObject(), *passing the FacesContext and the *UIComponent.

      * *

      and cause this inner loop to terminate.

      * *
        * *
      • If curHandler is an instance of {@link *ActionSource2AttachedObjectHandler} and curTarget is an *instance of {@link ActionSource2AttachedObjectTarget}, and *curTarget.getName() is equal to curTargetName, *consider it a match.

      • * *
      • If curHandler is an instance of {@link *EditableValueHolderAttachedObjectHandler} and curTarget *is an instance of {@link EditableValueHolderAttachedObjectTarget}, *and *curTarget.getName() is equal to curTargetName, *consider it a match.

      • * *
      • If curHandler *is an instance of {@link ValueHolderAttachedObjectHandler} and *curTarget is an instance of {@link *ValueHolderAttachedObjectTarget}, and curTarget.getName() *is equal to curTargetName, consider it a match.

      • * *
      • If curHandler is an instance of {@link *BehaviorHolderAttachedObjectHandler} and curTarget is an *instance of {@link BehaviorHolderAttachedObjectTarget}, and either *of the following conditions are true,

        * *
          * *
        • curHandler.getEventName() is not null * and is equal to curTargetName.
        • * *
        • curHandler.getEventName() is null and * curTarget.isDefaultEvent() is true.
        • * *
        * *

        consider it a match.

      • * *
      *
    • *
    *
  • *
* *

The implementation must * support retargeting attached objects from the top level compsite * component to targets that are composite and non-composite * components.

* *

An implementation is provided that will throw * UnsupportedOperationException. A Faces implementation * compliant with version 2.0 and beyond of the specification must * override this method.

* *
* * @param context the FacesContext for this request. * * @param topLevelComponent The UIComponent in the view to which the * attached objects must be attached. This UIComponent must have * its component metadata already associated and available from via * the JavaBeans API. * * @param handlers the tag handlers for the attached objects * * @throws NullPointerException if any of the arguments are * null. * * @since 2.0 */ public void retargetAttachedObjects(FacesContext context, UIComponent topLevelComponent, List handlers) { // no-op } /** *

Assuming the component metadata for * argument topLevelComponent has been made available * by an earlier call to {@link * ViewDeclarationLanguage#getComponentMetadata}, leverage the * component metadata for the purpose of re-targeting any method * expressions from the top level component to the appropriate inner * component. For each attribute that is a * MethodExpression (as indicated by the presence of a * "method-signature" attribute and the absence of a * "type" attribute), the following action must be * taken:

* *
* *
    * *
  • Get the value of the targets attribute. If the * value is a ValueExpression evaluate it. If there is * no targets attribute, let the name of the metadata * element be the evaluated value of the targets * attribute.

  • * *
  • Interpret targets as a space (not tab) separated * list of ids. For each entry in the list:

    * *
      * *
    • Find the inner component of the * topLevelComponent with the id equal to * the current list entry. For discussion, this component is called * target. If not found, log and error and continue to * the next attribute.

    • * *
    • For discussion the declared name of the attribute is * called name.

    • * *
    • In the attributes map of the * topLevelComponent, look up the entry under the key * name. Assume the result is a * ValueExpression. For discussion, this is * attributeValueExpression. If not found, log an error * and continue to the next attribute.

    • * *
    • If name is equal to the string "action", or * "actionListener" without the quotes, assume target is * an {@link javax.faces.component.ActionSource2}.

    • * *
    • If name is equal to the string "validator", or * "valueChangeListener" without the quotes, assume * target is an {@link * javax.faces.component.EditableValueHolder}.

    • * *
    • Call getExpressionString() on the * attributeValueExpression and use that string to * create a MethodExpression of the appropriate * signature for name.

    • * *
    • If name is not equal to any of the previously * listed strings, call getExpressionString() on the * attributeValueExpression and use that string to * create a MethodExpression where the signature is * created based on the value of the * "method-signature" attribute of the * <composite:attribute /> tag.

    • * *
    • Let the resultant MethodExpression be * called attributeMethodExpression for discussion. *

    • * *
    • If name is equal to the string "action" * without the quotes, call {@link * javax.faces.component.ActionSource2#setActionExpression} on * target, passing attributeMethodExpression.

    • * *
    • If name is equal to the string * "actionListener" without the quotes, call {@link * javax.faces.component.ActionSource#addActionListener} on * target, passing attributeMethodExpression * wrapped in a {@link javax.faces.event.MethodExpressionActionListener}.

    • * *
    • If name is equal to the string * "validator" without the quotes, call {@link * javax.faces.component.EditableValueHolder#addValidator} on target, * passing attributeMethodExpression wrapped in a {@link * javax.faces.validator.MethodExpressionValidator}.

    • * *
    • If name is equal to the string * "valueChangeListener" without the quotes, call {@link * javax.faces.component.EditableValueHolder#addValueChangeListener} on * target, passing attributeMethodExpression wrapped in a * {@link javax.faces.event.MethodExpressionValueChangeListener}.

    • * *
    • Otherwise, assume that the MethodExpression * should be placed in the components attribute set. The runtme * must create the MethodExpression instance based on * the value of the "method-signature" * attribute.

    • *
    * *
  • * *
* *

An implementation is provided that will throw * UnsupportedOperationException. A Faces implementation * compliant with version 2.0 and beyond of the specification must * override this method.

* *
* * @param context the FacesContext for this request. * * @param topLevelComponent The UIComponent in the view to which the * attached objects must be attached. This UIComponent must have * its component metadata already associated and available from via * the JavaBeans API. * * @throws NullPointerException if context * or topLevelComponent is null. * * @since 2.0 */ public void retargetMethodExpressions(FacesContext context, UIComponent topLevelComponent) { // no-op } /** *

Return the list of resource library * contracts that will be made available for use in the view * specified by the argument {@code viewId}. If no match is found, * return an empty list. See section JSF.7.7.2 for the * specification of the default implementation. For backward * compatibility with prior implementations, an implementation is * provided that returns {@code null}, but any implementation * compliant with the version of the specification in which this * method was introduced must implement it as specified in * JSF.7.7.2.

* * @param context the {@code FacesContext} for this request * @param viewId the view id for which the applicable resource library * contracts should be calculated. * * @since 2.2 * * @return the calculated list of resource library contract names */ public List calculateResourceLibraryContracts(FacesContext context, String viewId) { return null; } /** *

For implementations that want to * control the implementation of state saving and restoring, the * {@link StateManagementStrategy} allows them to do so. Returning * null indicates that the implementation wishes the * runtime to handle the state saving and restoring. * Implementations that provide the VDL for Facelets for JSF 2.0 and * later must return non-null from this method.

* * @param context the {@code FacesContext} for the current request. * * @param viewId the view id. * * @return the strategy as specified above * * @since 2.0 */ public abstract StateManagementStrategy getStateManagementStrategy(FacesContext context, String viewId); /** *

Tests * whether a physical resource * corresponding to the specified viewId exists.

* *

The default implementation uses * {@link javax.faces.application.ResourceHandler#createViewResource} * to locate the physical resource.

* * @param context The FacesContext for this request. * @param viewId the view id to test * * @return the result as specified above * * @since 2.1 */ public boolean viewExists(FacesContext context, String viewId) { return context.getApplication().getResourceHandler().createViewResource(context, viewId) != null; } /** *

* Return a {@code Stream} possibly lazily populated by walking the view tree * rooted at a given initial path. The view tree is traversed breadth-first, * the elements in the stream are logical view ids. *

* *

* This method works as if invoking it were equivalent to evaluating the expression: *

     * getViewResources(facesContext, start, Integer.MAX_VALUE, options)
     * 
* Put differently, it visits all levels of the resource tree. * * @param facesContext The {@link FacesContext} for this request. * @param path The initial path from which to start looking for views * @param options The options to influence the traversal. See {@link ViewVisitOption} for details on those. * * @return the {@link Stream} of view ids * * @since 2.3 */ public Stream getViews(FacesContext facesContext, String path, ViewVisitOption... options) { return facesContext.getApplication().getResourceHandler().getViewResources(facesContext, path, TOP_LEVEL_VIEWS_ONLY); } /** *

* Return a {@code Stream} possibly lazily populated by walking the view tree * rooted at a given initial path. The view tree is traversed breadth-first, * the elements in the stream are logical view ids. *

* *

* The {@code maxDepth} parameter is the maximum depth of directory levels to visit * beyond the initial path, which is always visited. The value is relative to the root * ({@code /}), not to the given initial path. E.g. given {@code maxDepth} = {@code 3} and initial * path {@code /foo/}, visiting will proceed up to {@code /foo/bar/}, where {@code /} counts as depth * {@code 1}, {@code /foo/} as depth {@code 2} and {@code /foo/bar/} as depth {@code 3}. * A value lower or equal to the depth of the initial path means that only the initial path * is visited. A value of {@link Integer#MAX_VALUE MAX_VALUE} may be used to indicate that all * levels should be visited. * * @param facesContext The {@link FacesContext} for this request. * @param path The initial path from which to start looking for views * @param maxDepth The absolute maximum depth of nested directories to visit counted from the root ({@code /}). * @param options The options to influence the traversal. See {@link ViewVisitOption} for details on those. * * @return the {@link Stream} of view ids * * @since 2.3 */ public Stream getViews(FacesContext facesContext, String path, int maxDepth, ViewVisitOption... options) { return facesContext.getApplication().getResourceHandler().getViewResources(facesContext, path, maxDepth, TOP_LEVEL_VIEWS_ONLY); } /** *

Returns a non-null String that can be * used to identify this view declaration language.

* *

The default implementation returns the fully qualified class name * of the view declaration language implementation. Subclasses may * override to provide a more meaningful id.

* * @return the id of this view declaration language * * @since 2.1 */ public String getId() { return getClass().getName(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy