| /* |
| * 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; |
| } |
| } |