1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.jexl3.internal;
18
19 import org.apache.commons.jexl3.JexlContext;
20 import org.apache.commons.jexl3.JexlOptions;
21 import org.apache.commons.jexl3.parser.ASTJexlLambda;
22
23 import java.util.Arrays;
24 import java.util.Objects;
25
26
27
28
29 public class Closure extends Script {
30
31 protected final Frame frame;
32
33 protected final JexlOptions options;
34
35
36
37
38
39
40 protected Closure(final Interpreter theCaller, final ASTJexlLambda lambda) {
41 super(theCaller.jexl, null, lambda);
42 frame = lambda.createFrame(theCaller.frame);
43 final JexlOptions callerOptions = theCaller.options;
44 options = callerOptions != null ? callerOptions.copy() : null;
45 }
46
47
48
49
50
51
52 protected Closure(final Script base, final Object[] args) {
53 super(base.jexl, base.source, base.script);
54 final Frame sf = (base instanceof Closure) ? ((Closure) base).frame : null;
55 frame = sf == null
56 ? script.createFrame(args)
57 : sf.assign(args);
58 JexlOptions closureOptions = null;
59 if (base instanceof Closure) {
60 closureOptions = ((Closure) base).options;
61 }
62 options = closureOptions != null ? closureOptions.copy() : null;
63 }
64
65 @Override
66 public int hashCode() {
67
68 int hash = 17;
69 hash = 31 * hash + Objects.hashCode(jexl);
70 hash = 31 * hash + Objects.hashCode(source);
71 hash = 31 * hash + (frame != null ? Arrays.deepHashCode(frame.nocycleStack(this)) : 0);
72
73 return hash;
74 }
75
76 @Override
77 public boolean equals(final Object obj) {
78 if (obj == null) {
79 return false;
80 }
81 if (getClass() != obj.getClass()) {
82 return false;
83 }
84 final Closure other = (Closure) obj;
85 if (this.jexl != other.jexl) {
86 return false;
87 }
88 if (!Objects.equals(this.source, other.source)) {
89 return false;
90 }
91 if (this.frame == other.frame) {
92 return true;
93 }
94 return Arrays.deepEquals(
95 this.frame.nocycleStack(this),
96 other.frame.nocycleStack(other));
97 }
98
99 @Override
100 public String[] getUnboundParameters() {
101 return frame.getUnboundParameters();
102 }
103
104
105
106
107
108
109
110
111
112
113 public void setCaptured(final int symbol, final Object value) {
114 if (script instanceof ASTJexlLambda) {
115 final ASTJexlLambda lambda = (ASTJexlLambda) script;
116 final Scope scope = lambda.getScope();
117 if (scope != null) {
118 final Integer reg = scope.getCaptured(symbol);
119 if (reg != null) {
120 frame.set(reg, value);
121 }
122 }
123 }
124 }
125
126 @Override
127 public Object evaluate(final JexlContext context) {
128 return execute(context, (Object[])null);
129 }
130
131 @Override
132 public Object execute(final JexlContext context) {
133 return execute(context, (Object[])null);
134 }
135
136 @Override
137 public Object execute(final JexlContext context, final Object... args) {
138 final Frame local = frame != null? frame.assign(args) : null;
139 final Interpreter interpreter = createInterpreter(context, local, options);
140 return interpreter.runClosure(this, null);
141 }
142
143 @Override
144 public Callable callable(final JexlContext context, final Object... args) {
145 final Frame local = frame != null? frame.assign(args) : null;
146 return new Callable(createInterpreter(context, local, options)) {
147 @Override
148 public Object interpret() {
149 return interpreter.runClosure(Closure.this, null);
150 }
151 };
152 }
153 }