public void save(Group group, Writer out) throws PerforceException {
    // A bit of validation to make sure we are correct.  Perforce does NOT freaking tell us about
    // this during the save...
    if (group.getOwnersAsString().equals("")) {
      throw new IllegalArgumentException("Group owner is a required field.");
    }
    /* form looks like:
    Group:  tekdev

    MaxResults: unlimited

    MaxScanRows:    unlimited

    MaxLockTime:    unlimited

    Timeout:    43200

    Subgroups:

    Owners:

    Users:
    	anil
    	mwille
    */
    try {
      out.write("Group: " + group.getName() + "\n");
      out.write("MaxResults: " + group.getMaxResults() + "\n");
      out.write("MaxScanRows: " + group.getMaxScanRows() + "\n");
      out.write("MaxLockTime: " + group.getMaxLockTime() + "\n");
      out.write("Timeout: " + group.getTimeout() + "\n");
      out.write("Subgroups:\n");
      for (String s : group.getSubgroups()) {
        out.write(" " + s + "\n");
      }
      out.write("Owners:\n");
      for (String s : group.getOwners()) {
        out.write(" " + s + "\n");
      }
      out.write("Users:\n");
      for (String s : group.getUsers()) {
        out.write(" " + s + "\n");
      }

    } catch (IOException e) {
      throw new PerforceException("Failed to save group: " + group.getName(), e);
    }
  }
  public Group buildForm(Map<String, String> fields) throws PerforceException {
    Group group = new Group();
    group.setName(getField("Group", fields));
    group.setMaxLockTime(getField("MaxLockTime", fields));
    group.setMaxResults(getField("MaxResults", fields));
    group.setMaxScanRows(getField("MaxScanRows", fields));

    String value = getField("Timeout", fields);
    if (value.equals("")) value = "0";

    group.setTimeout(Long.parseLong(value));
    group.setUsers(getFieldAsList("Users", fields));
    group.setSubgroups(getFieldAsList("Subgroups", fields));
    group.setOwners(getFieldAsList("Owners", fields));

    return group;
  }