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

TAKETODAY / today-infrastructure / 18154768944

01 Oct 2025 07:26AM UTC coverage: 81.882% (-0.005%) from 81.887%
18154768944

push

github

web-flow
Merge pull request #290 from TAKETODAY/dev/jspecify

jspecify

59788 of 78013 branches covered (76.64%)

Branch coverage included in aggregate %.

141239 of 167496 relevant lines covered (84.32%)

3.6 hits per line

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

85.71
today-context/src/main/java/infra/context/support/StaticMessageSource.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.context.support;
19

20
import org.jspecify.annotations.Nullable;
21

22
import java.text.MessageFormat;
23
import java.util.HashMap;
24
import java.util.Locale;
25
import java.util.Map;
26

27
import infra.lang.Assert;
28

29
/**
30
 * Simple implementation of {@link infra.context.MessageSource}
31
 * which allows messages to be registered programmatically.
32
 * This MessageSource supports basic internationalization.
33
 *
34
 * <p>Intended for testing rather than for use in production systems.
35
 *
36
 * @author Rod Johnson
37
 * @author Juergen Hoeller
38
 * @author <a href="https://github.com/TAKETODAY">Harry Yang</a>
39
 */
40
public class StaticMessageSource extends AbstractMessageSource {
2✔
41

42
  private final Map<String, Map<Locale, MessageHolder>> messageMap = new HashMap<>();
6✔
43

44
  @Override
45
  @Nullable
46
  protected String resolveCodeWithoutArguments(String code, Locale locale) {
47
    Map<Locale, MessageHolder> localeMap = this.messageMap.get(code);
6✔
48
    if (localeMap == null) {
2✔
49
      return null;
2✔
50
    }
51
    MessageHolder holder = localeMap.get(locale);
5✔
52
    if (holder == null) {
2!
53
      return null;
×
54
    }
55
    return holder.getMessage();
3✔
56
  }
57

58
  @Override
59
  @Nullable
60
  protected MessageFormat resolveCode(String code, Locale locale) {
61
    Map<Locale, MessageHolder> localeMap = this.messageMap.get(code);
6✔
62
    if (localeMap == null) {
2✔
63
      return null;
2✔
64
    }
65
    MessageHolder holder = localeMap.get(locale);
5✔
66
    if (holder == null) {
2!
67
      return null;
×
68
    }
69
    return holder.getMessageFormat();
3✔
70
  }
71

72
  /**
73
   * Associate the given message with the given code.
74
   *
75
   * @param code the lookup code
76
   * @param locale the locale that the message should be found within
77
   * @param msg the message associated with this lookup code
78
   */
79
  public void addMessage(String code, Locale locale, String msg) {
80
    Assert.notNull(code, "Code is required");
3✔
81
    Assert.notNull(locale, "Locale is required");
3✔
82
    Assert.notNull(msg, "Message is required");
3✔
83
    this.messageMap.computeIfAbsent(code, key -> new HashMap<>(4)).put(locale, new MessageHolder(msg, locale));
20✔
84
    if (logger.isDebugEnabled()) {
4!
85
      logger.debug("Added message [{}] for code [{}] and Locale [{}]", msg, code, locale);
×
86
    }
87
  }
1✔
88

89
  /**
90
   * Associate the given message values with the given keys as codes.
91
   *
92
   * @param messages the messages to register, with messages codes
93
   * as keys and message texts as values
94
   * @param locale the locale that the messages should be found within
95
   */
96
  public void addMessages(Map<String, String> messages, Locale locale) {
97
    Assert.notNull(messages, "Messages Map is required");
3✔
98
    for (Map.Entry<String, String> entry : messages.entrySet()) {
11✔
99
      String code = entry.getKey();
4✔
100
      String msg = entry.getValue();
4✔
101
      addMessage(code, locale, msg);
5✔
102
    }
1✔
103
  }
1✔
104

105
  @Override
106
  public String toString() {
107
    return getClass().getName() + ": " + this.messageMap;
×
108
  }
109

110
  private class MessageHolder {
111

112
    private final String message;
113

114
    private final Locale locale;
115

116
    @Nullable
117
    private volatile MessageFormat cachedFormat;
118

119
    public MessageHolder(String message, Locale locale) {
5✔
120
      this.message = message;
3✔
121
      this.locale = locale;
3✔
122
    }
1✔
123

124
    public String getMessage() {
125
      return this.message;
3✔
126
    }
127

128
    public MessageFormat getMessageFormat() {
129
      MessageFormat messageFormat = this.cachedFormat;
3✔
130
      if (messageFormat == null) {
2✔
131
        messageFormat = createMessageFormat(this.message, this.locale);
8✔
132
        this.cachedFormat = messageFormat;
3✔
133
      }
134
      return messageFormat;
2✔
135
    }
136

137
    @Override
138
    public String toString() {
139
      return this.message;
×
140
    }
141
  }
142

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

© 2026 Coveralls, Inc