• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

TAKETODAY / today-infrastructure / 20632861616

01 Jan 2026 04:53AM UTC coverage: 84.18% (-0.3%) from 84.439%
20632861616

push

github

TAKETODAY
:sparkles: ApplicationType 支持通过 SPI 获取

55643 of 70608 branches covered (78.81%)

Branch coverage included in aggregate %.

130472 of 150485 relevant lines covered (86.7%)

3.73 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

82.0
today-context/src/main/java/infra/validation/ObjectError.java
1
/*
2
 * Copyright 2017 - 2025 the original author or authors.
3
 *
4
 * This program is free software: you can redistribute it and/or modify
5
 * it under the terms of the GNU General Public License as published by
6
 * the Free Software Foundation, either version 3 of the License, or
7
 * (at your option) any later version.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program. If not, see [https://www.gnu.org/licenses/]
16
 */
17

18
package infra.validation;
19

20
import org.jspecify.annotations.Nullable;
21

22
import java.io.Serial;
23

24
import infra.beans.PropertyAccessException;
25
import infra.context.support.DefaultMessageSourceResolvable;
26
import infra.lang.Assert;
27

28
/**
29
 * Encapsulates an object error, that is, a global reason for rejecting
30
 * an object.
31
 *
32
 * <p>See the {@link DefaultMessageCodesResolver} javadoc for details on
33
 * how a message code list is built for an {@code ObjectError}.
34
 *
35
 * @author Juergen Hoeller
36
 * @author <a href="https://github.com/TAKETODAY">Harry Yang</a>
37
 * @see FieldError
38
 * @see DefaultMessageCodesResolver
39
 * @since 4.0
40
 */
41
public class ObjectError extends DefaultMessageSourceResolvable {
42

43
  @Serial
44
  private static final long serialVersionUID = 1L;
45

46
  private final String objectName;
47

48
  @Nullable
49
  private transient Object source;
50

51
  /**
52
   * Create a new instance of the ObjectError class.
53
   *
54
   * @param objectName the name of the affected object
55
   * @param defaultMessage the default message to be used to resolve this message
56
   */
57
  public ObjectError(String objectName, String defaultMessage) {
58
    this(objectName, null, null, defaultMessage);
6✔
59
  }
1✔
60

61
  /**
62
   * Create a new instance of the ObjectError class.
63
   *
64
   * @param objectName the name of the affected object
65
   * @param codes the codes to be used to resolve this message
66
   * @param arguments the array of arguments to be used to resolve this message
67
   * @param defaultMessage the default message to be used to resolve this message
68
   */
69
  public ObjectError(String objectName, String @Nullable [] codes,
70
          Object @Nullable [] arguments, @Nullable String defaultMessage) {
71

72
    super(codes, arguments, defaultMessage);
5✔
73
    Assert.notNull(objectName, "Object name is required");
3✔
74
    this.objectName = objectName;
3✔
75
  }
1✔
76

77
  /**
78
   * Return the name of the affected object.
79
   */
80
  public String getObjectName() {
81
    return this.objectName;
3✔
82
  }
83

84
  /**
85
   * Preserve the source behind this error: possibly an {@link Exception}
86
   * (typically {@link PropertyAccessException})
87
   * or a Bean Validation {@link jakarta.validation.ConstraintViolation}.
88
   * <p>Note that any such source object is being stored as transient:
89
   * that is, it won't be part of a serialized error representation.
90
   *
91
   * @param source the source object
92
   */
93
  public void wrap(Object source) {
94
    if (this.source != null) {
3!
95
      throw new IllegalStateException("Already wrapping " + this.source);
×
96
    }
97
    this.source = source;
3✔
98
  }
1✔
99

100
  /**
101
   * Unwrap the source behind this error: possibly an {@link Exception}
102
   * (typically {@link PropertyAccessException})
103
   * or a Bean Validation {@link jakarta.validation.ConstraintViolation}.
104
   * <p>The cause of the outermost exception will be introspected as well,
105
   * e.g. the underlying conversion exception or exception thrown from a setter
106
   * (instead of having to unwrap the {@code PropertyAccessException} in turn).
107
   *
108
   * @return the source object of the given type
109
   * @throws IllegalArgumentException if no such source object is available
110
   * (i.e. none specified or not available anymore after deserialization)
111
   */
112
  public <T> T unwrap(Class<T> sourceType) {
113
    if (sourceType.isInstance(this.source)) {
5✔
114
      return sourceType.cast(this.source);
5✔
115
    }
116
    else if (this.source instanceof Throwable) {
4!
117
      Throwable cause = ((Throwable) this.source).getCause();
5✔
118
      if (sourceType.isInstance(cause)) {
4!
119
        return sourceType.cast(cause);
4✔
120
      }
121
    }
122
    throw new IllegalArgumentException("No source object of the given type available: " + sourceType);
×
123
  }
124

125
  /**
126
   * Check the source behind this error: possibly an {@link Exception}
127
   * (typically {@link PropertyAccessException})
128
   * or a Bean Validation {@link jakarta.validation.ConstraintViolation}.
129
   * <p>The cause of the outermost exception will be introspected as well,
130
   * e.g. the underlying conversion exception or exception thrown from a setter
131
   * (instead of having to unwrap the {@code PropertyAccessException} in turn).
132
   *
133
   * @return whether this error has been caused by a source object of the given type
134
   */
135
  public boolean contains(Class<?> sourceType) {
136
    return (sourceType.isInstance(this.source) ||
14!
137
            (this.source instanceof Throwable && sourceType.isInstance(((Throwable) this.source).getCause())));
5!
138
  }
139

140
  @Override
141
  public boolean equals(@Nullable Object other) {
142
    if (this == other) {
3✔
143
      return true;
2✔
144
    }
145
    if (other == null || other.getClass() != getClass() || !super.equals(other)) {
11!
146
      return false;
2✔
147
    }
148
    ObjectError otherError = (ObjectError) other;
3✔
149
    return getObjectName().equals(otherError.getObjectName());
6✔
150
  }
151

152
  @Override
153
  public int hashCode() {
154
    return (29 * super.hashCode() + getObjectName().hashCode());
×
155
  }
156

157
  @Override
158
  public String toString() {
159
    return "Error in object '" + this.objectName + "': " + resolvableToString();
6✔
160
  }
161

162
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc