package fitnesse.wikitext.parser; import java.util.List; import fit.FixtureLoader; import fit.FixtureName; import fitnesse.testsystems.slim.tables.DecisionTable; import fitnesse.testsystems.slim.tables.DynamicDecisionTable; import fitnesse.testsystems.slim.tables.ImportTable; import fitnesse.testsystems.slim.tables.QueryTable; import fitnesse.testsystems.slim.tables.ScenarioTable; import fitnesse.testsystems.slim.tables.ScriptTable; import fitnesse.testsystems.slim.tables.SlimTable; import fitnesse.testsystems.slim.tables.SlimTableFactory; public class ColoredSlimTable extends SymbolTypeDecorator{ public static final String CLASS_PROPERTY = "class"; public ColoredSlimTable(Table baseSymbolType) { super("Table", baseSymbolType); } @Override public String toTarget(Translator translator, Symbol symbol) { HtmlWriter writer = new HtmlWriter(); writer.startTag("table"); if (symbol.hasProperty(CLASS_PROPERTY)) { writer.putAttribute(CLASS_PROPERTY, symbol.getProperty(CLASS_PROPERTY)); } int longestRow = ((Table)baseSymbolType).longestRow(symbol); int rowCount = 0; boolean isImportFixture = false; boolean colorTable = false; boolean isFirstColumnTitle = false; boolean isSecondRowTitle = false; for (Symbol child : symbol.getChildren()) { rowCount++; writer.startTag("tr"); if (rowCount == 1 && symbol.hasProperty("hideFirst")) { writer.putAttribute(CLASS_PROPERTY, "hidden"); } int extraColumnSpan = longestRow - ((Table)baseSymbolType).rowLength(child); int column = 1; for (Symbol grandChild : child.getChildren()) { String body = ((Table)baseSymbolType).translateCellBody(translator, grandChild); if(rowCount == 1 && column == 1){ String tableName = body; // If is slim table class declaration then get fixture info for table coloring scheme. SlimTableFactory sf = new SlimTableFactory(); Class<? extends SlimTable> slimTableClazz = sf.getTableType(tableName); if(slimTableClazz != null){ colorTable = true; if (DecisionTable.class.isAssignableFrom(slimTableClazz) || DynamicDecisionTable.class.isAssignableFrom(slimTableClazz) || QueryTable.class.isAssignableFrom(slimTableClazz)) { isSecondRowTitle = true; } else if (ImportTable.class.isAssignableFrom(slimTableClazz)) { isImportFixture = true; } else if (ScriptTable.class.isAssignableFrom(slimTableClazz) || ScenarioTable.class.isAssignableFrom(slimTableClazz)) { isFirstColumnTitle = true; } } // Unmarked decision tables aren't found by getTableType(). Color table if first row is valid class. if(!colorTable) { List<String> potentialClasses = new FixtureName(tableName) .getPotentialFixtureClassNames(FixtureLoader.instance().fixturePathElements); for(String potentialClass: potentialClasses){ if (isValidClass(potentialClass)) { colorTable = true; isSecondRowTitle = true; break; } } } } // Use color scheme attributes to color table rows. if(colorTable && column == 1){ if(isImportFixture){ FixtureLoader.instance().addPackageToPath(body); } if(rowCount == 1){ writer.putAttribute(CLASS_PROPERTY, "slimRowTitle"); }else if(isSecondRowTitle && rowCount == 2){ writer.putAttribute(CLASS_PROPERTY, "slimRowTitle"); }else if(isFirstColumnTitle){ byte[] bodyBytes = body.getBytes(); int sum = 0; for(byte b: bodyBytes){ sum = sum + (int) b; } writer.putAttribute(CLASS_PROPERTY, "slimRowColor" + (sum % 10)); } else { writer.putAttribute(CLASS_PROPERTY, "slimRowColor" + (rowCount % 2)); } } writer.startTag("td"); if (extraColumnSpan > 0 && column == ((Table)baseSymbolType).rowLength(child)) writer.putAttribute("colspan", Integer.toString(extraColumnSpan + 1)); writer.putText(body); writer.endTag(); column++; } writer.endTag(); } writer.endTag(); return writer.toHtml(); } private boolean isValidClass(String potentialClass) { try { return Class.forName(potentialClass) != null; } catch (Exception e) { return false; }catch (NoClassDefFoundError e) { return false; } } @Override public SymbolType isApplicable(Translator translator){ Maybe<String> testSystem = Maybe.noString; if(translator instanceof HtmlTranslator){ testSystem = ((HtmlTranslator) translator).getParsingPage().findVariable("TEST_SYSTEM"); } if(testSystem.isNothing() || !"slim".equals(testSystem.getValue())) { return baseSymbolType; } return this; } }