001: /*
002: $Header: /cvsroot/xorm/xorm/src/org/xorm/query/Expression.java,v 1.10 2004/05/28 15:38:23 wbiggs Exp $
003:
004: This file is part of XORM.
005:
006: XORM is free software; you can redistribute it and/or modify
007: it under the terms of the GNU General Public License as published by
008: the Free Software Foundation; either version 2 of the License, or
009: (at your option) any later version.
010:
011: XORM is distributed in the hope that it will be useful,
012: but WITHOUT ANY WARRANTY; without even the implied warranty of
013: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: GNU General Public License for more details.
015:
016: You should have received a copy of the GNU General Public License
017: along with XORM; if not, write to the Free Software
018: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: */
020: package org.xorm.query;
021:
022: import java.lang.reflect.Field;
023: import java.lang.reflect.Method;
024: import java.lang.reflect.InvocationTargetException;
025:
026: public abstract class Expression {
027: public abstract Object evaluate(QueryContext context);
028:
029: public abstract String toString();
030:
031: public void accept(ExpressionVisitor visitor) {
032: // Default implementation, only override where needed
033: }
034:
035: public abstract Class getType();
036:
037: public static abstract class Binary extends Expression {
038: protected Expression lhs;
039: protected Expression rhs;
040:
041: public Binary(Expression lhs, Expression rhs) {
042: this .lhs = lhs;
043: this .rhs = rhs;
044: }
045:
046: public Expression getLHS() {
047: return lhs;
048: }
049:
050: public Expression getRHS() {
051: return rhs;
052: }
053:
054: /** Returns a String representation of the operator */
055: public abstract Operator operator();
056:
057: public String toString() {
058: return "(" + lhs + " " + operator() + " " + rhs + ")";
059: }
060: }
061:
062: public static abstract class Comparison extends Binary {
063: // Just for declarative purposes, to separate it from Arithmetic
064: public Comparison(Expression lhs, Expression rhs) {
065: super (lhs, rhs);
066: }
067:
068: public Class getType() {
069: return Boolean.class;
070: }
071:
072: public void accept(ExpressionVisitor visitor) {
073: if (!visitor.visitComparison(this ))
074: super .accept(visitor);
075: }
076: }
077:
078: public static class ConditionalOr extends Comparison {
079: public ConditionalOr(Expression lhs, Expression rhs) {
080: super (lhs, rhs);
081: }
082:
083: public Object evaluate(QueryContext context) {
084: Boolean lhv = (Boolean) lhs.evaluate(context);
085: if (lhv.booleanValue())
086: return lhv;
087: return (Boolean) rhs.evaluate(context);
088: }
089:
090: public void accept(ExpressionVisitor visitor) {
091: if (!visitor.visitConditionalOr(this ))
092: super .accept(visitor);
093: }
094:
095: public Operator operator() {
096: return Operator.ORC;
097: }
098: }
099:
100: public static class ConditionalAnd extends Comparison {
101: public ConditionalAnd(Expression lhs, Expression rhs) {
102: super (lhs, rhs);
103: }
104:
105: public Object evaluate(QueryContext context) {
106: Boolean lhv = (Boolean) lhs.evaluate(context);
107: if (lhv.booleanValue()) {
108: return (Boolean) rhs.evaluate(context);
109: }
110: return lhv;
111: }
112:
113: public void accept(ExpressionVisitor visitor) {
114: if (!visitor.visitConditionalAnd(this )) {
115: super .accept(visitor);
116: }
117: }
118:
119: public Operator operator() {
120: return Operator.ANDC;
121: }
122: }
123:
124: public static class InclusiveOr extends Comparison {
125: public InclusiveOr(Expression lhs, Expression rhs) {
126: super (lhs, rhs);
127: }
128:
129: public Object evaluate(QueryContext context) {
130: Boolean lhv = (Boolean) lhs.evaluate(context);
131: Boolean rhv = (Boolean) rhs.evaluate(context);
132: if (lhv.booleanValue() || rhv.booleanValue()) {
133: return Boolean.TRUE;
134: }
135: return Boolean.FALSE;
136: }
137:
138: public Operator operator() {
139: return Operator.ORL;
140: }
141: }
142:
143: public static class And extends Comparison {
144: public And(Expression lhs, Expression rhs) {
145: super (lhs, rhs);
146: }
147:
148: public Object evaluate(QueryContext context) {
149: Boolean lhv = (Boolean) lhs.evaluate(context);
150: Boolean rhv = (Boolean) rhs.evaluate(context);
151: if (lhv.booleanValue() && rhv.booleanValue()) {
152: return Boolean.TRUE;
153: }
154: return Boolean.FALSE;
155: }
156:
157: public void accept(ExpressionVisitor visitor) {
158: if (!visitor.visitAnd(this )) {
159: super .accept(visitor);
160: }
161: }
162:
163: public Operator operator() {
164: return Operator.ANDL;
165: }
166: }
167:
168: public static class ExclusiveOr extends Comparison {
169: public ExclusiveOr(Expression lhs, Expression rhs) {
170: super (lhs, rhs);
171: }
172:
173: public Object evaluate(QueryContext context) {
174: Boolean lhv = (Boolean) lhs.evaluate(context);
175: Boolean rhv = (Boolean) rhs.evaluate(context);
176: if (lhv.booleanValue() ^ rhv.booleanValue()) {
177: return Boolean.TRUE;
178: }
179: return Boolean.FALSE;
180: }
181:
182: public Operator operator() {
183: return Operator.XOR;
184: }
185: }
186:
187: public static class Equal extends Comparison {
188: public Equal(Expression lhs, Expression rhs) {
189: super (lhs, rhs);
190: }
191:
192: public Object evaluate(QueryContext context) {
193: Object lhv = lhs.evaluate(context);
194: Object rhv = rhs.evaluate(context);
195:
196: return (lhv == null) ? Boolean.valueOf(rhv == null)
197: : Boolean.valueOf(lhv.equals(rhv));
198: }
199:
200: public Operator operator() {
201: return Operator.EQUAL;
202: }
203: }
204:
205: public static class NotEqual extends Equal {
206: public NotEqual(Expression lhs, Expression rhs) {
207: super (lhs, rhs);
208: }
209:
210: public Object evaluate(QueryContext context) {
211: return Boolean.TRUE.equals(super .evaluate(context)) ? Boolean.FALSE
212: : Boolean.TRUE;
213: }
214:
215: public Operator operator() {
216: return Operator.NOT_EQUAL;
217: }
218: }
219:
220: public static abstract class Numeric extends Comparison {
221: public Numeric(Expression lhs, Expression rhs) {
222: super (lhs, rhs);
223: }
224:
225: public abstract boolean evaluateCompared(int compareTo);
226:
227: public Object evaluate(QueryContext context) {
228: Object lhv = lhs.evaluate(context);
229: Object rhv = rhs.evaluate(context);
230:
231: if (lhv instanceof Long) {
232: return evaluateCompared(((Long) lhv)
233: .compareTo(new Long(((Number) rhv).longValue()))) ? Boolean.TRUE
234: : Boolean.FALSE;
235: } else if (lhv instanceof Integer) {
236: return evaluateCompared(((Integer) lhv)
237: .compareTo(new Integer(((Number) rhv)
238: .intValue()))) ? Boolean.TRUE
239: : Boolean.FALSE;
240: } else if (lhv instanceof Short) {
241: return evaluateCompared(((Short) lhv)
242: .compareTo(new Short(((Number) rhv)
243: .shortValue()))) ? Boolean.TRUE
244: : Boolean.FALSE;
245: } else if (lhv instanceof Byte) {
246: return evaluateCompared(((Byte) lhv)
247: .compareTo(new Byte(((Number) rhv).byteValue()))) ? Boolean.TRUE
248: : Boolean.FALSE;
249: } else if (lhv instanceof Double) {
250: return evaluateCompared(((Double) lhv)
251: .compareTo(new Double(((Number) rhv)
252: .doubleValue()))) ? Boolean.TRUE
253: : Boolean.FALSE;
254: } else if (lhv instanceof Float) {
255: return evaluateCompared(((Float) lhv)
256: .compareTo(new Float(((Number) rhv)
257: .floatValue()))) ? Boolean.TRUE
258: : Boolean.FALSE;
259: } else if (lhv instanceof Character) {
260: return evaluateCompared(((Character) lhv)
261: .compareTo((Character) rhv)) ? Boolean.TRUE
262: : Boolean.FALSE;
263: }
264: throw new IllegalArgumentException();
265: }
266: }
267:
268: public static class LessThan extends Numeric {
269: public LessThan(Expression lhs, Expression rhs) {
270: super (lhs, rhs);
271: }
272:
273: public boolean evaluateCompared(int i) {
274: return i < 0;
275: }
276:
277: public Operator operator() {
278: return Operator.LT;
279: }
280: }
281:
282: public static class LessThanEqual extends Numeric {
283: public LessThanEqual(Expression lhs, Expression rhs) {
284: super (lhs, rhs);
285: }
286:
287: public boolean evaluateCompared(int i) {
288: return i <= 0;
289: }
290:
291: public Operator operator() {
292: return Operator.LTE;
293: }
294: }
295:
296: public static class GreaterThan extends Numeric {
297: public GreaterThan(Expression lhs, Expression rhs) {
298: super (lhs, rhs);
299: }
300:
301: public boolean evaluateCompared(int i) {
302: return i > 0;
303: }
304:
305: public Operator operator() {
306: return Operator.GT;
307: }
308: }
309:
310: public static class GreaterThanEqual extends Numeric {
311: public GreaterThanEqual(Expression lhs, Expression rhs) {
312: super (lhs, rhs);
313: }
314:
315: public boolean evaluateCompared(int i) {
316: return i >= 0;
317: }
318:
319: public Operator operator() {
320: return Operator.GTE;
321: }
322: }
323:
324: public static class Constant extends Expression {
325: public static final Constant TRUE = new Constant(Boolean.TRUE);
326: public static final Constant FALSE = new Constant(Boolean.FALSE);
327: public static final Constant NULL = new Constant(null);
328:
329: protected Object value;
330:
331: public Constant(Object value) {
332: this .value = value;
333: }
334:
335: public Object evaluate(QueryContext context) {
336: return value;
337: }
338:
339: public Object getValue() {
340: return value;
341: }
342:
343: public Class getType() {
344: if (this == NULL)
345: return null;
346: return value.getClass();
347: }
348:
349: public String toString() {
350: if (this == NULL)
351: return "null";
352: if (value instanceof String) {
353: return escapeString((String) value);
354: } else if (value instanceof Character) {
355: return escapeChar(((Character) value).charValue());
356: }
357: return value.toString();
358: }
359:
360: public void accept(ExpressionVisitor visitor) {
361: if (!visitor.visitConstant(this )) {
362: super .accept(visitor);
363: }
364: }
365: }
366:
367: public abstract static class Symbolic extends Expression {
368: protected String name;
369: protected Class type;
370:
371: public Symbolic(String name, Class type) {
372: this .name = name;
373: this .type = type;
374: }
375:
376: public String getName() {
377: return name;
378: }
379:
380: public Class getType() {
381: return type;
382: }
383:
384: // breaks immutable.. fixme
385: public void setType(Class type) {
386: this .type = type;
387: }
388: }
389:
390: public static class Parameter extends Symbolic {
391: public Parameter(String name, Class type) {
392: super (name, type);
393: }
394:
395: public Object evaluate(QueryContext context) {
396: return context.resolveParameter(name);
397: }
398:
399: public void accept(ExpressionVisitor visitor) {
400: if (!visitor.visitParameter(this )) {
401: super .accept(visitor);
402: }
403: }
404:
405: public String toString() {
406: return name;
407: }
408: }
409:
410: public static class Variable extends Symbolic {
411: public Variable(String name, Class type) {
412: super (name, type);
413: }
414:
415: public Object evaluate(QueryContext context) {
416: return context.resolveVariable(name);
417: }
418:
419: public void accept(ExpressionVisitor visitor) {
420: if (!visitor.visitVariable(this )) {
421: super .accept(visitor);
422: }
423: }
424:
425: public String toString() {
426: return name;
427: }
428: }
429:
430: public abstract static class Member extends Symbolic {
431: protected Expression owner;
432:
433: public Member(Expression owner, String name, Class type) {
434: super (name, type);
435: this .owner = owner;
436: }
437:
438: public Expression getOwner() {
439: return owner;
440: }
441:
442: // This breaks the immutable pattern
443: public void setOwner(Expression owner) {
444: this .owner = owner;
445: }
446: }
447:
448: public static class FieldAccess extends Member {
449: public static final FieldAccess THIS = new FieldAccess(null,
450: "this", null);
451:
452: public FieldAccess(Expression owner, String name, Class type) {
453: super (owner, name, type);
454: }
455:
456: public Object evaluate(QueryContext context) {
457: if (this == THIS) {
458: return context.getCandidate();
459: }
460: // Evaluate using introspection
461: Object above = owner.evaluate(context);
462: Field f = findField(above.getClass(), name);
463: if (f != null) {
464: try {
465: return f.get(above);
466: } catch (IllegalAccessException e) {
467: }
468: } else {
469: // Then try get() method
470: StringBuffer sb = new StringBuffer("get").append(name);
471: sb.setCharAt(0, Character.toUpperCase(sb.charAt(3)));
472: Method m = findMethod(above.getClass(), sb.toString(),
473: null);
474: if (m != null) {
475: try {
476: return m.invoke(above, null);
477: } catch (IllegalAccessException e) {
478: } catch (InvocationTargetException e) {
479: }
480: }
481: }
482: return null;
483: }
484:
485: public String toString() {
486: if (this == THIS) {
487: return "this";
488: } else {
489: return owner + "." + name;
490: }
491: }
492:
493: public void accept(ExpressionVisitor visitor) {
494: if (!visitor.visitFieldAccess(this )) {
495: super .accept(visitor);
496: }
497: }
498: }
499:
500: public static class MethodCall extends Member {
501: protected Expression[] parameters;
502:
503: public MethodCall(Expression owner, String name,
504: Expression[] parameters, Class type) {
505: super (owner, name, type);
506: this .parameters = parameters;
507: }
508:
509: public Expression[] getParameters() {
510: return parameters;
511: }
512:
513: public Object evaluate(QueryContext context) {
514: // Evaluate using introspection
515: Object above = owner.evaluate(context);
516: Class[] types = new Class[parameters.length];
517: for (int i = 0; i < parameters.length; i++) {
518: types[i] = parameters[i].getType();
519: }
520: Method m = findMethod(above.getClass(), name, types);
521: if (m != null) {
522: try {
523: return m.invoke(above, parameters);
524: } catch (IllegalAccessException e) {
525: } catch (InvocationTargetException e) {
526: }
527: }
528: return null;
529: }
530:
531: public String toString() {
532: StringBuffer sb = new StringBuffer(owner.toString())
533: .append(".").append(name).append("(");
534: for (int i = 0; i < parameters.length; i++) {
535: if (i > 0) {
536: sb.append(", ");
537: }
538: sb.append(parameters[i].toString());
539: }
540: return sb.append(")").toString();
541: }
542:
543: public void accept(ExpressionVisitor visitor) {
544: if (!visitor.visitMethodCall(this )) {
545: super .accept(visitor);
546: }
547: }
548: }
549:
550: public static abstract class Unary extends Expression {
551: protected Expression operand;
552:
553: public Unary(Expression operand) {
554: this .operand = operand;
555: }
556:
557: public Expression getOperand() {
558: return operand;
559: }
560:
561: // breaks immutable
562: public void setOperand(Expression operand) {
563: this .operand = operand;
564: }
565:
566: public Class getType() {
567: return operand.getType();
568: }
569:
570: public void accept(ExpressionVisitor visitor) {
571: if (!visitor.visitUnary(this ))
572: super .accept(visitor);
573: }
574: }
575:
576: public static class UnaryMinus extends Unary {
577: public UnaryMinus(Expression operand) {
578: super (operand);
579: }
580:
581: public Object evaluate(QueryContext context) {
582: Number value = (Number) operand.evaluate(context);
583: if (value instanceof Float) {
584: return new Float(-value.floatValue());
585: } else if (value instanceof Long) {
586: return new Long(-value.longValue());
587: } else if (value instanceof Double) {
588: return new Double(-value.doubleValue());
589: } else {
590: return new Integer(-value.intValue());
591: }
592: }
593:
594: public String toString() {
595: return "-" + operand;
596: }
597: }
598:
599: public static abstract class Arithmetic extends Binary {
600: // For declarative purposes
601: public Arithmetic(Expression lhs, Expression rhs) {
602: super (lhs, rhs);
603: }
604:
605: public Object evaluate(QueryContext context) {
606: Number lhv = (Number) lhs.evaluate(context);
607: Number rhv = (Number) rhs.evaluate(context);
608: return evaluateNumeric(lhv, rhv);
609: }
610:
611: protected abstract Object evaluateNumeric(Number lhs, Number rhs);
612:
613: public Class getType() {
614: if (Double.class.equals(lhs.getType())
615: || Double.class.equals(rhs.getType())) {
616: return Double.class;
617: } else if (Float.class.equals(lhs.getType())
618: || Float.class.equals(rhs.getType())) {
619: return Float.class;
620: } else if (Long.class.equals(lhs.getType())
621: || Long.class.equals(rhs.getType())) {
622: return Long.class;
623: } else {
624: return Integer.class;
625: }
626: }
627: }
628:
629: public static class Multiply extends Arithmetic {
630: public Multiply(Expression lhs, Expression rhs) {
631: super (lhs, rhs);
632: }
633:
634: public Object evaluateNumeric(Number lhs, Number rhs) {
635: if ((lhs instanceof Double) || (rhs instanceof Double)) {
636: // Treat as double
637: return new Double(lhs.doubleValue() * rhs.doubleValue());
638: } else if ((lhs instanceof Float) || (rhs instanceof Float)) {
639: // Treat as float
640: return new Float(lhs.floatValue() * rhs.floatValue());
641: } else if ((lhs instanceof Long) || (rhs instanceof Long)) {
642: // Treat as long
643: return new Long(lhs.longValue() * rhs.longValue());
644: } else {
645: // Treat as int
646: return new Integer(lhs.intValue() * rhs.intValue());
647: }
648: }
649:
650: public Operator operator() {
651: return Operator.TIMES;
652: }
653: }
654:
655: public static class Modulo extends Arithmetic {
656: public Modulo(Expression lhs, Expression rhs) {
657: super (lhs, rhs);
658: }
659:
660: public Object evaluateNumeric(Number lhs, Number rhs) {
661: if ((lhs instanceof Double) || (rhs instanceof Double)) {
662: // Treat as double
663: return new Double(lhs.doubleValue() % rhs.doubleValue());
664: } else if ((lhs instanceof Float) || (rhs instanceof Float)) {
665: // Treat as float
666: return new Float(lhs.floatValue() % rhs.floatValue());
667: } else if ((lhs instanceof Long) || (rhs instanceof Long)) {
668: // Treat as long
669: return new Long(lhs.longValue() % rhs.longValue());
670: } else {
671: // Treat as int
672: return new Integer(lhs.intValue() % rhs.intValue());
673: }
674: }
675:
676: public Operator operator() {
677: return Operator.MODULO;
678: }
679: }
680:
681: public static class Divide extends Arithmetic {
682: public Divide(Expression lhs, Expression rhs) {
683: super (lhs, rhs);
684: }
685:
686: public Object evaluateNumeric(Number lhs, Number rhs) {
687: if ((lhs instanceof Double) || (rhs instanceof Double)) {
688: // Treat as double
689: return new Double(lhs.doubleValue() / rhs.doubleValue());
690: } else if ((lhs instanceof Float) || (rhs instanceof Float)) {
691: // Treat as float
692: return new Float(lhs.floatValue() / rhs.floatValue());
693: } else if ((lhs instanceof Long) || (rhs instanceof Long)) {
694: // Treat as long
695: return new Long(lhs.longValue() / rhs.longValue());
696: } else {
697: // Treat as int
698: return new Integer(lhs.intValue() / rhs.intValue());
699: }
700: }
701:
702: public Operator operator() {
703: return Operator.DIVIDE;
704: }
705: }
706:
707: public static class Add extends Arithmetic {
708: public Add(Expression lhs, Expression rhs) {
709: super (lhs, rhs);
710: }
711:
712: public Object evaluate(QueryContext context) {
713: Object lhv = lhs.evaluate(context);
714: Object rhv = rhs.evaluate(context);
715: if (lhv instanceof String) {
716: return lhv.toString() + rhv;
717: } else if (rhv instanceof String) {
718: return lhv + rhv.toString();
719: } else {
720: return evaluateNumeric((Number) lhv, (Number) rhv);
721: }
722: }
723:
724: public Object evaluateNumeric(Number lhs, Number rhs) {
725: if ((lhs instanceof Double) || (rhs instanceof Double)) {
726: // Treat as double
727: return new Double(lhs.doubleValue() + rhs.doubleValue());
728: } else if ((lhs instanceof Float) || (rhs instanceof Float)) {
729: // Treat as float
730: return new Float(lhs.floatValue() + rhs.floatValue());
731: } else if ((lhs instanceof Long) || (rhs instanceof Long)) {
732: // Treat as long
733: return new Long(lhs.longValue() + rhs.longValue());
734: } else {
735: // Treat as int
736: return new Integer(lhs.intValue() + rhs.intValue());
737: }
738: }
739:
740: public Operator operator() {
741: return Operator.PLUS;
742: }
743: }
744:
745: public static class Subtract extends Arithmetic {
746: public Subtract(Expression lhs, Expression rhs) {
747: super (lhs, rhs);
748: }
749:
750: public Object evaluateNumeric(Number lhs, Number rhs) {
751: if ((lhs instanceof Double) || (rhs instanceof Double)) {
752: // Treat as double
753: return new Double(lhs.doubleValue() - rhs.doubleValue());
754: } else if ((lhs instanceof Float) || (rhs instanceof Float)) {
755: // Treat as float
756: return new Float(lhs.floatValue() - rhs.floatValue());
757: } else if ((lhs instanceof Long) || (rhs instanceof Long)) {
758: // Treat as long
759: return new Long(lhs.longValue() - rhs.longValue());
760: } else {
761: // Treat as int
762: return new Integer(lhs.intValue() - rhs.intValue());
763: }
764: }
765:
766: public Operator operator() {
767: return Operator.MINUS;
768: }
769: }
770:
771: public static class Cast extends Unary {
772: protected Class type;
773:
774: public Cast(Class type, Expression operand) {
775: super (operand);
776: this .type = type;
777: }
778:
779: public Object evaluate(QueryContext context) {
780: return operand;
781: }
782:
783: public Class getType() {
784: return type;
785: }
786:
787: public String toString() {
788: return "(" + type.getName() + ") " + operand;
789: }
790: }
791:
792: public static class Not extends Unary {
793: public Not(Expression operand) {
794: super (operand);
795: }
796:
797: public Object evaluate(QueryContext context) {
798: return Boolean.valueOf(!(((Boolean) operand
799: .evaluate(context)).booleanValue()));
800: }
801:
802: public void accept(ExpressionVisitor visitor) {
803: if (!visitor.visitNot(this ))
804: super .accept(visitor);
805: }
806:
807: public String toString() {
808: return "!" + operand;
809: }
810: }
811:
812: public static class BitwiseComplement extends Unary {
813: public BitwiseComplement(Expression operand) {
814: super (operand);
815: }
816:
817: public Object evaluate(QueryContext context) {
818: Object value = operand.evaluate(context);
819: if (value instanceof Long) {
820: return new Long(~((Long) value).longValue());
821: } else if (value instanceof Integer) {
822: return new Integer(~((Integer) value).intValue());
823: } else if (value instanceof Short) {
824: return new Integer(~((Short) value).shortValue());
825: } else if (value instanceof Byte) {
826: return new Integer(~((Byte) value).byteValue());
827: }
828: throw new IllegalArgumentException();
829: }
830:
831: public Class getType() {
832: return (operand.getType().equals(Long.class)) ? Long.class
833: : Integer.class;
834: }
835:
836: public String toString() {
837: return "~" + operand;
838: }
839: }
840:
841: /**
842: * Converts a String object into its representation in
843: * a Java source file by adding double quotes around it
844: * and escaping any special characters within.
845: */
846: public static String escapeString(String input) {
847: int len = input.length();
848: StringBuffer sb = new StringBuffer(len + 2);
849: sb.append('"');
850: for (int i = 0; i < len; i++) {
851: escapeCharImpl(input.charAt(i), sb);
852: }
853: sb.append('"');
854: return sb.toString();
855: }
856:
857: /**
858: * Converts a character into its representation in a Java
859: * source file by adding single quotes around it and
860: * escaping it if it's a special character.
861: */
862: public static String escapeChar(char ch) {
863: StringBuffer sb = new StringBuffer(3);
864: sb.append('\'');
865: escapeCharImpl(ch, sb);
866: sb.append('\'');
867: return sb.toString();
868: }
869:
870: /** Escapes the character given and adds it to the StringBuffer. */
871: private static void escapeCharImpl(char ch, StringBuffer sb) {
872: switch (ch) {
873: case '"':
874: case '\'':
875: case '\\':
876: sb.append('\\').append(ch);
877: break;
878: case '\t':
879: sb.append("\\t");
880: break;
881: case '\n':
882: sb.append("\\n");
883: break;
884: case '\r':
885: sb.append("\\r");
886: break;
887: case '\b':
888: sb.append("\\b");
889: break;
890: case '\f':
891: sb.append("\\f");
892: break;
893: default:
894: sb.append(ch);
895: }
896: }
897:
898: /**
899: * Locates the field in the class or superclass chain,
900: * swallowing all exceptions.
901: */
902: private static Field findField(Class clazz, String name) {
903: while (!Object.class.equals(clazz)) {
904: try {
905: return clazz.getDeclaredField(name);
906: } catch (NoSuchFieldException e) {
907: clazz = clazz.getSuperclass();
908: }
909: }
910: return null;
911: }
912:
913: /**
914: * Locates the method in the class, superclass chain, or interfaces,
915: * swallowing all exceptions.
916: */
917: private static Method findMethod(Class clazz, String name,
918: Class[] paramTypes) {
919: try {
920: return clazz.getDeclaredMethod(name, paramTypes);
921: } catch (NoSuchMethodException e) {
922: Method m = null;
923: Class super class = clazz.getSuperclass();
924: if (super class != null) {
925: m = findMethod(super class, name, paramTypes);
926: }
927: if (m == null) {
928: Class[] interfaces = clazz.getInterfaces();
929: for (int i = 0; i < interfaces.length; i++) {
930: m = findMethod(interfaces[i], name, paramTypes);
931: if (m != null) {
932: return m;
933: }
934: }
935: }
936: }
937: return null;
938: }
939: }
|