• 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

72.92
today-context/src/main/java/infra/context/expression/CachedExpressionEvaluator.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.expression;
19

20
import org.jspecify.annotations.Nullable;
21

22
import java.util.Map;
23

24
import infra.core.ParameterNameDiscoverer;
25
import infra.expression.Expression;
26
import infra.expression.spel.standard.SpelExpressionParser;
27
import infra.lang.Assert;
28

29
/**
30
 * Shared utility class used to evaluate and cache EL expressions that
31
 * are defined on {@link java.lang.reflect.AnnotatedElement}.
32
 *
33
 * @author <a href="https://github.com/TAKETODAY">Harry Yang</a>
34
 * @since 4.0 2021/12/25 16:59
35
 */
36
public abstract class CachedExpressionEvaluator {
37

38
  protected final SpelExpressionParser parser;
39

40
  /**
41
   * a shared parameter name discoverer which caches data internally.
42
   */
43
  protected final ParameterNameDiscoverer parameterNameDiscoverer;
44

45
  /**
46
   * Create a new instance with a default {@link SpelExpressionParser}.
47
   */
48
  protected CachedExpressionEvaluator() {
49
    this(SpelExpressionParser.INSTANCE);
3✔
50
  }
1✔
51

52
  /**
53
   * Create a new instance with the specified {@link SpelExpressionParser}.
54
   */
55
  protected CachedExpressionEvaluator(SpelExpressionParser parser) {
56
    this(parser, ParameterNameDiscoverer.getSharedInstance());
4✔
57
  }
1✔
58

59
  /**
60
   * Create a new instance with the specified {@link SpelExpressionParser}.
61
   */
62
  protected CachedExpressionEvaluator(SpelExpressionParser parser, ParameterNameDiscoverer parameterNameDiscoverer) {
2✔
63
    Assert.notNull(parser, "SpelExpressionParser is required");
3✔
64
    Assert.notNull(parameterNameDiscoverer, "ParameterNameDiscoverer is required");
3✔
65
    this.parser = parser;
3✔
66
    this.parameterNameDiscoverer = parameterNameDiscoverer;
3✔
67
  }
1✔
68

69
  /**
70
   * Return the {@link Expression} for the specified SpEL value
71
   * <p>{@link #parseExpression(String) Parse the expression} if it hasn't been already.
72
   *
73
   * @param cache the cache to use
74
   * @param elementKey the element on which the expression is defined
75
   * @param expression the expression to parse
76
   */
77
  protected Expression getExpression(Map<ExpressionKey, Expression> cache, AnnotatedElementKey elementKey, String expression) {
78
    ExpressionKey expressionKey = createKey(elementKey, expression);
5✔
79
    Expression expr = cache.get(expressionKey);
5✔
80
    if (expr == null) {
2✔
81
      expr = parseExpression(expression);
4✔
82
      cache.put(expressionKey, expr);
5✔
83
    }
84
    return expr;
2✔
85
  }
86

87
  /**
88
   * Parse the specified {@code expression}.
89
   *
90
   * @param expression the expression to parse
91
   */
92
  protected Expression parseExpression(String expression) {
93
    return parser.parseExpression(expression);
5✔
94
  }
95

96
  private ExpressionKey createKey(AnnotatedElementKey elementKey, String expression) {
97
    return new ExpressionKey(elementKey, expression);
6✔
98
  }
99

100
  /**
101
   * An expression key.
102
   */
103
  protected static class ExpressionKey implements Comparable<ExpressionKey> {
104

105
    private final String expression;
106

107
    private final AnnotatedElementKey element;
108

109
    protected ExpressionKey(AnnotatedElementKey element, String expression) {
2✔
110
      Assert.notNull(element, "AnnotatedElementKey is required");
3✔
111
      Assert.notNull(expression, "Expression is required");
3✔
112
      this.element = element;
3✔
113
      this.expression = expression;
3✔
114
    }
1✔
115

116
    @Override
117
    public boolean equals(@Nullable Object other) {
118
      if (this == other) {
3!
119
        return true;
×
120
      }
121
      if (!(other instanceof ExpressionKey otherKey)) {
7!
122
        return false;
×
123
      }
124
      return element.equals(otherKey.element)
11!
125
              && expression.equals(otherKey.expression);
4!
126
    }
127

128
    @Override
129
    public int hashCode() {
130
      return this.element.hashCode() * 29 + this.expression.hashCode();
10✔
131
    }
132

133
    @Override
134
    public String toString() {
135
      return "%s with expression \"%s\"".formatted(this.element, this.expression);
×
136
    }
137

138
    @Override
139
    public int compareTo(ExpressionKey other) {
140
      int result = this.element.toString().compareTo(other.element.toString());
×
141
      if (result == 0) {
×
142
        result = this.expression.compareTo(other.expression);
×
143
      }
144
      return result;
×
145
    }
146
  }
147

148
}
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