1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.jxpath.ri.compiler;
18
19 import java.text.DecimalFormat;
20 import java.text.DecimalFormatSymbols;
21 import java.text.NumberFormat;
22 import java.util.Collection;
23 import java.util.Locale;
24
25 import org.apache.commons.jxpath.BasicNodeSet;
26 import org.apache.commons.jxpath.JXPathContext;
27 import org.apache.commons.jxpath.JXPathException;
28 import org.apache.commons.jxpath.JXPathInvalidSyntaxException;
29 import org.apache.commons.jxpath.NodeSet;
30 import org.apache.commons.jxpath.ri.Compiler;
31 import org.apache.commons.jxpath.ri.EvalContext;
32 import org.apache.commons.jxpath.ri.InfoSetUtil;
33 import org.apache.commons.jxpath.ri.axes.NodeSetContext;
34 import org.apache.commons.jxpath.ri.model.NodePointer;
35
36
37
38
39
40
41
42
43 public class CoreFunction extends Operation {
44
45 private static final Double ZERO = new Double(0);
46 private int functionCode;
47
48
49
50
51
52
53 public CoreFunction(int functionCode, Expression[] args) {
54 super(args);
55 this.functionCode = functionCode;
56 }
57
58
59
60
61
62 public int getFunctionCode() {
63 return functionCode;
64 }
65
66
67
68
69
70 protected String getFunctionName() {
71 switch (functionCode) {
72 case Compiler.FUNCTION_LAST :
73 return "last";
74 case Compiler.FUNCTION_POSITION :
75 return "position";
76 case Compiler.FUNCTION_COUNT :
77 return "count";
78 case Compiler.FUNCTION_ID :
79 return "id";
80 case Compiler.FUNCTION_LOCAL_NAME :
81 return "local-name";
82 case Compiler.FUNCTION_NAMESPACE_URI :
83 return "namespace-uri";
84 case Compiler.FUNCTION_NAME :
85 return "name";
86 case Compiler.FUNCTION_STRING :
87 return "string";
88 case Compiler.FUNCTION_CONCAT :
89 return "concat";
90 case Compiler.FUNCTION_STARTS_WITH :
91 return "starts-with";
92 case Compiler.FUNCTION_ENDS_WITH :
93 return "ends-with";
94 case Compiler.FUNCTION_CONTAINS :
95 return "contains";
96 case Compiler.FUNCTION_SUBSTRING_BEFORE :
97 return "substring-before";
98 case Compiler.FUNCTION_SUBSTRING_AFTER :
99 return "substring-after";
100 case Compiler.FUNCTION_SUBSTRING :
101 return "substring";
102 case Compiler.FUNCTION_STRING_LENGTH :
103 return "string-length";
104 case Compiler.FUNCTION_NORMALIZE_SPACE :
105 return "normalize-space";
106 case Compiler.FUNCTION_TRANSLATE :
107 return "translate";
108 case Compiler.FUNCTION_BOOLEAN :
109 return "boolean";
110 case Compiler.FUNCTION_NOT :
111 return "not";
112 case Compiler.FUNCTION_TRUE :
113 return "true";
114 case Compiler.FUNCTION_FALSE :
115 return "false";
116 case Compiler.FUNCTION_LANG :
117 return "lang";
118 case Compiler.FUNCTION_NUMBER :
119 return "number";
120 case Compiler.FUNCTION_SUM :
121 return "sum";
122 case Compiler.FUNCTION_FLOOR :
123 return "floor";
124 case Compiler.FUNCTION_CEILING :
125 return "ceiling";
126 case Compiler.FUNCTION_ROUND :
127 return "round";
128 case Compiler.FUNCTION_KEY :
129 return "key";
130 case Compiler.FUNCTION_FORMAT_NUMBER:
131 return "format-number";
132 default:
133 return "unknownFunction" + functionCode + "()";
134 }
135 }
136
137
138
139
140
141 public Expression getArg1() {
142 return args[0];
143 }
144
145
146
147
148
149 public Expression getArg2() {
150 return args[1];
151 }
152
153
154
155
156
157 public Expression getArg3() {
158 return args[2];
159 }
160
161
162
163
164
165 public int getArgumentCount() {
166 if (args == null) {
167 return 0;
168 }
169 return args.length;
170 }
171
172
173
174
175
176
177
178 public boolean computeContextDependent() {
179 if (super.computeContextDependent()) {
180 return true;
181 }
182
183 switch (functionCode) {
184 case Compiler.FUNCTION_LAST:
185 case Compiler.FUNCTION_POSITION:
186 return true;
187
188 case Compiler.FUNCTION_BOOLEAN:
189 case Compiler.FUNCTION_LOCAL_NAME:
190 case Compiler.FUNCTION_NAME:
191 case Compiler.FUNCTION_NAMESPACE_URI:
192 case Compiler.FUNCTION_STRING:
193 case Compiler.FUNCTION_LANG:
194 case Compiler.FUNCTION_NUMBER:
195 return args == null || args.length == 0;
196
197 case Compiler.FUNCTION_FORMAT_NUMBER:
198 return args != null && args.length == 2;
199
200 case Compiler.FUNCTION_COUNT:
201 case Compiler.FUNCTION_ID:
202 case Compiler.FUNCTION_CONCAT:
203 case Compiler.FUNCTION_STARTS_WITH:
204 case Compiler.FUNCTION_ENDS_WITH:
205 case Compiler.FUNCTION_CONTAINS:
206 case Compiler.FUNCTION_SUBSTRING_BEFORE:
207 case Compiler.FUNCTION_SUBSTRING_AFTER:
208 case Compiler.FUNCTION_SUBSTRING:
209 case Compiler.FUNCTION_STRING_LENGTH:
210 case Compiler.FUNCTION_NORMALIZE_SPACE:
211 case Compiler.FUNCTION_TRANSLATE:
212 case Compiler.FUNCTION_NOT:
213 case Compiler.FUNCTION_TRUE:
214 case Compiler.FUNCTION_FALSE:
215 case Compiler.FUNCTION_SUM:
216 case Compiler.FUNCTION_FLOOR:
217 case Compiler.FUNCTION_CEILING:
218 case Compiler.FUNCTION_ROUND:
219 default:
220 return false;
221 }
222 }
223
224 public String toString() {
225 StringBuffer buffer = new StringBuffer();
226 buffer.append(getFunctionName());
227 buffer.append('(');
228 Expression[] args = getArguments();
229 if (args != null) {
230 for (int i = 0; i < args.length; i++) {
231 if (i > 0) {
232 buffer.append(", ");
233 }
234 buffer.append(args[i]);
235 }
236 }
237 buffer.append(')');
238 return buffer.toString();
239 }
240
241 public Object compute(EvalContext context) {
242 return computeValue(context);
243 }
244
245 public Object computeValue(EvalContext context) {
246 switch (functionCode) {
247 case Compiler.FUNCTION_LAST :
248 return functionLast(context);
249 case Compiler.FUNCTION_POSITION :
250 return functionPosition(context);
251 case Compiler.FUNCTION_COUNT :
252 return functionCount(context);
253 case Compiler.FUNCTION_LANG :
254 return functionLang(context);
255 case Compiler.FUNCTION_ID :
256 return functionID(context);
257 case Compiler.FUNCTION_LOCAL_NAME :
258 return functionLocalName(context);
259 case Compiler.FUNCTION_NAMESPACE_URI :
260 return functionNamespaceURI(context);
261 case Compiler.FUNCTION_NAME :
262 return functionName(context);
263 case Compiler.FUNCTION_STRING :
264 return functionString(context);
265 case Compiler.FUNCTION_CONCAT :
266 return functionConcat(context);
267 case Compiler.FUNCTION_STARTS_WITH :
268 return functionStartsWith(context);
269 case Compiler.FUNCTION_ENDS_WITH :
270 return functionEndsWith(context);
271 case Compiler.FUNCTION_CONTAINS :
272 return functionContains(context);
273 case Compiler.FUNCTION_SUBSTRING_BEFORE :
274 return functionSubstringBefore(context);
275 case Compiler.FUNCTION_SUBSTRING_AFTER :
276 return functionSubstringAfter(context);
277 case Compiler.FUNCTION_SUBSTRING :
278 return functionSubstring(context);
279 case Compiler.FUNCTION_STRING_LENGTH :
280 return functionStringLength(context);
281 case Compiler.FUNCTION_NORMALIZE_SPACE :
282 return functionNormalizeSpace(context);
283 case Compiler.FUNCTION_TRANSLATE :
284 return functionTranslate(context);
285 case Compiler.FUNCTION_BOOLEAN :
286 return functionBoolean(context);
287 case Compiler.FUNCTION_NOT :
288 return functionNot(context);
289 case Compiler.FUNCTION_TRUE :
290 return functionTrue(context);
291 case Compiler.FUNCTION_FALSE :
292 return functionFalse(context);
293 case Compiler.FUNCTION_NULL :
294 return functionNull(context);
295 case Compiler.FUNCTION_NUMBER :
296 return functionNumber(context);
297 case Compiler.FUNCTION_SUM :
298 return functionSum(context);
299 case Compiler.FUNCTION_FLOOR :
300 return functionFloor(context);
301 case Compiler.FUNCTION_CEILING :
302 return functionCeiling(context);
303 case Compiler.FUNCTION_ROUND :
304 return functionRound(context);
305 case Compiler.FUNCTION_KEY :
306 return functionKey(context);
307 case Compiler.FUNCTION_FORMAT_NUMBER :
308 return functionFormatNumber(context);
309 default:
310 return null;
311 }
312 }
313
314
315
316
317
318
319 protected Object functionLast(EvalContext context) {
320 assertArgCount(0);
321
322
323 int old = context.getCurrentPosition();
324 context.reset();
325 int count = 0;
326 while (context.nextNode()) {
327 count++;
328 }
329
330
331 if (old != 0) {
332 context.setPosition(old);
333 }
334 return new Double(count);
335 }
336
337
338
339
340
341
342 protected Object functionPosition(EvalContext context) {
343 assertArgCount(0);
344 return new Integer(context.getCurrentPosition());
345 }
346
347
348
349
350
351
352 protected Object functionCount(EvalContext context) {
353 assertArgCount(1);
354 Expression arg1 = getArg1();
355 int count = 0;
356 Object value = arg1.compute(context);
357 if (value instanceof NodePointer) {
358 value = ((NodePointer) value).getValue();
359 }
360 if (value instanceof EvalContext) {
361 EvalContext ctx = (EvalContext) value;
362 while (ctx.hasNext()) {
363 ctx.next();
364 count++;
365 }
366 }
367 else if (value instanceof Collection) {
368 count = ((Collection) value).size();
369 }
370 else if (value == null) {
371 count = 0;
372 }
373 else {
374 count = 1;
375 }
376 return new Double(count);
377 }
378
379
380
381
382
383
384 protected Object functionLang(EvalContext context) {
385 assertArgCount(1);
386 String lang = InfoSetUtil.stringValue(getArg1().computeValue(context));
387 NodePointer pointer = (NodePointer) context.getSingleNodePointer();
388 if (pointer == null) {
389 return Boolean.FALSE;
390 }
391 return pointer.isLanguage(lang) ? Boolean.TRUE : Boolean.FALSE;
392 }
393
394
395
396
397
398
399 protected Object functionID(EvalContext context) {
400 assertArgCount(1);
401 String id = InfoSetUtil.stringValue(getArg1().computeValue(context));
402 JXPathContext jxpathContext = context.getJXPathContext();
403 NodePointer pointer = (NodePointer) jxpathContext.getContextPointer();
404 return pointer.getPointerByID(jxpathContext, id);
405 }
406
407
408
409
410
411
412 protected Object functionKey(EvalContext context) {
413 assertArgCount(2);
414 String key = InfoSetUtil.stringValue(getArg1().computeValue(context));
415 Object value = getArg2().compute(context);
416 EvalContext ec = null;
417 if (value instanceof EvalContext) {
418 ec = (EvalContext) value;
419 if (ec.hasNext()) {
420 value = ((NodePointer) ec.next()).getValue();
421 }
422 else {
423 return new NodeSetContext(context, new BasicNodeSet());
424 }
425 }
426 JXPathContext jxpathContext = context.getJXPathContext();
427 NodeSet nodeSet = jxpathContext.getNodeSetByKey(key, value);
428 if (ec != null && ec.hasNext()) {
429 BasicNodeSet accum = new BasicNodeSet();
430 accum.add(nodeSet);
431 while (ec.hasNext()) {
432 value = ((NodePointer) ec.next()).getValue();
433 accum.add(jxpathContext.getNodeSetByKey(key, value));
434 }
435 nodeSet = accum;
436 }
437 return new NodeSetContext(context, nodeSet);
438 }
439
440
441
442
443
444
445 protected Object functionNamespaceURI(EvalContext context) {
446 if (getArgumentCount() == 0) {
447 NodePointer ptr = context.getCurrentNodePointer();
448 String str = ptr.getNamespaceURI();
449 return str == null ? "" : str;
450 }
451 assertArgCount(1);
452 Object set = getArg1().compute(context);
453 if (set instanceof EvalContext) {
454 EvalContext ctx = (EvalContext) set;
455 if (ctx.hasNext()) {
456 NodePointer ptr = (NodePointer) ctx.next();
457 String str = ptr.getNamespaceURI();
458 return str == null ? "" : str;
459 }
460 }
461 return "";
462 }
463
464
465
466
467
468
469 protected Object functionLocalName(EvalContext context) {
470 if (getArgumentCount() == 0) {
471 NodePointer ptr = context.getCurrentNodePointer();
472 return ptr.getName().getName();
473 }
474 assertArgCount(1);
475 Object set = getArg1().compute(context);
476 if (set instanceof EvalContext) {
477 EvalContext ctx = (EvalContext) set;
478 if (ctx.hasNext()) {
479 NodePointer ptr = (NodePointer) ctx.next();
480 return ptr.getName().getName();
481 }
482 }
483 return "";
484 }
485
486
487
488
489
490
491 protected Object functionName(EvalContext context) {
492 if (getArgumentCount() == 0) {
493 NodePointer ptr = context.getCurrentNodePointer();
494 return ptr.getName().toString();
495 }
496 assertArgCount(1);
497 Object set = getArg1().compute(context);
498 if (set instanceof EvalContext) {
499 EvalContext ctx = (EvalContext) set;
500 if (ctx.hasNext()) {
501 NodePointer ptr = (NodePointer) ctx.next();
502 return ptr.getName().toString();
503 }
504 }
505 return "";
506 }
507
508
509
510
511
512
513 protected Object functionString(EvalContext context) {
514 if (getArgumentCount() == 0) {
515 return InfoSetUtil.stringValue(context.getCurrentNodePointer());
516 }
517 assertArgCount(1);
518 return InfoSetUtil.stringValue(getArg1().computeValue(context));
519 }
520
521
522
523
524
525
526 protected Object functionConcat(EvalContext context) {
527 if (getArgumentCount() < 2) {
528 assertArgCount(2);
529 }
530 StringBuffer buffer = new StringBuffer();
531 Expression[] args = getArguments();
532 for (int i = 0; i < args.length; i++) {
533 buffer.append(InfoSetUtil.stringValue(args[i].compute(context)));
534 }
535 return buffer.toString();
536 }
537
538
539
540
541
542
543 protected Object functionStartsWith(EvalContext context) {
544 assertArgCount(2);
545 String s1 = InfoSetUtil.stringValue(getArg1().computeValue(context));
546 String s2 = InfoSetUtil.stringValue(getArg2().computeValue(context));
547 return s1.startsWith(s2) ? Boolean.TRUE : Boolean.FALSE;
548 }
549
550
551
552
553
554
555
556 protected Object functionEndsWith(EvalContext context) {
557 assertArgCount(2);
558 String s1 = InfoSetUtil.stringValue(getArg1().computeValue(context));
559 String s2 = InfoSetUtil.stringValue(getArg2().computeValue(context));
560 return s1.endsWith(s2) ? Boolean.TRUE : Boolean.FALSE;
561 }
562
563
564
565
566
567
568 protected Object functionContains(EvalContext context) {
569 assertArgCount(2);
570 String s1 = InfoSetUtil.stringValue(getArg1().computeValue(context));
571 String s2 = InfoSetUtil.stringValue(getArg2().computeValue(context));
572 return s1.indexOf(s2) != -1 ? Boolean.TRUE : Boolean.FALSE;
573 }
574
575
576
577
578
579
580 protected Object functionSubstringBefore(EvalContext context) {
581 assertArgCount(2);
582 String s1 = InfoSetUtil.stringValue(getArg1().computeValue(context));
583 String s2 = InfoSetUtil.stringValue(getArg2().computeValue(context));
584 int index = s1.indexOf(s2);
585 if (index == -1) {
586 return "";
587 }
588 return s1.substring(0, index);
589 }
590
591
592
593
594
595
596 protected Object functionSubstringAfter(EvalContext context) {
597 assertArgCount(2);
598 String s1 = InfoSetUtil.stringValue(getArg1().computeValue(context));
599 String s2 = InfoSetUtil.stringValue(getArg2().computeValue(context));
600 int index = s1.indexOf(s2);
601 if (index == -1) {
602 return "";
603 }
604 return s1.substring(index + s2.length());
605 }
606
607
608
609
610
611
612 protected Object functionSubstring(EvalContext context) {
613 final int minArgs = 2;
614 final int maxArgs = 3;
615 assertArgRange(minArgs, maxArgs);
616 int ac = getArgumentCount();
617
618 String s1 = InfoSetUtil.stringValue(getArg1().computeValue(context));
619 double from = InfoSetUtil.doubleValue(getArg2().computeValue(context));
620 if (Double.isNaN(from)) {
621 return "";
622 }
623
624 from = Math.round(from);
625 if (from > s1.length() + 1) {
626 return "";
627 }
628 if (ac == 2) {
629 if (from < 1) {
630 from = 1;
631 }
632 return s1.substring((int) from - 1);
633 }
634 double length =
635 InfoSetUtil.doubleValue(getArg3().computeValue(context));
636 length = Math.round(length);
637 if (length < 0) {
638 return "";
639 }
640
641 double to = from + length;
642 if (to < 1) {
643 return "";
644 }
645
646 if (to > s1.length() + 1) {
647 if (from < 1) {
648 from = 1;
649 }
650 return s1.substring((int) from - 1);
651 }
652
653 if (from < 1) {
654 from = 1;
655 }
656 return s1.substring((int) from - 1, (int) (to - 1));
657 }
658
659
660
661
662
663
664 protected Object functionStringLength(EvalContext context) {
665 String s;
666 if (getArgumentCount() == 0) {
667 s = InfoSetUtil.stringValue(context.getCurrentNodePointer());
668 }
669 else {
670 assertArgCount(1);
671 s = InfoSetUtil.stringValue(getArg1().computeValue(context));
672 }
673 return new Double(s.length());
674 }
675
676
677
678
679
680
681 protected Object functionNormalizeSpace(EvalContext context) {
682 assertArgCount(1);
683 String s = InfoSetUtil.stringValue(getArg1().computeValue(context));
684 char[] chars = s.toCharArray();
685 int out = 0;
686 int phase = 0;
687 for (int in = 0; in < chars.length; in++) {
688 switch (chars[in]) {
689 case ' ':
690 case '\t':
691 case '\r':
692 case '\n':
693 if (phase == 1) {
694 phase = 2;
695 chars[out++] = ' ';
696 }
697 break;
698 default:
699 chars[out++] = chars[in];
700 phase = 1;
701 }
702 }
703 if (phase == 2) {
704 out--;
705 }
706 return new String(chars, 0, out);
707 }
708
709
710
711
712
713
714 protected Object functionTranslate(EvalContext context) {
715 final int argCount = 3;
716 assertArgCount(argCount);
717 String s1 = InfoSetUtil.stringValue(getArg1().computeValue(context));
718 String s2 = InfoSetUtil.stringValue(getArg2().computeValue(context));
719 String s3 = InfoSetUtil.stringValue(getArg3().computeValue(context));
720 char[] chars = s1.toCharArray();
721 int out = 0;
722 for (int in = 0; in < chars.length; in++) {
723 char c = chars[in];
724 int inx = s2.indexOf(c);
725 if (inx != -1) {
726 if (inx < s3.length()) {
727 chars[out++] = s3.charAt(inx);
728 }
729 }
730 else {
731 chars[out++] = c;
732 }
733 }
734 return new String(chars, 0, out);
735 }
736
737
738
739
740
741
742 protected Object functionBoolean(EvalContext context) {
743 assertArgCount(1);
744 return InfoSetUtil.booleanValue(getArg1().computeValue(context))
745 ? Boolean.TRUE
746 : Boolean.FALSE;
747 }
748
749
750
751
752
753
754 protected Object functionNot(EvalContext context) {
755 assertArgCount(1);
756 return InfoSetUtil.booleanValue(getArg1().computeValue(context))
757 ? Boolean.FALSE
758 : Boolean.TRUE;
759 }
760
761
762
763
764
765
766 protected Object functionTrue(EvalContext context) {
767 assertArgCount(0);
768 return Boolean.TRUE;
769 }
770
771
772
773
774
775
776 protected Object functionFalse(EvalContext context) {
777 assertArgCount(0);
778 return Boolean.FALSE;
779 }
780
781
782
783
784
785
786 protected Object functionNull(EvalContext context) {
787 assertArgCount(0);
788 return null;
789 }
790
791
792
793
794
795
796 protected Object functionNumber(EvalContext context) {
797 if (getArgumentCount() == 0) {
798 return InfoSetUtil.number(context.getCurrentNodePointer());
799 }
800 assertArgCount(1);
801 return InfoSetUtil.number(getArg1().computeValue(context));
802 }
803
804
805
806
807
808
809 protected Object functionSum(EvalContext context) {
810 assertArgCount(1);
811 Object v = getArg1().compute(context);
812 if (v == null) {
813 return ZERO;
814 }
815 if (v instanceof EvalContext) {
816 double sum = 0.0;
817 EvalContext ctx = (EvalContext) v;
818 while (ctx.hasNext()) {
819 NodePointer ptr = (NodePointer) ctx.next();
820 sum += InfoSetUtil.doubleValue(ptr);
821 }
822 return new Double(sum);
823 }
824 throw new JXPathException(
825 "Invalid argument type for 'sum': " + v.getClass().getName());
826 }
827
828
829
830
831
832
833 protected Object functionFloor(EvalContext context) {
834 assertArgCount(1);
835 double v = InfoSetUtil.doubleValue(getArg1().computeValue(context));
836 if (Double.isNaN(v) || Double.isInfinite(v)) {
837 return new Double(v);
838 }
839 return new Double(Math.floor(v));
840 }
841
842
843
844
845
846
847 protected Object functionCeiling(EvalContext context) {
848 assertArgCount(1);
849 double v = InfoSetUtil.doubleValue(getArg1().computeValue(context));
850 if (Double.isNaN(v) || Double.isInfinite(v)) {
851 return new Double(v);
852 }
853 return new Double(Math.ceil(v));
854 }
855
856
857
858
859
860
861 protected Object functionRound(EvalContext context) {
862 assertArgCount(1);
863 double v = InfoSetUtil.doubleValue(getArg1().computeValue(context));
864 if (Double.isNaN(v) || Double.isInfinite(v)) {
865 return new Double(v);
866 }
867 return new Double(Math.round(v));
868 }
869
870
871
872
873
874
875 private Object functionFormatNumber(EvalContext context) {
876 final int minArgs = 2;
877 final int maxArgs = 3;
878 assertArgRange(minArgs, maxArgs);
879
880 double number =
881 InfoSetUtil.doubleValue(getArg1().computeValue(context));
882 String pattern =
883 InfoSetUtil.stringValue(getArg2().computeValue(context));
884
885 DecimalFormatSymbols symbols = null;
886 if (getArgumentCount() == maxArgs) {
887 String symbolsName =
888 InfoSetUtil.stringValue(getArg3().computeValue(context));
889 symbols =
890 context.getJXPathContext().getDecimalFormatSymbols(symbolsName);
891 }
892 else {
893 NodePointer pointer = context.getCurrentNodePointer();
894 Locale locale;
895 if (pointer != null) {
896 locale = pointer.getLocale();
897 }
898 else {
899 locale = context.getJXPathContext().getLocale();
900 }
901 symbols = new DecimalFormatSymbols(locale);
902 }
903
904 DecimalFormat format = (DecimalFormat) NumberFormat.getInstance();
905 format.setDecimalFormatSymbols(symbols);
906 format.applyLocalizedPattern(pattern);
907 return format.format(number);
908 }
909
910
911
912
913
914 private void assertArgCount(int count) {
915 assertArgRange(count, count);
916 }
917
918
919
920
921
922
923 private void assertArgRange(int min, int max) {
924 int ct = getArgumentCount();
925 if (ct < min || ct > max) {
926 throw new JXPathInvalidSyntaxException(
927 "Incorrect number of arguments: " + this);
928 }
929 }
930 }