/* Copyright 2005-2006 Tim Fennell
*
* 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 net.sourceforge.stripes.tag;
import net.sourceforge.stripes.controller.StripesConstants;
import net.sourceforge.stripes.exception.StripesJspException;
import net.sourceforge.stripes.action.ActionBean;
import net.sourceforge.stripes.util.bean.BeanUtil;
import net.sourceforge.stripes.util.bean.ExpressionException;
import net.sourceforge.stripes.util.Log;
/**
* <p>An alternative tag population strategy that will normally prefer the value from the ActionBean
* over values from the request - even when the ActionBean returns null! Only if the ActionBean
* is not present, or does not define an attribute with the name supplied to the tag will other
* population sources be examined. When that happens, the strategy will check the value
* specified on the page next, and finally the value(s) in the request.</p>
*
* <p>If the field represented by the tag is determined to be in error (i.e. the ActionBean is
* present and has validation errors for the matching field) then the repopulation behaviour
* will revert to the default behaviour of preferring the request parameters.</p>
*
* @author Tim Fennell
* @since Stripes 1.4
*/
public class BeanFirstPopulationStrategy extends DefaultPopulationStrategy {
private static final Log log = Log.getInstance(BeanFirstPopulationStrategy.class);
/**
* Implementation of the interface method that will follow the search described in the class
* level JavaDoc and attempt to find a value for this tag.
*
* @param tag the form input tag whose value to populate
* @return Object will be one of null, a single Object or an Array of Objects depending upon
* what was submitted in the prior request, and what is declared on the ActionBean
*/
@Override
public Object getValue(InputTagSupport tag) throws StripesJspException {
// If the specific tag is in error, grab the values from the request
if (tag.hasErrors()) {
return super.getValue(tag);
}
else {
// Try getting from the ActionBean. If the bean is present and the property
// is defined, then the value from the bean takes precedence even if it's null
ActionBean bean = tag.getActionBean();
Object value = null;
boolean kaboom = false;
if (bean != null) {
try {
value = BeanUtil.getPropertyValue(tag.getName(), bean);
}
catch (ExpressionException ee) {
if (!StripesConstants.SPECIAL_URL_KEYS.contains(tag.getName())) {
log.info("Could not find property [", tag.getName(), "] on ActionBean.", ee);
}
kaboom = true;
}
}
// If there's no matching bean property, then look elsewhere
if (bean == null || kaboom) {
value = getValueFromTag(tag);
if (value == null) {
value = getValuesFromRequest(tag);
}
}
return value;
}
}
}