gt:                 usersRemoved = new ArrayList();
context: /*
   * Group.java
   *
   * This work is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published
   * by the Free Software Foundation; either version 2 of the License,
   * or (at your option) any later version.
   *
   * This work is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
   * General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software
   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
   * USA
   *
   * Copyright (c) 2004-2005 Per Cederberg. All rights reserved.
   */
  
  package org.liquidsite.core.content;
  
  import java.util.ArrayList;
  
  import org.liquidsite.core.data.DataObjectException;
  import org.liquidsite.core.data.DataSource;
  import org.liquidsite.core.data.GroupData;
  import org.liquidsite.core.data.GroupPeer;
  import org.liquidsite.core.data.UserGroupData;
  import org.liquidsite.core.data.UserGroupPeer;
  import org.liquidsite.util.log.Log;
  
  /**
   * A system group.
   *
   * @author   Per Cederberg, <per at percederberg dot net>
   * @version  1.0
   */
  public class Group extends PersistentObject {
  
      /**
       * The class logger.
       */
      private static final Log LOG = new Log(Group.class);
  
      /**
       * The permitted group name characters.
       */
      public static final String NAME_CHARS =
          UPPER_CASE + LOWER_CASE + NUMBERS + BINDERS;
  
      /**
       * The group data.
       */
      private GroupData data;
  
      /**
       * The list of user names added since the object was saved.
       */
      private ArrayList usersAdded = null;
  
      /**
       * The list of user names removed since the object was saved.
       */
      private ArrayList usersRemoved = null;
  
      /**
       * Returns a list of matching groups in a specified domain. Only
       * groups with matching names will be returned.
       *
       * @param manager        the content manager to use
       * @param domain         the domain
       * @param filter         the search filter (empty for all)
       *
       * @return an array of all groups in the domain
       *
       * @throws ContentException if the database couldn't be accessed
       *             properly
       */
      static Group[] findByDomain(ContentManager manager,
                                  Domain domain,
                                  String filter)
          throws ContentException {
  
          DataSource  src = getDataSource(manager);
          ArrayList   list;
          Group[]     res;
  
          try {
              list = GroupPeer.doSelectByDomain(src, domain.getName(), filter);
              res = new Group[list.size()];
              for (int i = 0; i < list.size(); i++) {
                  res[i] = new Group(manager, (GroupData) list.get(i));
              }
          } catch (DataObjectException e) {
              LOG.error(e.getMessage());
              throw new ContentException(e);
          } finally {
              src.close();
          }
          return res;
      }
  
      /**
       * Returns a group with a specified name.
       *
       * @param manager        the content manager to use
       * @param domain         the domain
       * @param name           the group name
       *
       * @return the group found, or
       *         null if no matching group existed
       *
       * @throws ContentException if the database couldn't be accessed
       *             properly
       */
      static Group findByName(ContentManager manager,
                              Domain domain,
                              String name)
          throws ContentException {
  
          DataSource  src = getDataSource(manager);
          GroupData   data;
  
          try {
              data = GroupPeer.doSelectByName(src, domain.getName(), name);
          } catch (DataObjectException e) {
              LOG.error(e.getMessage());
              throw new ContentException(e);
          } finally {
              src.close();
          }
          if (data == null) {
              return null;
          } else {
              return new Group(manager, data);
          }
      }
  
      /**
       * Returns an array of all groups a certain user belongs to.
       *
       * @param manager        the content manager to use
       * @param user           the user
       *
       * @return an array of all groups the user belongs to
       *
       * @throws ContentException if the database couldn't be accessed
       *             properly
       */
      static Group[] findByUser(ContentManager manager, User user)
          throws ContentException {
  
          DataSource     src = getDataSource(manager);
          ArrayList      list;
          Group[]        res;
          UserGroupData  data;
          GroupData      group;
          String         name;
  
          try {
              list = UserGroupPeer.doSelectByUser(src,
                                                  user.getDomainName(),
                                                  user.getName());
              res = new Group[list.size()];
              for (int i = 0; i < list.size(); i++) {
                  data = (UserGroupData) list.get(i);
                  name = data.getString(UserGroupData.GROUP);
                  group = GroupPeer.doSelectByName(src,
                                                   user.getDomainName(),
                                                   name);
                  res[i] = new Group(manager, group);
              }
          } catch (DataObjectException e) {
              LOG.error(e.getMessage());
              throw new ContentException(e);
          } finally {
              src.close();
          }
          return res;
      }
  
      /**
       * Creates a new group with default values.
       *
       * @param manager        the content manager to use
       * @param domain         the domain
       * @param name           the group name
       */
      public Group(ContentManager manager, Domain domain, String name) {
          super(manager, false);
          this.data = new GroupData();
          this.data.setString(GroupData.DOMAIN, domain.getName());
          this.data.setString(GroupData.NAME, name);
      }
  
      /**
       * Creates a new group from a data object.
       *
       * @param manager        the content manager to use
       * @param data           the group data object
       */
      private Group(ContentManager manager, GroupData data) {
          super(manager, true);
          this.data = data;
      }
  
      /**
       * Checks if this group equals another object. This method will
       * only return true if the other object is a group with the same
       * domain and group name.
       *
       * @param obj            the object to compare with
       *
       * @return true if the other object is an identical group, or
       *         false otherwise
       */
      public boolean equals(Object obj) {
          if (obj instanceof Group) {
              return equals((Group) obj);
          } else {
              return false;
          }
      }
  
      /**
       * Checks if this group equals another group. This method will
       * only return true if the other object is a group with the same
       * domain and group name.
       *
       * @param obj            the object to compare with
       *
       * @return true if the other object is an identical group, or
       *         false otherwise
       */
      public boolean equals(Group obj) {
          return getDomainName().equals(obj.getDomainName())
              && getName().equals(obj.getName());
      }
  
      /**
       * Returns a string representation of this object.
       *
       * @return a string representation of this object
       */
      public String toString() {
          return getName();
      }
  
      /**
       * Returns the group domain.
       *
       * @return the group domain
       *
       * @throws ContentException if no content manager is available
       */
      public Domain getDomain() throws ContentException {
          return getContentManager().getDomain(getDomainName());
      }
  
      /**
       * Returns the group domain name
       *
       * @return the group domain name
       */
      public String getDomainName() {
          return data.getString(GroupData.DOMAIN);
      }
  
      /**
       * Returns the group name.
       *
       * @return the group name
       */
      public String getName() {
          return data.getString(GroupData.NAME);
      }
  
      /**
       * Returns the group description.
       *
       * @return the group description
       */
      public String getDescription() {
          return data.getString(GroupData.DESCRIPTION);
      }
  
      /**
       * Sets the the group description.
       *
       * @param description    the new group description
       */
      public void setDescription(String description) {
          data.setString(GroupData.DESCRIPTION, description);
      }
  
      /**
       * Checks if this group is public. A public group allows users
       * to add or remove themselves to or from the group. This is used
       * in the template API to allow users administer some of their
       * group memberships. The public groups should not be security
       * related, but only used for other things such as mailing list
       * membership and similar.
       *
       * @return true if this group is public, or
       *         false otherwise
       */
      public boolean isPublic() {
          return data.getBoolean(GroupData.PUBLIC);
      }
  
      /**
       * Sets the public group flag. A public group allows users to add
       * or remove themselves to or from the group. This is used in the
       * template API to allow users administer some of their group
       * memberships. The public groups should not be security related,
       * but only used for other things such as mailing list membership
       * and similar.
       *
       * @param value          the new flag value
       */
      public void setPublic(boolean value) {
          data.setBoolean(GroupData.PUBLIC, value);
      }
  
      /**
       * Returns the group comment.
       *
       * @return the group comment
       */
      public String getComment() {
          return data.getString(GroupData.COMMENT);
      }
  
      /**
       * Sets the group comment.
       *
       * @param comment        the new group comment
       */
      public void setComment(String comment) {
          data.setString(GroupData.COMMENT, comment);
      }
  
      /**
       * Returns the number of users that belong to this group. This
       * method will only count the users registered to this group in
       * the database.
       *
       * @return the number of users that belong to this group
       *
       * @throws ContentException if the database couldn't be accessed
       *             properly
       */
      public int getUserCount() throws ContentException {
          return User.countByGroup(getContentManager(), this);
      }
  
      /**
       * Returns the users that belong to this group. This method will
       * only return the users registered to this group in the database.
       * Also, only a limited interval of the matching users will be
       * returned.
       *
       * @param startPos       the list interval start position
       * @param maxLength      the list interval maximum length
       *
       * @return an array of users belonging to this group
       *
       * @throws ContentException if the database couldn't be accessed
       *             properly
       */
      public User[] getUsers(int startPos, int maxLength)
          throws ContentException {
  
          return User.findByGroup(getContentManager(),
                                  this,
                                  startPos,
                                  maxLength);
      }
  
      /**
       * Adds the specified user to this  group. This action will not
       * take effect until this object is saved.
       *
       * @param user           the user object
       */
      public void addUser(User user) {
          if (getDomainName().equals(user.getDomainName())) {
              if (usersAdded == null) {
                  usersAdded = new ArrayList();
              }
              usersAdded.add(user.getName());
          }
      }
  
      /**
       * Removes the specified user from this group. This action will
       * not take effect until this object is saved.
       *
       * @param user           the user object
       */
      public void removeUser(User user) {
          if (getDomainName().equals(user.getDomainName())) {
              if (usersRemoved == null) {
  