001/*
002 * Copyright 2002-2018 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.validation;
018
019import org.springframework.util.Assert;
020import org.springframework.util.ObjectUtils;
021
022/**
023 * Encapsulates a field error, that is, a reason for rejecting a specific
024 * field value.
025 *
026 * <p>See the {@link DefaultMessageCodesResolver} javadoc for details on
027 * how a message code list is built for a {@code FieldError}.
028 *
029 * @author Rod Johnson
030 * @author Juergen Hoeller
031 * @since 10.03.2003
032 * @see DefaultMessageCodesResolver
033 */
034@SuppressWarnings("serial")
035public class FieldError extends ObjectError {
036
037        private final String field;
038
039        private final Object rejectedValue;
040
041        private final boolean bindingFailure;
042
043
044        /**
045         * Create a new FieldError instance.
046         * @param objectName the name of the affected object
047         * @param field the affected field of the object
048         * @param defaultMessage the default message to be used to resolve this message
049         */
050        public FieldError(String objectName, String field, String defaultMessage) {
051                this(objectName, field, null, false, null, null, defaultMessage);
052        }
053
054        /**
055         * Create a new FieldError instance.
056         * @param objectName the name of the affected object
057         * @param field the affected field of the object
058         * @param rejectedValue the rejected field value
059         * @param bindingFailure whether this error represents a binding failure
060         * (like a type mismatch); else, it is a validation failure
061         * @param codes the codes to be used to resolve this message
062         * @param arguments the array of arguments to be used to resolve this message
063         * @param defaultMessage the default message to be used to resolve this message
064         */
065        public FieldError(String objectName, String field, Object rejectedValue, boolean bindingFailure,
066                        String[] codes, Object[] arguments, String defaultMessage) {
067
068                super(objectName, codes, arguments, defaultMessage);
069                Assert.notNull(field, "Field must not be null");
070                this.field = field;
071                this.rejectedValue = rejectedValue;
072                this.bindingFailure = bindingFailure;
073        }
074
075
076        /**
077         * Return the affected field of the object.
078         */
079        public String getField() {
080                return this.field;
081        }
082
083        /**
084         * Return the rejected field value.
085         */
086        public Object getRejectedValue() {
087                return this.rejectedValue;
088        }
089
090        /**
091         * Return whether this error represents a binding failure
092         * (like a type mismatch); otherwise it is a validation failure.
093         */
094        public boolean isBindingFailure() {
095                return this.bindingFailure;
096        }
097
098
099        @Override
100        public boolean equals(Object other) {
101                if (this == other) {
102                        return true;
103                }
104                if (!super.equals(other)) {
105                        return false;
106                }
107                FieldError otherError = (FieldError) other;
108                return (getField().equals(otherError.getField()) &&
109                                ObjectUtils.nullSafeEquals(getRejectedValue(), otherError.getRejectedValue()) &&
110                                isBindingFailure() == otherError.isBindingFailure());
111        }
112
113        @Override
114        public int hashCode() {
115                int hashCode = super.hashCode();
116                hashCode = 29 * hashCode + getField().hashCode();
117                hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(getRejectedValue());
118                hashCode = 29 * hashCode + (isBindingFailure() ? 1 : 0);
119                return hashCode;
120        }
121
122        @Override
123        public String toString() {
124                return "Field error in object '" + getObjectName() + "' on field '" + this.field +
125                                "': rejected value [" + ObjectUtils.nullSafeToString(this.rejectedValue) + "]; " +
126                                resolvableToString();
127        }
128
129}