public int compareTo(UnicodeString str) {

    int result = getString().compareTo(str.getString());

    // As per the equals method lets do this in stages
    if (result != 0) return result;

    // OK string appears to be equal but now lets compare formatting runs
    if ((field_4_format_runs == null) && (str.field_4_format_runs == null))
      // Strings are equal, and there are no formatting runs.
      return 0;

    if ((field_4_format_runs == null) && (str.field_4_format_runs != null))
      // Strings are equal, but one or the other has formatting runs
      return 1;
    if ((field_4_format_runs != null) && (str.field_4_format_runs == null))
      // Strings are equal, but one or the other has formatting runs
      return -1;

    // Strings are equal, so now compare formatting runs.
    int size = field_4_format_runs.size();
    if (size != str.field_4_format_runs.size()) return size - str.field_4_format_runs.size();

    for (int i = 0; i < size; i++) {
      FormatRun run1 = field_4_format_runs.get(i);
      FormatRun run2 = str.field_4_format_runs.get(i);

      result = run1.compareTo(run2);
      if (result != 0) return result;
    }

    // Well the format runs are equal as well!, better check the ExtRst data
    if ((field_5_ext_rst == null) && (str.field_5_ext_rst == null)) return 0;
    if ((field_5_ext_rst == null) && (str.field_5_ext_rst != null)) return 1;
    if ((field_5_ext_rst != null) && (str.field_5_ext_rst == null)) return -1;

    result = field_5_ext_rst.compareTo(str.field_5_ext_rst);
    if (result != 0) return result;

    // Phew!! After all of that we have finally worked out that the strings
    // are identical.
    return 0;
  }
  public Object clone() {
    UnicodeString str = new UnicodeString();
    str.field_1_charCount = field_1_charCount;
    str.field_2_optionflags = field_2_optionflags;
    str.field_3_string = field_3_string;
    if (field_4_format_runs != null) {
      str.field_4_format_runs = new ArrayList<FormatRun>();
      for (FormatRun r : field_4_format_runs) {
        str.field_4_format_runs.add(new FormatRun(r._character, r._fontIndex));
      }
    }
    if (field_5_ext_rst != null) {
      str.field_5_ext_rst = field_5_ext_rst.clone();
    }

    return str;
  }