Skip to content

Commit c26eae1

Browse files
committed
[ignore] cleanup of UserDefinedFunction
- make variables final - reorder methods - add code to XPathException constructor - add annotations - fix formatting
1 parent d50ccf7 commit c26eae1

File tree

1 file changed

+153
-161
lines changed

1 file changed

+153
-161
lines changed

exist-core/src/main/java/org/exist/xquery/UserDefinedFunction.java

Lines changed: 153 additions & 161 deletions
Original file line numberDiff line numberDiff line change
@@ -35,133 +35,127 @@
3535
*/
3636
public class UserDefinedFunction extends Function implements Cloneable {
3737

38-
private Expression body;
39-
40-
private List<QName> parameters = new ArrayList<>(5);
41-
42-
private Sequence[] currentArguments = null;
43-
38+
private final List<QName> parameters = new ArrayList<>(5);
39+
protected boolean visited = false;
40+
private Expression body;
41+
private Sequence[] currentArguments = null;
4442
private DocumentSet[] contextDocs = null;
45-
4643
private boolean bodyAnalyzed = false;
47-
4844
private FunctionCall call;
49-
5045
private boolean hasBeenReset = false;
51-
52-
protected boolean visited = false;
53-
5446
private List<ClosureVariable> closureVariables = null;
55-
56-
public UserDefinedFunction(XQueryContext context, FunctionSignature signature) {
57-
super(context, signature);
58-
}
59-
60-
public void setFunctionBody(Expression body) {
61-
this.body = body.simplify();
62-
}
47+
48+
public UserDefinedFunction(XQueryContext context, FunctionSignature signature) {
49+
super(context, signature);
50+
}
6351

6452
public Expression getFunctionBody() {
6553
return body;
6654
}
67-
55+
56+
public void setFunctionBody(Expression body) {
57+
this.body = body.simplify();
58+
}
59+
6860
public void addVariable(final String varName) throws XPathException {
69-
try {
70-
final QName qname = QName.parse(context, varName, null);
71-
addVariable(qname);
72-
} catch (final QName.IllegalQNameException e) {
73-
throw new XPathException(this, ErrorCodes.XPST0081, "No namespace defined for prefix " + varName);
74-
}
75-
}
76-
61+
try {
62+
final QName qname = QName.parse(context, varName, null);
63+
addVariable(qname);
64+
} catch (final QName.IllegalQNameException e) {
65+
throw new XPathException(this, ErrorCodes.XPST0081, "No namespace defined for prefix " + varName);
66+
}
67+
}
68+
7769
public void addVariable(QName varName) throws XPathException {
78-
if (parameters.contains(varName))
79-
{throw new XPathException(this, "XQST0039: function " + getName() + " is already have parameter with the name "+varName);}
70+
if (parameters.contains(varName)) {
71+
throw new XPathException(this, ErrorCodes.XQST0039, "function " + getName() + " already has a parameter with the name " + varName);
72+
}
8073

81-
parameters.add(varName);
74+
parameters.add(varName);
8275
}
83-
84-
/* (non-Javadoc)
85-
* @see org.exist.xquery.Function#setArguments(java.util.List)
86-
*/
87-
public void setArguments(Sequence[] args, DocumentSet[] contextDocs) throws XPathException {
88-
this.currentArguments = args;
76+
77+
public void setArguments(Sequence[] args, DocumentSet[] contextDocs) throws XPathException {
78+
this.currentArguments = args;
8979
this.contextDocs = contextDocs;
9080
}
91-
92-
/* (non-Javadoc)
93-
* @see org.exist.xquery.Function#analyze(org.exist.xquery.AnalyzeContextInfo)
94-
*/
95-
public void analyze(AnalyzeContextInfo contextInfo) throws XPathException {
96-
hasBeenReset = false;
97-
98-
if(call != null && !call.isRecursive()) {
99-
// Save the local variable stack
100-
final LocalVariable mark = context.markLocalVariables(true);
101-
if (closureVariables != null)
102-
// if this is a inline function, context variables are known
103-
{context.restoreStack(closureVariables);}
104-
try {
105-
LocalVariable var;
106-
for(final QName varName : parameters) {
107-
var = new LocalVariable(varName);
108-
context.declareVariableBinding(var);
109-
}
110-
111-
final AnalyzeContextInfo newContextInfo = new AnalyzeContextInfo(contextInfo);
112-
newContextInfo.setParent(this);
113-
if (!bodyAnalyzed) {
114-
if(body != null) {
115-
body.analyze(newContextInfo);
116-
}
117-
bodyAnalyzed = true;
118-
}
119-
} finally {
120-
// restore the local variable stack
121-
context.popLocalVariables(mark);
122-
}
123-
}
124-
}
125-
126-
/* (non-Javadoc)
127-
* @see org.exist.xquery.Expression#eval(org.exist.dom.persistent.DocumentSet, org.exist.xquery.value.Sequence, org.exist.xquery.value.Item)
128-
*/
129-
public Sequence eval(Sequence contextSequence, Item contextItem) throws XPathException {
81+
82+
@Override
83+
public void analyze(AnalyzeContextInfo contextInfo) throws XPathException {
84+
hasBeenReset = false;
85+
86+
if (call != null && !call.isRecursive()) {
87+
// Save the local variable stack
88+
final LocalVariable mark = context.markLocalVariables(true);
89+
if (closureVariables != null) {
90+
// if this is a inline function, context variables are known
91+
context.restoreStack(closureVariables);
92+
}
93+
try {
94+
LocalVariable var;
95+
for (final QName varName : parameters) {
96+
var = new LocalVariable(varName);
97+
context.declareVariableBinding(var);
98+
}
99+
100+
final AnalyzeContextInfo newContextInfo = new AnalyzeContextInfo(contextInfo);
101+
newContextInfo.setParent(this);
102+
if (!bodyAnalyzed) {
103+
if (body != null) {
104+
body.analyze(newContextInfo);
105+
}
106+
bodyAnalyzed = true;
107+
}
108+
} finally {
109+
// restore the local variable stack
110+
context.popLocalVariables(mark);
111+
}
112+
}
113+
}
114+
115+
@Override
116+
public Sequence eval(Sequence contextSequence, Item contextItem) throws XPathException {
130117
// context.expressionStart(this);
131118
context.stackEnter(this);
132119
// make sure reset state is called after query has finished
133-
hasBeenReset = false;
120+
hasBeenReset = false;
134121
// Save the local variable stack
135122
final LocalVariable mark = context.markLocalVariables(true);
136-
if (closureVariables != null)
137-
{context.restoreStack(closureVariables);}
123+
if (closureVariables != null) {
124+
context.restoreStack(closureVariables);
125+
}
138126
Sequence result = null;
139-
try {
140-
QName varName;
141-
LocalVariable var;
142-
int j = 0;
143-
for (int i = 0; i < parameters.size(); i++, j++) {
144-
varName = parameters.get(i);
145-
var = new LocalVariable(varName);
146-
var.setValue(currentArguments[j]);
147-
if (contextDocs != null)
148-
{var.setContextDocs(contextDocs[i]);}
149-
context.declareVariableBinding(var);
150-
151-
Cardinality actualCardinality;
152-
if (currentArguments[j].isEmpty()) {actualCardinality = Cardinality.EMPTY_SEQUENCE;}
153-
else if (currentArguments[j].hasMany()) {actualCardinality = Cardinality._MANY;}
154-
else {actualCardinality = Cardinality.EXACTLY_ONE;}
155-
156-
if (!getSignature().getArgumentTypes()[j].getCardinality().isSuperCardinalityOrEqualOf(actualCardinality))
157-
{throw new XPathException(this, ErrorCodes.XPTY0004, "Invalid cardinality for parameter $" + varName +
158-
". Expected " + getSignature().getArgumentTypes()[j].getCardinality().getHumanDescription() +
159-
", got " + currentArguments[j].getItemCount());}
160-
}
161-
result = body.eval(null, null);
162-
return result;
163-
} finally {
164-
// restore the local variable stack
127+
try {
128+
QName varName;
129+
LocalVariable var;
130+
int j = 0;
131+
for (int i = 0; i < parameters.size(); i++, j++) {
132+
varName = parameters.get(i);
133+
var = new LocalVariable(varName);
134+
var.setValue(currentArguments[j]);
135+
if (contextDocs != null) {
136+
var.setContextDocs(contextDocs[i]);
137+
}
138+
context.declareVariableBinding(var);
139+
140+
Cardinality actualCardinality;
141+
if (currentArguments[j].isEmpty()) {
142+
actualCardinality = Cardinality.EMPTY_SEQUENCE;
143+
} else if (currentArguments[j].hasMany()) {
144+
actualCardinality = Cardinality._MANY;
145+
} else {
146+
actualCardinality = Cardinality.EXACTLY_ONE;
147+
}
148+
149+
if (!getSignature().getArgumentTypes()[j].getCardinality().isSuperCardinalityOrEqualOf(actualCardinality)) {
150+
throw new XPathException(this, ErrorCodes.XPTY0004, "Invalid cardinality for parameter $" + varName +
151+
". Expected " + getSignature().getArgumentTypes()[j].getCardinality().getHumanDescription() +
152+
", got " + currentArguments[j].getItemCount());
153+
}
154+
}
155+
result = body.eval(null, null);
156+
return result;
157+
} finally {
158+
// restore the local variable stack
165159
context.popLocalVariables(mark, result);
166160
context.stackLeave(this);
167161
// context.expressionEnd(this);
@@ -209,91 +203,89 @@ public String toString() {
209203
buf.append(signature.getReturnType());
210204
return buf.toString();
211205
}
212-
213-
/* (non-Javadoc)
214-
* @see org.exist.xquery.functions.Function#getDependencies()
215-
*/
216-
public int getDependencies() {
217-
return Dependency.CONTEXT_SET + Dependency.CONTEXT_ITEM
218-
+ Dependency.CONTEXT_POSITION;
219-
}
220-
221-
/* (non-Javadoc)
222-
* @see org.exist.xquery.PathExpr#resetState()
223-
*/
224-
public void resetState(boolean postOptimization) {
225-
if (hasBeenReset) {
206+
207+
@Override
208+
public int getDependencies() {
209+
return Dependency.CONTEXT_SET + Dependency.CONTEXT_ITEM
210+
+ Dependency.CONTEXT_POSITION;
211+
}
212+
213+
@Override
214+
public void resetState(boolean postOptimization) {
215+
if (hasBeenReset) {
226216
return;
227217
}
228-
hasBeenReset = true;
229-
230-
super.resetState(postOptimization);
218+
hasBeenReset = true;
219+
220+
super.resetState(postOptimization);
231221
// Question: understand this test. Why not reset even is not in recursion ?
232-
// Answer: would lead to an infinite loop if the function is recursive.
222+
// Answer: would lead to an infinite loop if the function is recursive.
233223
bodyAnalyzed = false;
234-
if(body != null) {
235-
body.resetState(postOptimization);
236-
}
224+
if (body != null) {
225+
body.resetState(postOptimization);
226+
}
237227

238228
if (!postOptimization) {
239229
currentArguments = null;
240230
contextDocs = null;
241231
}
242232
}
243233

234+
@Override
244235
public void accept(ExpressionVisitor visitor) {
245-
if (visited)
246-
{return;}
236+
if (visited) {
237+
return;
238+
}
247239
visited = true;
248240
visitor.visitUserFunction(this);
249241
}
250-
242+
251243
/**
252244
* Return the functions parameters list
253-
*
245+
*
254246
* @return List of function parameters
255247
*/
256-
public List<QName> getParameters()
257-
{
258-
return parameters;
248+
public List<QName> getParameters() {
249+
return parameters;
259250
}
260251

252+
@Override
261253
public synchronized Object clone() {
262-
try {
263-
final UserDefinedFunction clone = (UserDefinedFunction) super.clone();
264-
265-
clone.currentArguments = null;
266-
clone.contextDocs = null;
267-
268-
clone.body = this.body; // so body will be analyzed and optimized for all calls of such functions in recursion.
269-
270-
return clone;
271-
} catch (final CloneNotSupportedException e) {
272-
// this shouldn't happen, since we are Cloneable
273-
throw new InternalError();
274-
}
275-
}
276-
277-
public FunctionCall getCaller(){
278-
return call;
254+
try {
255+
final UserDefinedFunction clone = (UserDefinedFunction) super.clone();
256+
257+
clone.currentArguments = null;
258+
clone.contextDocs = null;
259+
260+
clone.body = this.body; // so body will be analyzed and optimized for all calls of such functions in recursion.
261+
262+
return clone;
263+
} catch (final CloneNotSupportedException e) {
264+
// this shouldn't happen, since we are Cloneable
265+
throw new InternalError();
266+
}
279267
}
280-
281-
public void setCaller(FunctionCall call){
282-
this.call = call;
268+
269+
public FunctionCall getCaller() {
270+
return call;
283271
}
284-
285-
public void setClosureVariables(List<ClosureVariable> vars) {
286-
this.closureVariables = vars;
287-
if (vars != null) {
288-
// register the closure with the context so it gets cleared after execution
289-
context.pushClosure(this);
290-
}
272+
273+
public void setCaller(FunctionCall call) {
274+
this.call = call;
291275
}
292276

293277
public List<ClosureVariable> getClosureVariables() {
294278
return closureVariables;
295279
}
296280

281+
public void setClosureVariables(List<ClosureVariable> vars) {
282+
this.closureVariables = vars;
283+
if (vars != null) {
284+
// register the closure with the context so it gets cleared after execution
285+
context.pushClosure(this);
286+
}
287+
}
288+
297289
protected Sequence[] getCurrentArguments() {
298290
return currentArguments;
299291
}

0 commit comments

Comments
 (0)