gt:                 output.append(word.substring(0, maxCharInLine-lineLen) + "\n");
context: package autotest.common;
  
  import com.google.gwt.dom.client.Document;
  import com.google.gwt.dom.client.Element;
  import com.google.gwt.http.client.URL;
  import com.google.gwt.i18n.client.NumberFormat;
  import com.google.gwt.json.client.JSONArray;
  import com.google.gwt.json.client.JSONNumber;
  import com.google.gwt.json.client.JSONObject;
  import com.google.gwt.json.client.JSONString;
  import com.google.gwt.json.client.JSONValue;
  import com.google.gwt.user.client.Window;
  import com.google.gwt.user.client.ui.HTMLPanel;
  
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  
  public class Utils {
      public static final String JSON_NULL = "<null>";
      public static final String RETRIEVE_LOGS_URL = "/retrieve_logs/";
  
      private static final String[][] escapeMappings = {
          {"&", "&amp;"},
          {">", "&gt;"},
          {"<", "&lt;"},
          {"\"", "&quot;"},
          {"'", "&apos;"},
      };
  
      /**
       * Converts a collection of Java <code>String</code>s into a <code>JSONArray
       * </code> of <code>JSONString</code>s.
       */
      public static JSONArray stringsToJSON(Collection<String> strings) {
          JSONArray result = new JSONArray();
          for(String s : strings) {
              result.set(result.size(), new JSONString(s));
          }
          return result;
      }
  
      /**
       * Converts a collection of Java <code>Integers</code>s into a <code>JSONArray
       * </code> of <code>JSONNumber</code>s.
       */
      public static JSONArray integersToJSON(Collection<Integer> integers) {
          JSONArray result = new JSONArray();
          for(Integer i : integers) {
              result.set(result.size(), new JSONNumber(i));
          }
          return result;
      }
  
      /**
       * Converts a <code>JSONArray</code> of <code>JSONStrings</code> to an
       * array of Java <code>Strings</code>.
       */
      public static String[] JSONtoStrings(JSONArray strings) {
          String[] result = new String[strings.size()];
          for (int i = 0; i < strings.size(); i++) {
              result[i] = jsonToString(strings.get(i));
          }
          return result;
      }
  
      /**
       * Converts a <code>JSONArray</code> of <code>JSONObjects</code> to an
       * array of Java <code>Strings</code> by grabbing the specified field from
       * each object.
       */
      public static String[] JSONObjectsToStrings(JSONArray objects, String field) {
          String[] result = new String[objects.size()];
          for (int i = 0; i < objects.size(); i++) {
              JSONValue fieldValue = objects.get(i).isObject().get(field);
              result[i] = jsonToString(fieldValue);
          }
          return result;
      }
  
      public static JSONObject mapToJsonObject(Map<String, String> map) {
          JSONObject result = new JSONObject();
          for (Map.Entry<String, String> entry : map.entrySet()) {
              result.put(entry.getKey(), new JSONString(entry.getValue()));
          }
          return result;
      }
  
      public static Map<String, String> jsonObjectToMap(JSONObject object) {
          Map<String, String> result = new HashMap<String, String>();
          for (String key : object.keySet()) {
              result.put(key, jsonToString(object.get(key)));
          }
          return result;
      }
  
      /**
       * Get a value out of a JSONObject list of size 1.
       * @return list[0]
       * @throws IllegalArgumentException if the list is not of size 1
       */
      public static JSONObject getSingleObjectFromList(List<JSONObject> list) {
          if(list.size() != 1) {
              throw new IllegalArgumentException("List is not of size 1");
          }
          return list.get(0);
      }
  
      public static JSONObject getSingleObjectFromArray(JSONArray array) {
          return getSingleObjectFromList(new JSONArrayList<JSONObject>(array));
      }
  
      public static JSONObject copyJSONObject(JSONObject source) {
          JSONObject dest = new JSONObject();
          for(String key : source.keySet()) {
              dest.put(key, source.get(key));
          }
          return dest;
      }
  
      public static String escape(String text) {
          for (String[] mapping : escapeMappings) {
              text = text.replace(mapping[0], mapping[1]);
          }
          return text;
      }
  
      public static String unescape(String text) {
          // must iterate in reverse order
          for (int i = escapeMappings.length - 1; i >= 0; i--) {
              text = text.replace(escapeMappings[i][1], escapeMappings[i][0]);
          }
          return text;
      }
  
      public static <T> List<T> wrapObjectWithList(T object) {
          List<T> list = new ArrayList<T>();
          list.add(object);
          return list;
      }
  
      public static <T> String joinStrings(String joiner, List<T> objects, boolean wantBlanks) {
          StringBuilder result = new StringBuilder();
          boolean first = true;
          for (T object : objects) {
              String piece = object.toString();
              if (piece.equals("") && !wantBlanks) {
                  continue;
              }
              if (first) {
                  first = false;
              } else {
                  result.append(joiner);
              }
              result.append(piece);
          }
          return result.toString();
      }
  
      public static <T> String joinStrings(String joiner, List<T> objects) {
          return joinStrings(joiner, objects, false);
      }
  
      public static Map<String,String> decodeUrlArguments(String urlArguments,
                                                          Map<String, String> arguments) {
          String[] components = urlArguments.split("&");
          for (String component : components) {
              String[] parts = component.split("=");
              if (parts.length > 2) {
                  throw new IllegalArgumentException();
              }
              String key = decodeComponent(parts[0]);
              String value = "";
              if (parts.length == 2) {
                  value = URL.decodeComponent(parts[1]);
              }
              arguments.put(key, value);
          }
          return arguments;
      }
  
      private static String decodeComponent(String component) {
          return URL.decodeComponent(component.replace("%27", "'"));
      }
  
      public static String encodeUrlArguments(Map<String, String> arguments) {
          List<String> components = new ArrayList<String>();
          for (Map.Entry<String, String> entry : arguments.entrySet()) {
              String key = encodeComponent(entry.getKey());
              String value = encodeComponent(entry.getValue());
              components.add(key + "=" + value);
          }
          return joinStrings("&", components);
      }
  
      private static String encodeComponent(String component) {
          return URL.encodeComponent(component).replace("'", "%27");
      }
  
      /**
       * @param path should be of the form "123-showard/status.log" or just "123-showard"
       */
      public static String getLogsUrl(String path) {
          return "/results/" + path;
      }
  
      public static String getRetrieveLogsUrl(String path) {
          String logUrl = URL.encode(getLogsUrl(path));
          return RETRIEVE_LOGS_URL + "?job=" + logUrl;
      }
  
      public static String jsonToString(JSONValue value) {
          JSONString string;
          JSONNumber number;
          assert value != null;
          if ((string = value.isString()) != null) {
              return string.stringValue();
          }
          if ((number = value.isNumber()) != null) {
              double doubleValue = number.doubleValue();
              if (doubleValue == (int) doubleValue) {
                  return Integer.toString((int) doubleValue);
              }
              return Double.toString(doubleValue);
  
          }
          if (value.isNull() != null) {
              return JSON_NULL;
          }
          return value.toString();
      }
  
      public static String setDefaultValue(Map<String, String> map, String key, String defaultValue) {
          if (map.containsKey(key)) {
              return map.get(key);
          }
          map.put(key, defaultValue);
          return defaultValue;
      }
  
      public static JSONValue setDefaultValue(JSONObject object, String key, JSONValue defaultValue) {
          if (object.containsKey(key)) {
              return object.get(key);
          }
          object.put(key, defaultValue);
          return defaultValue;
      }
  
      public static List<String> splitList(String list, String splitRegex) {
          String[] parts = list.split(splitRegex);
          List<String> finalParts = new ArrayList<String>();
          for (String part : parts) {
              if (!part.equals("")) {
                  finalParts.add(part);
              }
          }
          return finalParts;
      }
  
      public static List<String> splitList(String list) {
          return splitList(list, ",");
      }
  
      public static List<String> splitListWithSpaces(String list) {
          return splitList(list, "[,\\s]+");
      }
  
      public static void updateObject(JSONObject destination, JSONObject source) {
          if (source == null) {
              return;
          }
          for (String key : source.keySet()) {
              destination.put(key, source.get(key));
          }
      }
  
      public static void openUrlInNewWindow(String url) {
          Window.open(url, "_blank", "");
      }
  
      public static HTMLPanel divToPanel(String elementId) {
          Element divElement = Document.get().getElementById(elementId);
          divElement.getParentElement().removeChild(divElement);
          return new HTMLPanel(divElement.getInnerHTML());
      }
  
      public static void setElementVisible(String elementId, boolean visible) {
          String display = visible ? "block" : "none";
          Document.get().getElementById(elementId).getStyle().setProperty("display", display);
      }
  
      public static String percentage(int num, int total) {
          if (total == 0) {
              return "N/A";
          }
          NumberFormat format = NumberFormat.getFormat("##0.#%");
          return format.format(num / (double) total);
      }
  
      public static String numberAndPercentage(int num, int total) {
          return num + " (" + percentage(num, total) + ")";
      }
  
      public static interface JsonObjectFactory<T> {
          public T fromJsonObject(JSONObject object);
      }
  
      public static <T> List<T> createList(JSONArray objects, JsonObjectFactory<T> factory) {
          List<T> list = new ArrayList<T>();
          for (JSONObject object : new JSONArrayList<JSONObject>(objects)) {
              list.add(factory.fromJsonObject(object));
          }
          return list;
      }
  
      public static String getBaseUrl() {
          return Window.Location.getProtocol() + "//" + Window.Location.getHost();
      }
      
      /**
       * Split string into multiple lines, preserving words, insert "\n" at the end of lines
       * @param input text to be split
       * @param maxCharInLine maximum number of characters allowed in a line
       * @return
       */
      public static String splitIntoLines(String input, int maxCharInLine){
          StringBuilder output = new StringBuilder(input.length());
          int lineLen = 0;
      	String[] words = input.split("\\s"); // split on all whitespace
      	int wordIndex = 0;
          while (wordIndex < words.length) {
              String word = words[wordIndex++];
              while(word.length() > maxCharInLine) { // break words longer than line limit
  