001: // Copyright (C) 2003,2004,2005 by Object Mentor, Inc. All rights reserved.
002: // Released under the terms of the GNU General Public License version 2 or later.
003: package fit;
004:
005: import fit.exception.*;
006: import java.lang.reflect.*;
007: import java.util.regex.*;
008:
009: public abstract class Binding {
010: private static Pattern methodPattern = Pattern
011: .compile("(.+)(?:\\(\\)|\\?|!)");
012:
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
126: // fixture.
127: if (fixture instanceof ColumnFixture)
128: ((ColumnFixture) fixture).executeIfNeeded();
129: String symbolValue = adapter.get().toString();
130: String symbolName = cell.text();
131: Fixture.setSymbol(symbolName, symbolValue);
132: cell.addToBody(Fixture.gray(" = " + symbolValue));
133: } catch (Exception e) {
134: fixture.exception(cell, e);
135: }
136: }
137: }
138:
139: public static class RecallBinding extends Binding {
140: public void doCell(Fixture fixture, Parse cell)
141: throws Exception {
142: String symbolName = cell.text();
143: String value = (String) Fixture.getSymbol(symbolName);
144: if (value == null)
145: fixture.exception(cell, new FitFailureException(
146: "No such symbol: " + symbolName));
147: else
148: adapter.set(adapter.parse(value));
149: }
150: }
151:
152: public static class SetBinding extends Binding {
153: public void doCell(Fixture fixture, Parse cell)
154: throws Throwable {
155: if ("".equals(cell.text()))
156: fixture.handleBlankCell(cell, adapter);
157: adapter.set(adapter.parse(cell.text()));
158: }
159: }
160:
161: public static class QueryBinding extends Binding {
162: public void doCell(Fixture fixture, Parse cell) {
163: fixture.check(cell, adapter);
164: }
165: }
166:
167: public static class NullBinding extends Binding {
168: public void doCell(Fixture fixture, Parse cell) {
169: fixture.ignore(cell);
170: }
171: }
172: }
|