View Javadoc

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 }