/* Copyright 2008 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 javax.servlet.jsp.tagext.TagExtraInfo; import javax.servlet.jsp.tagext.VariableInfo; import javax.servlet.jsp.tagext.TagData; import javax.servlet.jsp.tagext.ValidationMessage; import java.util.Collection; import java.util.ArrayList; /** * Validates that the mutually exclusive attribute pairs of the tag are provided correctly * and attempts to provide type information to the container for the bean assigned * to the variable named by the {@code var} or {@code id} attribute. The latter can only be done * when the {@code beanclass} attribute is used instead of the {@code binding} attribute * because runtime information is needed to translate {@code binding} into a class name. * * @author tfenne * @since Stripes 1.5 */ public class UseActionBeanTagExtraInfo extends TagExtraInfo { private static final VariableInfo[] NO_INFO = new VariableInfo[0]; /** * Attempts to return type information so that the container can create a * named variable for the action bean. */ @Override public VariableInfo[] getVariableInfo(final TagData tag) { // We can only provide the type of 'var' if beanclass was used because // if binding was used we need runtime information! Object beanclass = tag.getAttribute("beanclass"); // Turns out beanclass="${...}" does NOT return TagData.REQUEST_TIME_VALUE; only beanclass="<%= ... %>". if (beanclass != null && !beanclass.equals(TagData.REQUEST_TIME_VALUE)) { String var = tag.getAttributeString("var"); if (var == null) var = tag.getAttributeString("id"); // Make sure we have the class name, not the class if (beanclass instanceof Class<?>) beanclass = ((Class<?>) beanclass).getName(); // Return the variable info if (beanclass instanceof String) { String string = (String) beanclass; if (!string.startsWith("${")) { return new VariableInfo[] { new VariableInfo(var, string, true, VariableInfo.AT_BEGIN) }; } } } return NO_INFO; } /** * Checks to ensure that where the tag supports providing one of two attributes * that one and only one is provided. */ @Override public ValidationMessage[] validate(final TagData tag) { Collection<ValidationMessage> errors = new ArrayList<ValidationMessage>(); Object beanclass = tag.getAttribute("beanclass"); Object binding = tag.getAttribute("binding"); if (!(beanclass != null ^ binding != null)) { errors.add(new ValidationMessage(tag.getId(), "Exactly one of 'beanclass' or 'binding' must be supplied.")); } String var = tag.getAttributeString("var"); String id = tag.getAttributeString("id"); if (!(var != null ^ id != null)) { errors.add(new ValidationMessage(tag.getId(), "Exactly one of 'var' or 'id' must be supplied.")); } return errors.toArray(new ValidationMessage[errors.size()]); } }