Coverage Report - org.jbehave.core.model.ExamplesTable
 
Classes in this File Line Coverage Branch Coverage Complexity
ExamplesTable
100%
52/52
100%
18/18
1.643
 
 1  
 package org.jbehave.core.model;
 2  
 
 3  
 import java.util.ArrayList;
 4  
 import java.util.HashMap;
 5  
 import java.util.List;
 6  
 import java.util.Map;
 7  
 
 8  
 import org.apache.commons.lang.StringUtils;
 9  
 import org.apache.commons.lang.builder.ToStringBuilder;
 10  
 import org.apache.commons.lang.builder.ToStringStyle;
 11  
 
 12  
 /**
 13  
  * <p>
 14  
  * Represents a tabular structure to hold example data for parameters named via the headers:
 15  
  * <p/>
 16  
  * <pre>
 17  
  * |header 1|header 2| .... |header n|
 18  
  * |value 11|value 12| .... |value 1n|
 19  
  * ...
 20  
  * |value m1|value m2| .... |value mn|
 21  
  * </pre>
 22  
  * <p>Different header and value column separators can be specified to replace the default separator "|":</p>
 23  
  * <pre>
 24  
  * !!header 1!!header 2!! .... !!header n!!
 25  
  * !value 11!value 12! .... !value 1n!
 26  
  * ...
 27  
  * !value m1!value m2| .... !value mn!
 28  
  * </pre>
 29  
  * <p>Rows starting with an ignorable separator are allowed and ignored:</p>
 30  
  * <pre>
 31  
  * |header 1|header 2| .... |header n|
 32  
  * |-- A commented row --|
 33  
  * |value 11|value 12| .... |value 1n|
 34  
  * ...
 35  
  * |-- Another commented row --|
 36  
  * |value m1|value m2| .... |value mn|
 37  
  * </pre>
 38  
  * <p>Ignorable separator is configurable and defaults to "|--".</p>
 39  
  */
 40  
 public class ExamplesTable {
 41  
 
 42  
     private static final String NEWLINE = "\n";
 43  
     private static final String HEADER_SEPARATOR = "|";
 44  
     private static final String VALUE_SEPARATOR = "|";
 45  
     private static final String IGNORABLE_SEPARATOR = "|--";
 46  179
     private final List<Map<String, String>> data = new ArrayList<Map<String, String>>();
 47  
     private final String tableAsString;
 48  
     private final String headerSeparator;
 49  
     private final String valueSeparator;
 50  
     private final String ignorableSeparator;
 51  179
     private final List<String> headers = new ArrayList<String>();
 52  
 
 53  
     public ExamplesTable(String tableAsString) {
 54  56
         this(tableAsString, HEADER_SEPARATOR, VALUE_SEPARATOR);
 55  56
     }
 56  
 
 57  
     public ExamplesTable(String tableAsString, String headerSeparator, String valueSeparator) {
 58  179
         this(tableAsString, headerSeparator, valueSeparator, IGNORABLE_SEPARATOR);
 59  179
     }
 60  
 
 61  179
     public ExamplesTable(String tableAsString, String headerSeparator, String valueSeparator, String ignorableSeparator) {
 62  179
         this.tableAsString = tableAsString;
 63  179
         this.headerSeparator = headerSeparator;
 64  179
         this.valueSeparator = valueSeparator;
 65  179
         this.ignorableSeparator = ignorableSeparator;
 66  179
         parse();
 67  179
     }
 68  
 
 69  
     private void parse() {
 70  179
         data.clear();
 71  179
         String[] rows = tableAsString.trim().split(NEWLINE);
 72  179
         headers.clear();
 73  413
         for (int row = 0; row < rows.length; row++) {
 74  234
             String rowAsString = rows[row];
 75  234
             if ( rowAsString.startsWith(ignorableSeparator) ) {
 76  
                 // skip rows that start with ignorable separator
 77  2
                 continue;
 78  232
             } else if (row == 0) {
 79  179
                 List<String> columns = columnsFor(rowAsString, headerSeparator);
 80  179
                 headers.addAll(columns);
 81  179
             } else {
 82  53
                 List<String> columns = columnsFor(rowAsString, valueSeparator);
 83  53
                 Map<String, String> map = new HashMap<String, String>();
 84  165
                 for (int column = 0; column < columns.size(); column++) {
 85  112
                     map.put(headers.get(column), columns.get(column));
 86  
                 }
 87  53
                 data.add(map);
 88  
             }
 89  
         }
 90  179
     }
 91  
 
 92  
     private List<String> columnsFor(String row, String separator) {
 93  232
         List<String> columns = new ArrayList<String>();
 94  
         // use split limit -1 to ensure that empty strings will not be discarted
 95  704
         for (String column : row.split(buildRegex(separator), -1)) {
 96  472
             columns.add(column.trim());
 97  
         }
 98  
         // we could have a leading and a trailing empty column which we ignore
 99  232
         if ( StringUtils.isBlank(columns.get(0)) ){
 100  226
             columns.remove(0);
 101  
         }
 102  232
         int lastIndex = columns.size() - 1;
 103  232
         if ( lastIndex != -1 && StringUtils.isBlank(columns.get(lastIndex))  ){
 104  75
             columns.remove(lastIndex);
 105  
         }
 106  232
         return columns;
 107  
     }
 108  
 
 109  
     private String buildRegex(String separator) {
 110  232
         char[] chars = separator.toCharArray();
 111  232
         StringBuffer sb = new StringBuffer();
 112  466
         for ( char c : chars ){
 113  234
             sb.append("\\").append(c);
 114  
         }
 115  232
         return sb.toString();
 116  
     }
 117  
 
 118  
     public List<String> getHeaders() {
 119  21
         return headers;
 120  
     }
 121  
 
 122  
     public Map<String, String> getRow(int row) {
 123  70
         return data.get(row);
 124  
     }
 125  
 
 126  
     public int getRowCount() {
 127  19
         return data.size();
 128  
     }
 129  
 
 130  
     public List<Map<String, String>> getRows() {
 131  23
         return data;
 132  
     }
 133  
 
 134  
     public String getHeaderSeparator() {
 135  2
         return headerSeparator;
 136  
     }
 137  
 
 138  
     public String getValueSeparator() {
 139  2
         return valueSeparator;
 140  
     }
 141  
 
 142  
     public String asString() {
 143  13
         return tableAsString;
 144  
     }
 145  
 
 146  
     @Override
 147  
     public String toString() {
 148  15
         return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
 149  
     }
 150  
 
 151  
 }