Package org.apache.shale.validator.faces

Source Code of org.apache.shale.validator.faces.ValidatorInputRenderer

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.apache.shale.validator.faces;

import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import javax.faces.component.EditableValueHolder;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.ConverterException;
import javax.faces.render.Renderer;
import javax.faces.validator.Validator;
import org.apache.shale.util.Tags;
import org.apache.shale.validator.CommonsValidator;


/**
* <p>This renderer is a hybrid renderer decorator that is dynamically
* registered by the {@link ValidatorRenderKit}
* for component renderers in the "javax.faces.Input" family.</p>
*/
public class ValidatorInputRenderer extends Renderer {


    /**
     * <p>The Renderer that we are wrapping.</p>
     */
    private Renderer defaultRenderer = null;


    /**
     * <p>This constant is the name of a reserved attribute that will hold
     * a <code>Map</code> of clientId's for the component.</p>
     */
    public static final String VALIDATOR_CLIENTIDS_ATTR = "org.apache.shale.validator.clientIdSet";


    /**
     * <p>Overloaded constructor is passed the original
     * <code>Renderer</code>.</p>
     *
     * @param defaultRenderer The Renderer we should wrap
     */
    public ValidatorInputRenderer(Renderer defaultRenderer) {
       this.defaultRenderer = defaultRenderer;
    }


    /** {@inheritDoc} */
    public String convertClientId(FacesContext context, String id) {
        return defaultRenderer.convertClientId(context, id);
    }


    /** {@inheritDoc} */
    public void decode(FacesContext context, UIComponent component) {
        defaultRenderer.decode(context, component);
    }


    /**
     * <p>This override captures the clientId of the target component before
     * passing on to the original renderer.  The clientId is added to a Map
     * that is used by the {@link org.apache.shale.component.ValidatorScript}
     * component for adding client side JavaScript validation.  This hook is
     * needed when the {@link org.apache.shale.validator.CommonsValidator}
     * is added to a UIData subclass.  The components in this class are not
     * unique per row so the clientId can only be captured during the rendering
     * process.  The Map also contains a snapshot of validator var arguments
     * that contain value binding expressions.  This snapshot of state at
     * renderering is used by the client side JavaScript.  The snapshot
     * allows client side validation in UIData components.</p>
     *
     * @param context FacesContext for the current request
     * @param component UIComponent being rendered
     *
     * @exception IOException if an input/output error occurs
     */
    public void encodeBegin(FacesContext context, UIComponent component) throws IOException {

        if (component instanceof EditableValueHolder && component.isRendered()) {

                Tags tagUtils = new Tags();

                EditableValueHolder editableComponent = (EditableValueHolder) component;

                // A map that captures information about a component that might contain
                // commons validators.  The map is organized by a hierarchy "clientId/validatorType/vars"
                Map ids = (Map) component.getAttributes().get(VALIDATOR_CLIENTIDS_ATTR);
                if (ids == null) {
                    ids = new TreeMap();
                    component.getAttributes().put(VALIDATOR_CLIENTIDS_ATTR, ids);
                }

                // captrue the clientId before renderering
                String clientId = component.getClientId(context);
                Map validatorVars = (Map) ids.get(clientId);
                if (validatorVars == null) {
                    validatorVars = new TreeMap();
                    ids.put(clientId, validatorVars);
                }


                Validator[] validators = editableComponent.getValidators();
                // look for components using CommonsValidator
                for (int i = 0; i < validators.length; i++) {
                    if (validators[i] instanceof CommonsValidator) {
                       CommonsValidator validator = (CommonsValidator) validators[i];

                       // look for a map of var's by component type
                       Map localVars = (Map) validatorVars.get(validator.getType());
                       if (localVars == null) {
                           localVars = new TreeMap();
                           validatorVars.put(validator.getType(), localVars);
                       } else {
                           localVars.clear();
                       }

                       Map vars = validator.getVars();
                       Iterator vi = vars.entrySet().iterator();
                       while (vi.hasNext()) {
                          Map.Entry e = (Map.Entry) vi.next();
                          // only override if the var contains a value binding expression
                          if (e.getValue() != null && e.getValue() instanceof String
                              && isValueReference((String) e.getValue())) {

                             localVars.put(e.getKey(), tagUtils.eval((String) e.getValue()));

                          }
                       }

                    }
                }

        }

        defaultRenderer.encodeBegin(context, component);
    }


    /** {@inheritDoc} */
    public void encodeChildren(FacesContext context, UIComponent component) throws IOException {
        defaultRenderer.encodeChildren(context, component);
    }


    /** {@inheritDoc} */
    public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
        defaultRenderer.encodeEnd(context, component);
    }


    /** {@inheritDoc} */
    public Object getConvertedValue(FacesContext context, UIComponent component,
            Object value) throws ConverterException {
        return defaultRenderer.getConvertedValue(context, component, value);
    }


    /** {@inheritDoc} */
    public boolean getRendersChildren() {
        return defaultRenderer.getRendersChildren();
    }


    /**
     * <p>Return true if the specified string contains an EL expression.</p>
     *
     * <p>This is taken almost verbatim from {@link javax.faces.webapp.UIComponentTag}
     * in order to remove JSP dependencies from the renderers.</p>
     *
     * @param value String to be checked for being an expression
     */
    private boolean isValueReference(String value) {

        if (value == null) {
            return false;
        }

        int start = value.indexOf("#{");
        if (start < 0) {
            return false;
        }

        int end = value.lastIndexOf('}');
        return (end >= 0) && (start < end);
    }


}
TOP

Related Classes of org.apache.shale.validator.faces.ValidatorInputRenderer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.