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

aspectran / aspectran / #3974

09 Jan 2025 11:40AM CUT coverage: 35.027% (+0.007%) from 35.02%
#3974

push

github

topframe
Update

14192 of 40517 relevant lines covered (35.03%)

0.35 hits per line

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

89.02
/core/src/main/java/com/aspectran/core/context/asel/TokenizedExpression.java
1
/*
2
 * Copyright (c) 2008-2025 The Aspectran Project
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
package com.aspectran.core.context.asel;
17

18
import com.aspectran.core.activity.Activity;
19
import com.aspectran.core.context.asel.ognl.OgnlSupport;
20
import com.aspectran.core.context.asel.token.Token;
21
import com.aspectran.core.context.asel.token.TokenEvaluator;
22
import com.aspectran.core.context.asel.token.TokenParser;
23
import com.aspectran.core.context.rule.type.TokenType;
24
import com.aspectran.utils.Assert;
25
import com.aspectran.utils.StringUtils;
26
import com.aspectran.utils.ToStringBuilder;
27
import com.aspectran.utils.annotation.jsr305.NonNull;
28
import com.aspectran.utils.annotation.jsr305.Nullable;
29
import ognl.Ognl;
30
import ognl.OgnlContext;
31
import ognl.OgnlException;
32

33
import java.util.Collections;
34
import java.util.HashMap;
35
import java.util.Map;
36
import java.util.Set;
37

38
/**
39
 * <p>Created: 2024. 11. 26.</p>
40
 */
41
public class TokenizedExpression implements ExpressionEvaluator {
42

43
    private static final String TOKEN_VAR_REF_SYMBOL = "#";
44

45
    private static final String TOKEN_VAR_NAME_PREFIX = "__";
46

47
    private static final String TOKEN_VAR_NAME_SUFFIX = TOKEN_VAR_NAME_PREFIX;
48

49
    private final String expression;
50

51
    private String substitutedExpression;
52

53
    private Object parsedExpression;
54

55
    private Token[] tokens;
56

57
    private Map<String, Token> tokenVars;
58

59
    private Set<String> tokenVarNames;
60

61
    public TokenizedExpression(String expression) throws ExpressionParserException {
1✔
62
        this.expression = expression;
1✔
63
        parseExpression();
1✔
64
    }
1✔
65

66
    @Override
67
    @Nullable
68
    public String getExpressionString() {
69
        return expression;
1✔
70
    }
71

72
    @Override
73
    @Nullable
74
    public String getSubstitutedExpression() {
75
        return substitutedExpression;
×
76
    }
77

78
    @Override
79
    @Nullable
80
    public Object getParsedExpression() {
81
        return parsedExpression;
1✔
82
    }
83

84
    @Override
85
    @Nullable
86
    public Token[] getTokens() {
87
        return tokens;
1✔
88
    }
89

90
    @Override
91
    @Nullable
92
    public Set<String> getTokenVarNames() {
93
        return tokenVarNames;
1✔
94
    }
95

96
    public boolean hasTokenVars() {
97
        return (tokenVarNames != null && !tokenVarNames.isEmpty());
1✔
98
    }
99

100
    private void parseExpression() throws ExpressionParserException {
101
        Token[] tokens = TokenParser.makeTokens(expression, true);
1✔
102
        Map<String, Token> tokenVars = null;
1✔
103
        String substitutedExpression = null;
1✔
104
        if (tokens != null && tokens.length > 0) {
1✔
105
            tokenVars = new HashMap<>();
1✔
106
            if (tokens.length == 1) {
1✔
107
                Token token = tokens[0];
1✔
108
                if (token.getType() == TokenType.TEXT) {
1✔
109
                    substitutedExpression = token.getDefaultValue();
1✔
110
                } else {
111
                    String tokenVarName = createTokenVarName(token);
1✔
112
                    tokenVars.putIfAbsent(tokenVarName, token);
1✔
113
                    substitutedExpression = createTokenVarRefName(tokenVarName);
1✔
114
                }
115
            } else {
1✔
116
                StringBuilder sb = new StringBuilder();
1✔
117
                for (Token token : tokens) {
1✔
118
                    if (token.getType() == TokenType.TEXT) {
1✔
119
                        sb.append(token.getDefaultValue());
1✔
120
                    } else {
121
                        String tokenVarName = createTokenVarName(token);
1✔
122
                        tokenVars.putIfAbsent(tokenVarName, token);
1✔
123
                        substitutedExpression = createTokenVarRefName(tokenVarName);
1✔
124
                        sb.append(substitutedExpression);
1✔
125
                    }
126
                }
127
                substitutedExpression = sb.toString();
1✔
128
            }
129
        }
130
        this.tokens = tokens;
1✔
131
        this.tokenVars = (tokenVars != null && !tokenVars.isEmpty() ? Collections.unmodifiableMap(tokenVars) : null);
1✔
132
        this.tokenVarNames = (tokenVars != null && !tokenVars.isEmpty() ? Collections.unmodifiableSet(tokenVars.keySet()) : null);
1✔
133
        this.substitutedExpression = substitutedExpression;
1✔
134
        if (substitutedExpression != null) {
1✔
135
            try {
136
                this.parsedExpression = Ognl.parseExpression(substitutedExpression);
1✔
137
            } catch (OgnlException e) {
×
138
                throw new ExpressionParserException(expression, e);
×
139
            }
1✔
140
        }
141
    }
1✔
142

143
    @Override
144
    public Object evaluate(Activity activity, OgnlContext ognlContext) {
145
        return evaluate(activity, ognlContext, null, null);
×
146
    }
147

148
    @Override
149
    public Object evaluate(Activity activity, OgnlContext ognlContext, Object root) {
150
        return evaluate(activity, ognlContext, root, null);
×
151
    }
152

153
    @Override
154
    public Object evaluate(Activity activity, OgnlContext ognlContext, Object root, Class<?> resultType) {
155
        Assert.notNull(activity, "activity must not be null");
1✔
156
        Assert.notNull(ognlContext, "ognlContext must not be null");
1✔
157
        if (getParsedExpression() == null) {
1✔
158
            return null;
×
159
        }
160
        try {
161
            preProcess(activity, ognlContext);
1✔
162
            Object value = OgnlSupport.getValue(getParsedExpression(), ognlContext, root, resultType);
1✔
163
            return postProcess(activity, ognlContext, value);
1✔
164
        } catch (Exception e) {
×
165
            throw new ExpressionEvaluationException(getExpressionString(), e);
×
166
        }
167
    }
168

169
    private void preProcess(Activity activity, OgnlContext ognlContext) {
170
        if (hasTokenVars()) {
1✔
171
            TokenEvaluator tokenEvaluator = activity.getTokenEvaluator();
1✔
172
            resolveTokenVariables(ognlContext, tokenEvaluator);
1✔
173
        }
174
    }
1✔
175

176
    private Object postProcess(Activity activity, OgnlContext ognlContext, Object value) {
177
        if (getTokenVarNames() != null && value instanceof String str) {
1✔
178
            for (String tokenVarName : getTokenVarNames()) {
1✔
179
                String tokenVarRefName = createTokenVarRefName(tokenVarName);
1✔
180
                if (str.contains(tokenVarRefName)) {
1✔
181
                    Object tokenValue = ognlContext.get(tokenVarName);
1✔
182
                    String replacement;
183
                    if (tokenValue != null) {
1✔
184
                        replacement = ToStringBuilder.toString(tokenValue, activity.getStringifyContext());
1✔
185
                    } else {
186
                        replacement = StringUtils.EMPTY;
1✔
187
                    }
188
                    str = str.replace(tokenVarRefName, replacement);
1✔
189
                }
190
            }
1✔
191
            return str;
1✔
192
        } else {
193
            return value;
1✔
194
        }
195
    }
196

197
    private void resolveTokenVariables(OgnlContext ognlContext, TokenEvaluator tokenEvaluator) {
198
        for (Map.Entry<String, Token> entry : tokenVars.entrySet()) {
1✔
199
            String tokenVarName = entry.getKey();
1✔
200
            Token token = entry.getValue();
1✔
201
            Object value = tokenEvaluator.evaluate(token);
1✔
202
            ognlContext.put(tokenVarName, value);
1✔
203
        }
1✔
204
    }
1✔
205

206
    @NonNull
207
    private static String createTokenVarName(Token token) {
208
        return TOKEN_VAR_NAME_PREFIX + createTokenName(token) + TOKEN_VAR_NAME_SUFFIX;
1✔
209
    }
210

211
    @NonNull
212
    private static String createTokenVarRefName(String tokenVarName) {
213
        return TOKEN_VAR_REF_SYMBOL + tokenVarName;
1✔
214
    }
215

216
    @NonNull
217
    private static String createTokenName(@NonNull Token token) {
218
        int hashCode = token.hashCode();
1✔
219
        if (hashCode >= 0) {
1✔
220
            return Long.toString(hashCode, 32);
1✔
221
        } else {
222
            return Long.toString(hashCode & 0x7fffffff, 32);
×
223
        }
224
    }
225

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

© 2025 Coveralls, Inc