Package org.springframework.springfaces.mvc.internal

Source Code of org.springframework.springfaces.mvc.internal.ModelBuilder

/*
* Copyright 2010-2012 the original author or authors.
*
* Licensed 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.springframework.springfaces.mvc.internal;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.faces.component.UIComponent;
import javax.faces.component.UIParameter;
import javax.faces.context.FacesContext;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.core.Conventions;
import org.springframework.springfaces.mvc.model.SpringFacesModel;
import org.springframework.util.StringUtils;

/**
* Utility class that can be used to combine several sources to build a complete model. Elements can be added to the
* model using the various <tt>add</tt> methods. When trying to add an item with a key that is already contained in the
* model the existing value is retained. The add methods should be called in order of precedence, with the highest
* importance being called first.
*
* @author Phillip Webb
* @see #add(Map, boolean)
* @see #addFromComponent(UIComponent)
* @see #addFromParameterList(Map)
*/
public class ModelBuilder {

  private Log logger = LogFactory.getLog(ModelBuilder.class);

  private FacesContext context;

  private Map<String, Object> model = new HashMap<String, Object>();

  /**
   * Create a new ModelBuilder.
   * @param context
   */
  public ModelBuilder(FacesContext context) {
    this.context = context;
  }

  /**
   * Add model elements by inspecting all {@link UIParameter} children of the specified component. Child parameters
   * that do not specify a name will have one generated using Spring {@link Conventions#getVariableName conventions}.
   * If a parameter references an existing MVC {@link SpringFacesModel model} then the complete model will be added.
   * @param component the component to inspect or <tt>null</tt>
   */
  public void addFromComponent(UIComponent component) {
    if (component != null) {
      if (this.logger.isDebugEnabled()) {
        this.logger.debug("Exposing UIParameter children of component " + component.getClientId(this.context)
            + " to MVC model");
      }
      for (UIComponent child : component.getChildren()) {
        if (child instanceof UIParameter) {
          UIParameter parameter = (UIParameter) child;
          addUIParam(parameter);
        }
      }
    }
  }

  /**
   * Adds a single {@link UIParameter} to the model.
   * @param parameter the parameter to add
   */
  private void addUIParam(UIParameter parameter) {
    String source = parameter.getClientId(this.context)
        + (parameter.getName() == null ? "" : " ('" + parameter.getName() + "')");
    if (parameter.isDisable()) {
      if (this.logger.isDebugEnabled()) {
        this.logger.debug("Skipping disabled parameter " + source);
      }
      return;
    }
    addIfNotInModel(source, parameter.getName(), parameter.getValue(), false, true);
  }

  /**
   * Add model elements from the specified map. When <tt>resolveExpressions</tt> is <tt>true</tt> the map may contain
   * String EL expressions that will be resolved as the model is built.
   * @param map a map of items to add to the model or <tt>null</tt>
   * @param resolveExpressions if the EL expression from <tt>String<tt> values in the map should be resolved.
   */
  public void add(Map<String, Object> map, boolean resolveExpressions) {
    if (map != null) {
      for (Map.Entry<String, Object> modelEntry : map.entrySet()) {
        addIfNotInModel(modelEntry.getKey(), modelEntry.getKey(), modelEntry.getValue(), resolveExpressions,
            false);
      }
    }
  }

  /**
   * Add model elements from a JSF parameters map. Only entries with a single parameter will be added to the model.
   * Parameters may contain String EL expressions that will be resolved as the model is built. NOTE: JSF Parameters
   * are often constructed from {@link UIParameter}s. Whenever possible call {@link #addFromComponent(UIComponent)} to
   * add {@link UIParameter}s before calling this method.
   * @param parameters the parameters to add or <tt>null</tt>
   */
  public void addFromParameterList(Map<String, List<String>> parameters) {
    if (parameters != null) {
      for (Map.Entry<String, List<String>> parameter : parameters.entrySet()) {
        if (parameter.getValue().size() == 1) {
          addIfNotInModel(parameter.getKey(), parameter.getKey(), parameter.getValue().get(0), true, false);
        } else {
          if (this.logger.isWarnEnabled()) {
            this.logger.warn("Unable to expose multi-value parameter '" + parameter.getKey()
                + "' to bookmark model");
          }
        }
      }
    }
  }

  /**
   * Adds the specified key/value pair to the model as long as the model does not already contain the key.
   * @param source a textual description of the source of the item that can be used for logging
   * @param key the key to add to the model or <tt>null</tt> if the key should be generated from the value
   * @param value the value to add to the model. If the value is not specified then the model remains unchanged
   * @param resolveExpressions determines if values can contain <tt>String</tt> EL expression that should be resolved
   * @param expandModelHolder determines if values containing {@link SpringFacesModel} objects should have each member
   * of the holder added to the model as a separate item
   */
  private void addIfNotInModel(String source, String key, Object value, boolean resolveExpressions,
      boolean expandModelHolder) {
    if (value == null) {
      if (this.logger.isDebugEnabled()) {
        this.logger.debug("Skipping parameter " + source + " due to null value");
      }
      return;
    }
    if (key == null) {
      key = Conventions.getVariableName(value);
    }
    if (this.model.containsKey(key)) {
      if (this.logger.isDebugEnabled()) {
        this.logger.debug("Skipping parameter " + source + " due to exsting value in model");
      }
      return;
    }
    if (resolveExpressions) {
      value = resolveExpressionIfNecessary(value);
    }
    if (value instanceof SpringFacesModel && expandModelHolder) {
      SpringFacesModel modelHolder = (SpringFacesModel) value;
      for (Map.Entry<String, Object> modelEntry : modelHolder.entrySet()) {
        addIfNotInModel(source, modelEntry.getKey(), modelEntry.getValue(), false, false);
      }
    } else {
      this.model.put(key, value);
    }
  }

  /**
   * Resolve any <tt>String</tt> EL expressions from the value.
   * @param value the value to resolve
   * @return a resolved EL expression or the value unchanged
   */
  private Object resolveExpressionIfNecessary(Object value) {
    if (isExpression(value)) {
      return this.context.getApplication().evaluateExpressionGet(this.context, value.toString(), Object.class);
    }
    return value;
  }

  /**
   * Determine if an object contains an expression.
   * @param value the value to check
   * @return <tt>true</tt> if the value contains an EL expression
   */
  private boolean isExpression(Object value) {
    if (value instanceof String && StringUtils.hasLength((String) value)) {
      String expressionString = (String) value;
      int start = expressionString.indexOf("#{");
      int end = expressionString.indexOf('}');
      return (start != -1) && (start < end);
    }
    return false;
  }

  public Map<String, Object> getModel() {
    return this.model;
  }
}
TOP

Related Classes of org.springframework.springfaces.mvc.internal.ModelBuilder

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.