001: // Modified or written by Object Mentor, Inc. for inclusion with FitNesse.
002: // Copyright (c) 2002 Cunningham & Cunningham, Inc.
003: // Released under the terms of the GNU General Public License version 2 or later.
004: package fit;
005:
006: import fit.exception.*;
007: import java.lang.reflect.*;
008: import java.util.regex.*;
009:
010: public abstract class Binding {
011: private static Pattern methodPattern = Pattern
012: .compile("(.+)(?:\\(\\)|\\?|!)");
013: private static Pattern fieldPattern = Pattern
014: .compile("=?([^=]+)=?");
015:
016: public TypeAdapter adapter;
017:
018: public static Binding create(Fixture fixture, String name)
019: throws Throwable {
020: Binding binding = null;
021:
022: if (name.startsWith("="))
023: binding = new SaveBinding();
024: else if (name.endsWith("="))
025: binding = new RecallBinding();
026: else if (methodPattern.matcher(name).matches())
027: binding = new QueryBinding();
028: else if (fieldPattern.matcher(name).matches())
029: binding = new SetBinding();
030:
031: if (binding == null)
032: binding = new NullBinding();
033: else
034: binding.adapter = makeAdapter(fixture, name);
035:
036: return binding;
037: }
038:
039: private static TypeAdapter makeAdapter(Fixture fixture, String name)
040: throws Throwable {
041: Matcher matcher = methodPattern.matcher(name);
042: if (matcher.find())
043: return makeAdapterForMethod(name, fixture, matcher);
044: else
045: return makeAdapterForField(name, fixture);
046: }
047:
048: private static TypeAdapter makeAdapterForField(String name,
049: Fixture fixture) {
050: Field field = null;
051: if (GracefulNamer.isGracefulName(name)) {
052: String simpleName = GracefulNamer.disgrace(name)
053: .toLowerCase();
054: field = findField(fixture, simpleName);
055: } else {
056: try {
057: Matcher matcher = fieldPattern.matcher(name);
058: matcher.find();
059: String fieldName = matcher.group(1);
060: field = fixture.getTargetClass().getField(fieldName);
061: } catch (NoSuchFieldException e) {
062: }
063: }
064:
065: if (field == null)
066: throw new NoSuchFieldFitFailureException(name);
067: return TypeAdapter.on(fixture, field);
068: }
069:
070: private static TypeAdapter makeAdapterForMethod(String name,
071: Fixture fixture, Matcher matcher) {
072: Method method = null;
073: if (GracefulNamer.isGracefulName(name)) {
074: String simpleName = GracefulNamer.disgrace(name)
075: .toLowerCase();
076: method = findMethod(fixture, simpleName);
077: } else {
078: try {
079: String methodName = matcher.group(1);
080: method = fixture.getTargetClass().getMethod(methodName,
081: new Class[] {});
082: } catch (NoSuchMethodException e) {
083: }
084: }
085:
086: if (method == null)
087: throw new NoSuchMethodFitFailureException(name);
088: return TypeAdapter.on(fixture, method);
089: }
090:
091: private static Field findField(Fixture fixture, String simpleName) {
092: Field[] fields = fixture.getTargetClass().getFields();
093: Field field = null;
094: for (int i = 0; i < fields.length; i++) {
095: Field possibleField = fields[i];
096: if (simpleName
097: .equals(possibleField.getName().toLowerCase())) {
098: field = possibleField;
099: break;
100: }
101: }
102: return field;
103: }
104:
105: private static Method findMethod(Fixture fixture, String simpleName) {
106: Method[] methods = fixture.getTargetClass().getMethods();
107: Method method = null;
108: for (int i = 0; i < methods.length; i++) {
109: Method possibleMethod = methods[i];
110: if (simpleName.equals(possibleMethod.getName()
111: .toLowerCase())) {
112: method = possibleMethod;
113: break;
114: }
115: }
116: return method;
117: }
118:
119: public abstract void doCell(Fixture fixture, Parse cell)
120: throws Throwable;
121:
122: public static class SaveBinding extends Binding {
123: public void doCell(Fixture fixture, Parse cell) {
124: try {
125: //TODO-MdM hmm... somehow this needs to regulated by the fixture.
126: if (fixture instanceof ColumnFixture)
127: ((ColumnFixture) fixture).executeIfNeeded();
128: String symbolValue = adapter.get().toString();
129: String symbolName = cell.text();
130: Fixture.setSymbol(symbolName, symbolValue);
131: cell.addToBody(Fixture.gray(" = " + symbolValue));
132: } catch (Exception e) {
133: fixture.exception(cell, e);
134: }
135: }
136: }
137:
138: public static class RecallBinding extends Binding {
139: public void doCell(Fixture fixture, Parse cell)
140: throws Exception {
141: String symbolName = cell.text();
142: String value = (String) Fixture.getSymbol(symbolName);
143: if (value == null)
144: fixture.exception(cell, new FitFailureException(
145: "No such symbol: " + symbolName));
146: else {
147: adapter.set(adapter.parse(value));
148: cell.addToBody(Fixture.gray(" = " + value));
149: }
150: }
151: }
152:
153: public static class SetBinding extends Binding {
154: public void doCell(Fixture fixture, Parse cell)
155: throws Throwable {
156: if ("".equals(cell.text()))
157: fixture.handleBlankCell(cell, adapter);
158: adapter.set(adapter.parse(cell.text()));
159: }
160: }
161:
162: public static class QueryBinding extends Binding {
163: public void doCell(Fixture fixture, Parse cell) {
164: fixture.check(cell, adapter);
165: }
166: }
167:
168: public static class NullBinding extends Binding {
169: public void doCell(Fixture fixture, Parse cell) {
170: fixture.ignore(cell);
171: }
172: }
173: }
|