package nl.hsac.fitnesse.slim.converter; import fitnesse.slim.Converter; import fitnesse.slim.converters.ConverterRegistry; import fitnesse.slim.converters.ElementConverterHelper; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Slim Converter which works with HTML ordered lists (i.e. numbered lists) instead of the standard Java * toString() representation for lists. */ public class NumberedListConverter extends fitnesse.slim.converters.GenericCollectionConverter<Object, List<Object>> { private static final Pattern LIST_PATTERN = Pattern.compile( "<ol( start=\"\\d+\")?\\s*>\\s*((<li>\\s*.*?\\s*</li>\\s*)*)</ol>", Pattern.DOTALL); private static final Converter<Object> OBJ_CONVERTER = new ObjectConverter(); /** * Makes NumberedListConverter the Converter Slim will uses for (Array)Lists. */ public static void register() { try { Class<? extends List<Object>> listObjectClass; listObjectClass = (Class<List<Object>>) NumberedListConverter.class .getMethod("toString", List.class).getParameterTypes()[0]; NumberedListConverter converter = new NumberedListConverter(); ConverterRegistry.addConverter(listObjectClass, converter); ConverterRegistry.addConverter(ArrayList.class, new NumberedArrayListConverter(converter)); } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new RuntimeException(e); } } /** * NumberedListConverter cannot implement Converter for List and ArrayList, therefore * this inner class ensures we have an implementation of ArrayList also. */ public static class NumberedArrayListConverter implements Converter<ArrayList> { private final NumberedListConverter numberedListConverter; public NumberedArrayListConverter(NumberedListConverter aNumberedListConverter) { numberedListConverter = aNumberedListConverter; } @Override public String toString(ArrayList o) { return numberedListConverter.toString(o); } @Override public ArrayList fromString(String arg) { return numberedListConverter.fromString(arg); } } public NumberedListConverter() { super(ArrayList.class, OBJ_CONVERTER); } @Override public String toString(List<Object> list) { if (list == null) { return super.toString(list); } StringBuilder messageList = new StringBuilder("<ol start=\"0\">"); for (Object element : list) { messageList.append("<li>"); String formattedElement = ElementConverterHelper.elementToString(element); messageList.append(formattedElement); messageList.append("</li>"); } messageList.append("</ol>"); return messageList.toString(); } @Override public ArrayList<Object> fromString(String arg) { ArrayList<Object> result; Matcher matcher = LIST_PATTERN.matcher(arg); if (matcher.matches()) { result = new ArrayList<Object>(); String items = matcher.group(2); if (!"".equals(items)) { items = items.replaceFirst("^\\s*<li>\\s*", ""); items = items.replaceFirst("\\s*</li>\\s*$", ""); String[] elements = items.split("\\s*</li>\\s*<li>\\s*"); result.addAll(Arrays.asList(elements)); } } else { result = new ArrayList<Object>(super.fromString(arg)); } return result; } }