blob: 69f466dc0424fb7d1493d6eece23408a77b003b6 [file] [log] [blame]
/*
* 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.myfaces.extensions.validator.core.validation.strategy;
import org.apache.myfaces.extensions.validator.core.validation.message.resolver.MessageResolver;
import org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry;
import org.apache.myfaces.extensions.validator.core.property.PropertyInformationKeys;
import org.apache.myfaces.extensions.validator.internal.Priority;
import org.apache.myfaces.extensions.validator.internal.ToDo;
import org.apache.myfaces.extensions.validator.internal.UsageInformation;
import org.apache.myfaces.extensions.validator.internal.UsageCategory;
import org.apache.myfaces.extensions.validator.util.ExtValUtils;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.component.UIComponent;
import javax.faces.validator.ValidatorException;
import java.lang.annotation.Annotation;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.logging.Level;
/**
* This class provides an easier handling of violation messages.
* This abstract class is a good candidate as super-class for custom validation strategies.
*
* @since 1.x.1
*/
@UsageInformation({UsageCategory.INTERNAL, UsageCategory.REUSE})
public abstract class AbstractAnnotationValidationStrategy<A extends Annotation> extends AbstractValidationStrategy
{
protected static final String DETAIL_MESSAGE_KEY_POSTFIX = "_detail";
//e.g. for injecting a message resolver via spring
private MessageResolver messageResolver;
/**
* Uses the given message key to resolve the actual message in the correct language.
* The current {@link javax.faces.component.UIViewRoot} provides the target locale.
* When a {@link org.apache.myfaces.extensions.validator.core.validation.message.resolver.MessageResolver}
* is available, it is used to resolve the message.
* Otherwise the default rules are taken to define the
* {@link org.apache.myfaces.extensions.validator.core.validation.message.resolver.MessageResolver}.
* {@link org.apache.myfaces.extensions.validator.util.ExtValUtils#getMessageResolverForValidationStrategy(
* org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy)}
*
* @param key key of the error message that needs to be resolved.
* @return Resolved message.
*/
protected String resolveMessage(String key)
{
Locale locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
return this.messageResolver != null ? this.messageResolver.getMessage(key, locale) :
ExtValUtils.getMessageResolverForValidationStrategy(this).getMessage(key, locale);
}
/**
* Returns the error message (the summary) provided by the given constraint. The message is determined
* by using the {@link #getValidationErrorMsgKey} method for obtaining the message-/key which then is
* resolved by the method {@link #resolveMessage(String) resolveMessage}.
*
* @param annotation The annotation associated with the
* {@link org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy}.
* @return The error message used in the summary part of the
* {@link javax.faces.application.FacesMessage FacesMessage}.
*/
protected String getErrorMessageSummary(A annotation)
{
return resolveMessage(getValidationErrorMsgKey(annotation));
}
/**
* Returns the error message (the detailed message) provided by the given constraint. The message is determined
* by using the {@link #getValidationErrorMsgKey} method for obtaining the message-/key which then is
* resolved by the method {@link #resolveMessage(String) resolveMessage}.
* When the key isn't found, the resulting exception is just logged but not propagated.
* So the detail message isn't required and null is returned instead.
*
* @param annotation The annotation associated with the
* {@link org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy}.
* @return The error message used in the detail part of the
* {@link javax.faces.application.FacesMessage FacesMessage} or null.
*/
@ToDo(value = Priority.MEDIUM, description = "just log it in case of project stage development")
protected String getErrorMessageDetail(A annotation)
{
try
{
String key = getValidationErrorMsgKey(annotation);
return (key != null) ? resolveMessage(key + DETAIL_MESSAGE_KEY_POSTFIX) : null;
}
catch (MissingResourceException e)
{
logger.log(Level.WARNING,
"couldn't find key " + getValidationErrorMsgKey(annotation) + DETAIL_MESSAGE_KEY_POSTFIX, e);
}
return null;
}
/**
* Creates the {@link javax.faces.application.FacesMessage FacesMessage} that
* will be used to inform the user of a validation error. This method can be called by
* subclasses in the {@link #processValidation(FacesContext, UIComponent, MetaDataEntry, Object) processValidation}
* method when a {@link ValidatorException} is thrown.
*
* @param annotation The annotation associated with the
* {@link org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy}.
* @return FacesMessage for informing user of the problem.
*/
protected FacesMessage getValidationErrorFacesMessage(A annotation)
{
return ExtValUtils.createFacesMessage(getErrorMessageSummary(annotation), getErrorMessageDetail(annotation));
}
/**
* Returns the key for the message that needs to be resolved for the violation-message.
*
* @param annotation The annotation associated with the
* {@link org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy}.
* @return The key of the error message.
*/
protected abstract String getValidationErrorMsgKey(A annotation);
/**
* Injection point for a
* {@link org.apache.myfaces.extensions.validator.core.validation.message.resolver.MessageResolver}
* that needs to be used by this
* {@link org.apache.myfaces.extensions.validator.core.validation.strategy.ValidationStrategy}.
*
* @param messageResolver messageResolver that needs to be used by this validationStrategy.
*/
@SuppressWarnings({"UnusedDeclaration"})
public void setMessageResolver(MessageResolver messageResolver)
{
this.messageResolver = messageResolver;
}
/**
* {@inheritDoc}
* Adds the label of the component to the
* {@link org.apache.myfaces.extensions.validator.core.metadata.MetaDataEntry}.
*/
@Override
protected boolean processAfterValidatorException(FacesContext facesContext,
UIComponent uiComponent,
MetaDataEntry metaDataEntry,
Object convertedObject,
ValidatorException validatorException)
{
metaDataEntry.setProperty(PropertyInformationKeys.LABEL, getLabel(facesContext, uiComponent, metaDataEntry));
return super.processAfterValidatorException(
facesContext, uiComponent, metaDataEntry, convertedObject, validatorException);
}
/**
* Returns the label of the uiComponent field that could be used in the error messages. By default it returns null.
*
* @param facesContext The JSF Context
* @param uiComponent The JSF component that contained the value entered by the user.
* @param metaDataEntry The data holder which stores the meta-data and some information where the meta-data was
* around.
* @return The label-text of the {@link javax.faces.component.UIComponent} which can be used in the violation msg.
*/
//e.g. for custom annotations - override if needed
protected String getLabel(FacesContext facesContext, UIComponent uiComponent, MetaDataEntry metaDataEntry)
{
return null;
}
}