1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.jexl2;
18
19 import java.math.MathContext;
20
21 /**
22 * A derived arithmetic that allows different threads to operate with
23 * different strict/lenient/math modes using the same JexlEngine.
24 * @since 2.1
25 */
26 public class JexlThreadedArithmetic extends JexlArithmetic {
27
28 /** Holds the threaded version of some arithmetic features. */
29 static class Features {
30 /** Default ctor. */
31 Features() {}
32 /** Whether this JexlArithmetic instance behaves in strict or lenient mode. */
33 private Boolean lenient = null;
34 /** The big decimal math context. */
35 private MathContext mathContext = null;
36 /** The big decimal scale. */
37 private Integer mathScale = null;
38 }
39
40 /**
41 * Standard ctor.
42 * @param lenient lenient versus strict evaluation flag
43 */
44 public JexlThreadedArithmetic(boolean lenient) {
45 super(lenient);
46 }
47
48 /**
49 * Creates a JexlThreadedArithmetic instance.
50 * @param lenient whether this arithmetic is lenient or strict
51 * @param bigdContext the math context instance to use for +,-,/,*,% operations on big decimals.
52 * @param bigdScale the scale used for big decimals.
53 */
54 public JexlThreadedArithmetic(boolean lenient, MathContext bigdContext, int bigdScale) {
55 super(lenient, bigdContext, bigdScale);
56 }
57
58 /** Whether this JexlArithmetic instance behaves in strict or lenient mode for this thread. */
59 static final ThreadLocal<Features> FEATURES = new ThreadLocal<Features>() {
60 @Override
61 protected synchronized Features initialValue() {
62 return new Features();
63 }
64 };
65
66
67 /**
68 * Overrides the default behavior and sets whether this JexlArithmetic instance triggers errors
69 * during evaluation when null is used as an operand for the current thread.
70 * <p>It is advised to protect calls by either calling JexlThreadedArithmetic.setLenient explicitly
71 * before evaluation or add a try/finally clause resetting the flag to avoid unexpected reuse of the lenient
72 * flag value through thread pools side-effects.</p>
73 * @see JexlEngine#setSilent
74 * @see JexlEngine#setDebug
75 * @param flag true means no JexlException will occur, false allows them, null reverts to default behavior
76 */
77 public static void setLenient(Boolean flag) {
78 FEATURES.get().lenient = flag;
79 }
80
81 /**
82 * Sets the math scale.
83 * <p>The goal and constraints are the same than for setLenient.</p>
84 * @param scale the scale
85 */
86 public static void setMathScale(Integer scale) {
87 FEATURES.get().mathScale = scale;
88 }
89
90 /**
91 * Sets the math context.
92 * <p>The goal and constraints are the same than for setLenient.</p>
93 * @param mc the math context
94 */
95 public static void setMathContext(MathContext mc) {
96 FEATURES.get().mathContext = mc;
97 }
98
99 /** {@inheritDoc} */
100 @Override
101 public boolean isLenient() {
102 Boolean lenient = FEATURES.get().lenient;
103 return lenient == null ? super.isLenient() : lenient.booleanValue();
104 }
105
106 @Override
107 public int getMathScale() {
108 Integer scale = FEATURES.get().mathScale;
109 return scale == null ? super.getMathScale() : scale.intValue();
110 }
111
112 @Override
113 public MathContext getMathContext() {
114 MathContext mc = FEATURES.get().mathContext;
115 return mc == null? super.getMathContext() : mc;
116 }
117 }