/**
   * Fires an asynchronous call to update the passed group.
   *
   * @param data The object to update.
   * @param asynch Pass <code>true</code> to save data asynchronously, <code>false</code> otherwise.
   */
  void fireAdminSaving(AdminObject data, boolean asynch) {
    SecurityContext c = ctx;
    if (MetadataViewerAgent.isAdministrator()) c = getAdminContext();

    MetadataLoader loader;
    GroupData group = data.getGroup();

    switch (data.getIndex()) {
      case AdminObject.UPDATE_GROUP:
        loaderID++;
        loader =
            new GroupEditor(
                component, c, group, data.getPermissions(), loaderID, GroupEditor.UPDATE);
        loaders.put(loaderID, loader);
        loader.load();
        state = MetadataViewer.SAVING;
        break;
      case AdminObject.UPDATE_EXPERIMENTER:
        loaderID++;
        loader = new AdminEditor(component, c, data.getGroup(), data.getExperimenters(), loaderID);
        loaders.put(loaderID, loader);
        loader.load();
        state = MetadataViewer.SAVING;
    }
  }
 /**
  * Returns <code>true</code> if the user is an administrator, <code>false</code> otherwise.
  *
  * @return See above.
  */
 private boolean isUserAdministrator() {
   ExperimenterData user = (ExperimenterData) model.getRefObject();
   ExperimenterData loggedInUser = MetadataViewerAgent.getUserDetails();
   if (user.getId() == loggedInUser.getId()) return MetadataViewerAgent.isAdministrator();
   List<GroupData> groups = user.getGroups();
   Iterator<GroupData> i = groups.iterator();
   GroupData g;
   while (i.hasNext()) {
     g = i.next();
     if (GroupData.SYSTEM.equals(g.getName())) return true;
   }
   return false;
 }
 /** Builds and lays out the UI. */
 void buildGUI() {
   removeAll();
   initComponents();
   setLayout(new GridBagLayout());
   GridBagConstraints c = new GridBagConstraints();
   c.fill = GridBagConstraints.HORIZONTAL;
   c.anchor = GridBagConstraints.WEST;
   c.insets = new Insets(0, 2, 2, 0);
   c.gridx = 0;
   c.gridy = 0;
   c.gridwidth = GridBagConstraints.RELATIVE; // next-to-last
   c.weightx = 1.0;
   add(buildContentPanel(), c);
   if (model.isUserOwner(model.getRefObject()) || MetadataViewerAgent.isAdministrator()) {
     c.gridy++;
     add(Box.createVerticalStrut(5), c);
     c.gridy++;
     add(buildPasswordPanel(), c);
   }
 }
 /**
  * Returns the security context.
  *
  * @return See above.
  */
 SecurityContext getAdminContext() {
   if (MetadataViewerAgent.isAdministrator()) return MetadataViewerAgent.getAdminContext();
   return null;
 }
 /**
  * Fires an asynchronous call to modify the default group of the logged in experimenter.
  *
  * @param group
  */
 void fireChangeGroup(GroupData group) {
   SecurityContext c = ctx;
   if (MetadataViewerAgent.isAdministrator()) c = getAdminContext();
   MetadataLoader loader = new GroupEditor(component, c, group, loaderID, GroupEditor.CHANGE);
   loader.load();
 }
  /**
   * Returns the experimenter to save.
   *
   * @return See above.
   */
  Object getExperimenterToSave() {
    ExperimenterData original = (ExperimenterData) model.getRefObject();
    // Required fields first

    String v = loginArea.getText();
    if (v == null || v.trim().length() == 0) showRequiredField();
    original.setLastName(v);
    JTextField f = items.get(EditorUtil.EMAIL);
    v = f.getText();
    if (v == null || v.trim().length() == 0) v = ""; // showRequiredField();
    original.setEmail(v);
    f = items.get(EditorUtil.INSTITUTION);
    v = f.getText();
    if (v == null) v = "";
    original.setInstitution(v.trim());
    f = items.get(EditorUtil.LAST_NAME);
    v = f.getText();
    if (v == null) v = "";
    original.setLastName(v.trim());

    f = items.get(EditorUtil.FIRST_NAME);
    v = f.getText();
    if (v == null) v = "";
    original.setFirstName(v.trim());

    f = items.get(EditorUtil.MIDDLE_NAME);
    v = f.getText();
    if (v == null) v = "";
    original.setMiddleName(v.trim());

    // set the groups
    GroupData g = null;
    /*

     	if (selectedIndex != originalIndex) {
     		if (selectedIndex < groupData.length)
     			g = groupData[selectedIndex];
     		ExperimenterData user = (ExperimenterData) model.getRefObject();
     		List userGroups = user.getGroups();
     		List<GroupData> newGroups = new ArrayList<GroupData>();
     		if (g != null) newGroups.add(g);
     		Iterator i = userGroups.iterator();
     		long id = -1;
     		if (g != null) id = g.getId();
     		GroupData group;
     		while (i.hasNext()) {
    	group = (GroupData) i.next();
    	if (group.getId() != id)
    		newGroups.add(group);
    }
     		//Need to see what to do b/c no ExperimenterGroupMap
     		original.setGroups(newGroups);
     	}
     	*/
    String value = loginArea.getText().trim();
    UserCredentials uc = new UserCredentials(value, "");
    Boolean b = ownerBox.isSelected();
    // if (g == null) g = original.getDefaultGroup();
    boolean a = false;
    if (b.compareTo(groupOwner) != 0) {
      a = true;
      uc.setOwner(b);
      Object parent = model.getParentRootObject();
      if (parent instanceof GroupData) {
        Map<GroupData, Boolean> map = new HashMap<GroupData, Boolean>();
        map.put((GroupData) parent, b);
        uc.setGroupsOwner(map);
      }
    }
    if (adminBox.isVisible()) {
      b = adminBox.isSelected();
      if (b.compareTo(admin) != 0) {
        a = true;
        uc.setAdministrator(b);
      }
    }
    if (activeBox.isVisible()) {
      b = activeBox.isSelected();
      if (b.compareTo(active) != 0) {
        a = true;
        uc.setActive(b);
      }
    }
    if (!original.getUserName().equals(value)) a = true;
    // if admin
    if (MetadataViewerAgent.isAdministrator()) a = true;
    if (a) {
      Map<ExperimenterData, UserCredentials> m = new HashMap<ExperimenterData, UserCredentials>();
      m.put(original, uc);
      AdminObject object = new AdminObject(g, m, AdminObject.UPDATE_EXPERIMENTER);
      return object;
    }
    return original; // newOne;
  }
  /**
   * Builds the UI component hosting the UI component used to modify the password.
   *
   * @return See above.
   */
  private JPanel buildPasswordPanel() {
    JPanel content = new JPanel();
    content.setBackground(UIUtilities.BACKGROUND_COLOR);
    Registry reg = MetadataViewerAgent.getRegistry();
    String ldap = (String) reg.lookup(LookupNames.USER_AUTHENTICATION);
    if (ldap != null && ldap.length() > 0) {
      content.setBorder(BorderFactory.createTitledBorder("LDAP Authentication"));
      content.setLayout(new FlowLayout(FlowLayout.LEFT));
      content.add(new JLabel(ldap));
      return content;
    }
    content.setBorder(BorderFactory.createTitledBorder("Change Password"));

    content.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    c.fill = GridBagConstraints.HORIZONTAL;
    c.anchor = GridBagConstraints.WEST;
    c.insets = new Insets(0, 2, 2, 0);
    c.gridx = 0;
    c.gridy = 0;
    c.gridwidth = GridBagConstraints.RELATIVE; // next-to-last
    c.fill = GridBagConstraints.NONE; // reset to default
    c.weightx = 0.0;
    if (MetadataViewerAgent.isAdministrator()) {
      content.add(UIUtilities.setTextFont(PASSWORD_NEW), c);
      c.gridx++;
      c.gridwidth = GridBagConstraints.REMAINDER; // end row
      c.fill = GridBagConstraints.HORIZONTAL;
      c.weightx = 1.0;
      content.add(passwordNew, c);
    } else {
      content.add(UIUtilities.setTextFont(PASSWORD_OLD), c);
      c.gridx++;
      c.gridwidth = GridBagConstraints.REMAINDER; // end row
      c.fill = GridBagConstraints.HORIZONTAL;
      c.weightx = 1.0;
      content.add(oldPassword, c);
      c.gridy++;
      c.gridx = 0;
      c.gridwidth = GridBagConstraints.RELATIVE; // next-to-last
      c.fill = GridBagConstraints.NONE; // reset to default
      c.weightx = 0.0;
      content.add(UIUtilities.setTextFont(PASSWORD_NEW), c);
      c.gridx++;
      c.gridwidth = GridBagConstraints.REMAINDER; // end row
      c.fill = GridBagConstraints.HORIZONTAL;
      c.weightx = 1.0;
      content.add(passwordNew, c);
      c.gridy++;
      c.gridx = 0;
      c.gridwidth = GridBagConstraints.RELATIVE; // next-to-last
      c.fill = GridBagConstraints.NONE; // reset to default
      c.weightx = 0.0;
      content.add(UIUtilities.setTextFont(PASSWORD_CONFIRMATION), c);
      c.gridx++;
      c.gridwidth = GridBagConstraints.REMAINDER; // end row
      c.fill = GridBagConstraints.HORIZONTAL;
      c.weightx = 1.0;
      content.add(passwordConfirm, c);
      c.gridy++;
      c.gridx = 0;
    }

    JPanel p = new JPanel();
    p.setBackground(UIUtilities.BACKGROUND_COLOR);
    p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
    p.add(content);
    JPanel buttonPanel = UIUtilities.buildComponentPanel(passwordButton);
    buttonPanel.setBackground(UIUtilities.BACKGROUND_COLOR);
    p.add(buttonPanel);
    return p;
  }
  /**
   * Builds the panel hosting the user's details.
   *
   * @return See above.
   */
  private JPanel buildContentPanel() {
    ExperimenterData user = (ExperimenterData) model.getRefObject();
    boolean editable = model.isUserOwner(user);
    if (!editable) editable = model.isGroupLeader() || MetadataViewerAgent.isAdministrator();
    details = EditorUtil.convertExperimenter(user);
    JPanel content = new JPanel();
    content.setBorder(BorderFactory.createTitledBorder("Profile"));
    content.setBackground(UIUtilities.BACKGROUND_COLOR);
    Entry entry;
    Iterator i = details.entrySet().iterator();
    JComponent label;
    JTextField area;
    String key, value;
    content.setLayout(new GridBagLayout());
    GridBagConstraints c = new GridBagConstraints();
    c.fill = GridBagConstraints.HORIZONTAL;
    c.anchor = GridBagConstraints.WEST;
    c.insets = new Insets(0, 2, 2, 0);
    // Add log in name but cannot edit.
    c.gridx = 0;
    c.gridy = 0;
    c.gridwidth = GridBagConstraints.REMAINDER; // end row
    c.fill = GridBagConstraints.HORIZONTAL;
    content.add(userPicture, c);
    c.gridy++;
    c.gridx = 0;
    label = EditorUtil.getLabel(EditorUtil.DISPLAY_NAME, true);
    label.setBackground(UIUtilities.BACKGROUND_COLOR);
    c.gridwidth = GridBagConstraints.RELATIVE; // next-to-last
    c.fill = GridBagConstraints.NONE; // reset to default
    c.weightx = 0.0;
    content.add(label, c);
    c.gridx++;
    content.add(Box.createHorizontalStrut(5), c);
    c.gridx++;
    c.gridwidth = GridBagConstraints.REMAINDER; // end row
    c.fill = GridBagConstraints.HORIZONTAL;
    c.weightx = 1.0;
    loginArea.setText(user.getUserName());
    loginArea.getDocument().addDocumentListener(this);
    content.add(loginArea, c);
    while (i.hasNext()) {
      ++c.gridy;
      c.gridx = 0;
      entry = (Entry) i.next();
      key = (String) entry.getKey();
      value = (String) entry.getValue();
      label = EditorUtil.getLabel(key, false);
      area = new JTextField(value);
      area.setBackground(UIUtilities.BACKGROUND_COLOR);
      area.setEditable(editable);
      area.setEnabled(editable);
      if (editable) area.getDocument().addDocumentListener(this);
      items.put(key, area);
      label.setBackground(UIUtilities.BACKGROUND_COLOR);
      c.gridwidth = GridBagConstraints.RELATIVE; // next-to-last
      c.fill = GridBagConstraints.NONE; // reset to default
      c.weightx = 0.0;
      content.add(label, c);
      c.gridx++;
      content.add(Box.createHorizontalStrut(5), c);
      c.gridx++;
      c.gridwidth = GridBagConstraints.REMAINDER; // end row
      c.fill = GridBagConstraints.HORIZONTAL;
      c.weightx = 1.0;
      content.add(area, c);
    }
    c.gridx = 0;
    c.gridy++;
    label = EditorUtil.getLabel(EditorUtil.DEFAULT_GROUP, false);
    c.gridwidth = GridBagConstraints.RELATIVE; // next-to-last
    c.fill = GridBagConstraints.NONE; // reset to default
    c.weightx = 0.0;
    content.add(label, c);
    c.gridx++;
    content.add(Box.createHorizontalStrut(5), c);
    c.gridx++;
    c.gridwidth = GridBagConstraints.REMAINDER; // end row
    c.fill = GridBagConstraints.HORIZONTAL;
    c.weightx = 1.0;
    content.add(groupLabel, c);
    c.gridy++;
    content.add(permissionsPane, c);

    // content.add(groups, c);

    c.gridx = 0;
    c.gridy++;
    label = EditorUtil.getLabel(EditorUtil.GROUP_OWNER, false);
    c.gridwidth = GridBagConstraints.RELATIVE; // next-to-last
    c.fill = GridBagConstraints.NONE; // reset to default
    c.weightx = 0.0;
    content.add(label, c);
    c.gridx++;
    content.add(Box.createHorizontalStrut(5), c);
    c.gridx++;
    c.gridwidth = GridBagConstraints.REMAINDER; // end row
    c.fill = GridBagConstraints.HORIZONTAL;
    c.weightx = 1.0;
    content.add(ownerBox, c);
    if (activeBox.isVisible()) {
      c.gridx = 0;
      c.gridy++;
      label = EditorUtil.getLabel(EditorUtil.ACTIVE, false);
      c.gridwidth = GridBagConstraints.RELATIVE; // next-to-last
      c.fill = GridBagConstraints.NONE; // reset to default
      c.weightx = 0.0;
      content.add(label, c);
      c.gridx++;
      content.add(Box.createHorizontalStrut(5), c);
      c.gridx++;
      c.gridwidth = GridBagConstraints.REMAINDER; // end row
      c.fill = GridBagConstraints.HORIZONTAL;
      c.weightx = 1.0;
      content.add(activeBox, c);
    }
    if (adminBox.isVisible()) {
      c.gridx = 0;
      c.gridy++;
      label = EditorUtil.getLabel(EditorUtil.ADMINISTRATOR, false);
      c.gridwidth = GridBagConstraints.RELATIVE; // next-to-last
      c.fill = GridBagConstraints.NONE; // reset to default
      c.weightx = 0.0;
      content.add(label, c);
      c.gridx++;
      content.add(Box.createHorizontalStrut(5), c);
      c.gridx++;
      c.gridwidth = GridBagConstraints.REMAINDER; // end row
      c.fill = GridBagConstraints.HORIZONTAL;
      c.weightx = 1.0;
      content.add(adminBox, c);
    }
    c.gridx = 0;
    c.gridy++;
    content.add(Box.createHorizontalStrut(10), c);
    c.gridy++;
    label = UIUtilities.setTextFont(EditorUtil.MANDATORY_DESCRIPTION, Font.ITALIC);
    label.setForeground(UIUtilities.REQUIRED_FIELDS_COLOR);
    c.weightx = 0.0;
    content.add(label, c);
    return content;
  }
  /** Initializes the components composing this display. */
  private void initComponents() {
    admin = false;
    active = false;
    groupOwner = false;

    userPicture = new UserProfileCanvas();
    userPicture.setBackground(UIUtilities.BACKGROUND_COLOR);
    userPicture.setToolTipText("Click to upload your picture.");
    IconManager icons = IconManager.getInstance();
    userPicture.setImage(icons.getImageIcon(IconManager.USER_PHOTO_32).getImage());
    loginArea = new JTextField();
    boolean a = MetadataViewerAgent.isAdministrator();
    loginArea.setEnabled(a);
    loginArea.setEditable(a);
    adminBox = new JCheckBox();
    adminBox.setVisible(false);
    adminBox.setBackground(UIUtilities.BACKGROUND_COLOR);
    ownerBox = new JCheckBox();
    ownerBox.setBackground(UIUtilities.BACKGROUND_COLOR);
    activeBox = new JCheckBox();
    activeBox.setBackground(UIUtilities.BACKGROUND_COLOR);
    activeBox.setVisible(false);
    passwordButton = new JButton("Change password");
    passwordButton.setEnabled(false);
    passwordButton.setBackground(UIUtilities.BACKGROUND_COLOR);
    passwordButton.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            changePassword();
          }
        });
    manageButton = new JButton("Group");
    manageButton.setEnabled(false);
    manageButton.setBackground(UIUtilities.BACKGROUND_COLOR);
    manageButton.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            manageGroup();
          }
        });
    passwordNew = new JPasswordField();
    passwordNew.setBackground(UIUtilities.BACKGROUND_COLOR);
    passwordConfirm = new JPasswordField();
    passwordConfirm.setBackground(UIUtilities.BACKGROUND_COLOR);
    oldPassword = new JPasswordField();
    oldPassword.setBackground(UIUtilities.BACKGROUND_COLOR);
    items = new HashMap<String, JTextField>();
    ExperimenterData user = (ExperimenterData) model.getRefObject();
    GroupData defaultGroup = user.getDefaultGroup();

    permissionsPane =
        new PermissionsPane(defaultGroup.getPermissions(), UIUtilities.BACKGROUND_COLOR);
    permissionsPane.disablePermissions();
    groupLabel = new JLabel(defaultGroup.getName());
    groupLabel.setBackground(UIUtilities.BACKGROUND_COLOR);

    long groupID = defaultGroup.getId();
    boolean owner = false;
    /*
    if (defaultGroup.getLeaders() != null)
    	owner = setGroupOwner(defaultGroup);
    else {
    	GroupData g = model.loadGroup(groupID);
    	if (g != null)
    		owner = setGroupOwner(g);
    }
    */
    Object parentRootObject = model.getParentRootObject();
    if (parentRootObject instanceof GroupData) {
      owner = setGroupOwner((GroupData) parentRootObject);
    }
    // Build the array for box.
    /*
    Iterator i = userGroups.iterator();
    GroupData g;

    List<GroupData> validGroups = new ArrayList<GroupData>();
    while (i.hasNext()) {
    	g = (GroupData) i.next();
    	if (model.isValidGroup(g))
    		validGroups.add(g);
    }
    groupData = new GroupData[validGroups.size()];
    admin = false;
    active = false;
    int selectedIndex = 0;
    int index = 0;
    i = validGroups.iterator();
    boolean owner = false;
    while (i.hasNext()) {
    	g = (GroupData) i.next();
    	groupData[index] = g;
    	if (g.getId() == groupID) {
    		if (g.getLeaders() != null) {
    			owner = setGroupOwner(g);
    			originalIndex = index;
    		}
    	}
    	index++;
    }
    selectedIndex = originalIndex;
    groups = EditorUtil.createComboBox(groupData, 0);
    groups.setEnabled(false);
    groups.setRenderer(new GroupsRenderer());
    if (groupData.length != 0)
    	groups.setSelectedIndex(selectedIndex);
    */

    if (MetadataViewerAgent.isAdministrator()) {
      // Check that the user is not the one currently logged.
      oldPassword.setVisible(false);
      owner = true;
      adminBox.setVisible(true);
      activeBox.setVisible(true);
      adminBox.addChangeListener(this);
      active = user.isActive();
      activeBox.setSelected(active);
      activeBox.setEnabled(!model.isSelf());
      activeBox.addChangeListener(this);
      // indicate if the user is an administrator.a
      admin = isUserAdministrator();
      adminBox.setSelected(admin);
      ownerBox.addChangeListener(this);
      // admin = false;
      // Now check if the user is the last administrator
    } else {
      ownerBox.setEnabled(false);
      passwordConfirm
          .getDocument()
          .addDocumentListener(
              new DocumentListener() {

                /**
                 * Allows the user to interact with the password controls depending on the value
                 * entered.
                 *
                 * @see DocumentListener#removeUpdate(DocumentEvent)
                 */
                public void removeUpdate(DocumentEvent e) {
                  handlePasswordEntered();
                }

                /**
                 * Allows the user to interact with the password controls depending on the value
                 * entered.
                 *
                 * @see DocumentListener#insertUpdate(DocumentEvent)
                 */
                public void insertUpdate(DocumentEvent e) {
                  handlePasswordEntered();
                }

                /**
                 * Required by the {@link DocumentListener} I/F but no-operation implementation in
                 * our case.
                 *
                 * @see DocumentListener#changedUpdate(DocumentEvent)
                 */
                public void changedUpdate(DocumentEvent e) {}
              });
    }
    passwordNew
        .getDocument()
        .addDocumentListener(
            new DocumentListener() {

              /**
               * Allows the user to interact with the password controls depending on the value
               * entered.
               *
               * @see DocumentListener#removeUpdate(DocumentEvent)
               */
              public void removeUpdate(DocumentEvent e) {
                handlePasswordEntered();
              }

              /**
               * Allows the user to interact with the password controls depending on the value
               * entered.
               *
               * @see DocumentListener#insertUpdate(DocumentEvent)
               */
              public void insertUpdate(DocumentEvent e) {
                handlePasswordEntered();
              }

              /**
               * Required by the {@link DocumentListener} I/F but no-operation implementation in our
               * case.
               *
               * @see DocumentListener#changedUpdate(DocumentEvent)
               */
              public void changedUpdate(DocumentEvent e) {}
            });
    ExperimenterData logUser = MetadataViewerAgent.getUserDetails();
    if (user.getId() == logUser.getId()) {
      userPicture.addMouseListener(
          new MouseAdapter() {

            /** Brings up a chooser to load the user image. */
            public void mouseReleased(MouseEvent e) {
              uploadPicture();
            }
          });
    }
  }