View Javadoc

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              // no alias column has been provided, so we'll be adding one.
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         // copied down from superclass
115         cellTextList.clear();
116         doCells(row.parts);
117         if (!aliasBinding.isFound()) {
118             cellTextList.add(""); // placeholder
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         // should have been initialized in doTable.
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             // handle empty cell as null
160             if (cellText == null || cellText.length() == 0) {
161                 // use clear facet if available
162                 if (clearFacet != null) {
163                     clearFacet.clearProperty(adapter);
164                     right(cell);
165                     continue;
166                 }
167 
168                 // use setter facet otherwise
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             // non-empty, will need a setter
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                 // handle as parseable value
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                 // handle as reference to known object
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             // xactn mgmt now done by PersistenceSession#makePersistent()
215             // getTransactionManager().startTransaction();
216             getPersistenceSession().makePersistent(adapter);
217             // getTransactionManager().endTransaction();
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 }