1 package org.starobjects.tested.fitnesse.internal.fixtures;
2
3 import java.util.ArrayList;
4 import java.util.List;
5
6 import org.nakedobjects.metamodel.adapter.NakedObject;
7 import org.nakedobjects.metamodel.commons.exceptions.NakedObjectException;
8 import org.nakedobjects.metamodel.facets.object.parseable.ParseableFacet;
9 import org.nakedobjects.metamodel.facets.properties.modify.PropertyClearFacet;
10 import org.nakedobjects.metamodel.facets.properties.modify.PropertySetterFacet;
11 import org.nakedobjects.metamodel.spec.NakedObjectSpecification;
12 import org.nakedobjects.metamodel.spec.feature.NakedObjectAssociation;
13 import org.nakedobjects.metamodel.spec.feature.OneToOneAssociation;
14 import org.starobjects.tested.fitnesse.StoryFixture;
15 import org.starobjects.tested.fitnesse.internal.fixtures.bindings.CellBinding;
16 import org.starobjects.tested.fitnesse.internal.util.FitnesseUtil;
17 import org.starobjects.tested.fitnesse.internal.util.StringUtil;
18
19 import fit.Fixture;
20 import fit.Parse;
21
22 public class SetUpObjects extends AbstractFixture {
23
24 public static enum Mode {
25 PERSIST, DO_NOT_PERSIST,
26 }
27
28 private final String className;
29
30 private final List<String> cellTextList = new ArrayList<String>();
31 private final List<OneToOneAssociation> associations = new ArrayList<OneToOneAssociation>();
32 private final CellBinding aliasBinding;
33 private final Mode mode;
34
35 private NakedObjectSpecification spec;
36
37 public SetUpObjects(final StoryFixture storyFixture,
38 final String className, final Mode mode) {
39 this(storyFixture, className, mode, CellBinding.builder(
40 Constants.ALIAS_RESULT_NAME, Constants.ALIAS_RESULT_HEAD_SET)
41 .autoCreate().build());
42 }
43
44 private SetUpObjects(final StoryFixture storyFixture,
45 final String className, final Mode mode,
46 final CellBinding aliasBinding) {
47 super(storyFixture, aliasBinding);
48 this.className = className;
49 this.mode = mode;
50 this.aliasBinding = aliasBinding;
51 }
52
53 @Override
54 public void doTable(final Parse table) {
55 final Parse classNameCell = table.parts.parts.more;
56
57 try {
58 spec = getSpecificationLoader().loadSpecification(className);
59 } catch (final NakedObjectException ex) {
60 FitnesseUtil.exception(this, classNameCell, "(no such class)");
61 return;
62 }
63
64 super.doTable(table);
65
66 if (!aliasBinding.isFound()) {
67
68
69 final Parse blankFinalCell = new Parse("th", "", null, null);
70 classNameCell.last().more = blankFinalCell;
71 }
72 }
73
74 @Override
75 protected void doRowsWithBindings(final Parse headRow) {
76 Parse eachHead = headRow.parts;
77 final int aliasColumn = aliasBinding.getColumn();
78 try {
79 for (int i = 0; eachHead != null; i++, eachHead = eachHead.more) {
80 final String headText = eachHead.text();
81
82 if (i == aliasColumn) {
83 associations.add(null);
84 continue;
85 }
86
87 NakedObjectAssociation association = null;
88 try {
89 final String memberName = StringUtil.memberIdFor(headText);
90 association = spec.getAssociation(memberName);
91 } catch (final Exception ex) {
92 associations.add(null);
93 FitnesseUtil
94 .exception(this, eachHead, "(no such property)");
95 continue;
96 }
97
98 if (!association.isOneToOneAssociation()) {
99 associations.add(null);
100 FitnesseUtil.exception(this, eachHead, "(not a property)");
101 continue;
102 }
103
104 associations.add((OneToOneAssociation) association);
105 }
106 } catch (final Throwable throwable) {
107 exception(eachHead, throwable);
108 }
109 }
110
111 @Override
112 public void doRow(final Parse row) {
113
114
115 cellTextList.clear();
116 doCells(row.parts);
117 if (!aliasBinding.isFound()) {
118 cellTextList.add("");
119 }
120
121 try {
122 setUpObject(row);
123 rightAllKnownAssociationCells(row);
124 } catch (final Exception e) {
125 wrongAllKnownAssociationCells(row);
126 reportError(row, e);
127 }
128 }
129
130 @Override
131 public void doCell(final Parse cell, final int column) {
132 super.doCell(cell, column);
133 cellTextList.add(cell.text());
134 }
135
136 private void setUpObject(final Parse row) throws Exception {
137
138
139 if (spec == null) {
140 return;
141 }
142
143 final NakedObject adapter =
144 getPersistenceSession().createInstance(spec);
145
146 for (int i = 0; i < associations.size(); i++) {
147 final OneToOneAssociation association = associations.get(i);
148 if (association == null) {
149 continue;
150 }
151
152 final String cellText = cellTextList.get(i);
153 final Parse cell = FitnesseUtil.cell(row, i);
154 final PropertyClearFacet clearFacet = association
155 .getFacet(PropertyClearFacet.class);
156 final PropertySetterFacet setterFacet = association
157 .getFacet(PropertySetterFacet.class);
158
159
160 if (cellText == null || cellText.length() == 0) {
161
162 if (clearFacet != null) {
163 clearFacet.clearProperty(adapter);
164 right(cell);
165 continue;
166 }
167
168
169 if (setterFacet != null) {
170 setterFacet.setProperty(adapter, null);
171 right(cell);
172 continue;
173 }
174
175 FitnesseUtil.exception(this, cell, "(cannot clear)");
176 continue;
177 }
178
179
180 if (setterFacet == null) {
181 FitnesseUtil.exception(this, cell, "(cannot set)");
182 continue;
183 }
184
185 final NakedObjectSpecification fieldSpecification = association
186 .getSpecification();
187 final ParseableFacet parseableFacet = fieldSpecification
188 .getFacet(ParseableFacet.class);
189
190 NakedObject referencedAdapter = null;
191 if (parseableFacet != null) {
192
193 try {
194 referencedAdapter = parseableFacet.parseTextEntry(adapter,
195 cellText);
196 } catch (final IllegalArgumentException ex) {
197 FitnesseUtil.exception(this, cell, "(cannot parse)");
198 continue;
199 }
200
201 } else {
202
203 referencedAdapter = getStoryFixture().getAliased(cellText);
204 if (referencedAdapter == null) {
205 FitnesseUtil.exception(this, cell, "(unknown reference)");
206 continue;
207 }
208 }
209 setterFacet.setProperty(adapter, referencedAdapter);
210
211 }
212
213 if (mode == Mode.PERSIST) {
214
215
216 getPersistenceSession().makePersistent(adapter);
217
218 }
219
220 if (aliasBinding.isFound()) {
221 final Parse aliasCell = FitnesseUtil.cell(row, aliasBinding
222 .getColumn());
223 if (aliasCell != null) {
224 String alias = aliasCell.text();
225 if (StringUtil.emptyString(alias)) {
226 alias = getStoryFixture().aliasPrefixedAs(StringUtil
227 .lowerLeading(spec.getShortName()), adapter);
228 aliasCell.body = Fixture.gray(alias);
229 } else {
230 getStoryFixture().aliasAs(alias, adapter);
231 }
232 }
233 } else {
234 final String alias = getStoryFixture().aliasPrefixedAs(StringUtil
235 .lowerLeading(spec.getShortName()), adapter);
236 appendCell(row, Fixture.gray(alias));
237 }
238 }
239
240 private void rightAllKnownAssociationCells(final Parse row) {
241 for (int i = 0; i < associations.size(); i++) {
242 final OneToOneAssociation association = associations.get(i);
243 if (association != null) {
244 final Parse cell = FitnesseUtil.cell(row, i);
245 if (cell != null) {
246 right(cell);
247 }
248 }
249 }
250 }
251
252 private void wrongAllKnownAssociationCells(final Parse row) {
253 for (int i = 0; i < associations.size(); i++) {
254 final OneToOneAssociation association = associations.get(i);
255 if (association != null) {
256 final Parse cell = FitnesseUtil.cell(row, i);
257 if (cell != null) {
258 wrong(cell);
259 }
260 }
261 }
262 }
263
264 private Parse appendCell(final Parse row, final String text) {
265 final Parse lastCell = new Parse("td", text, null, null);
266 row.parts.last().more = lastCell;
267 return lastCell;
268 }
269
270 }