public void remove(int index) {
    if (activeEditors.size() == 0)
      return; // it can get a bit excitable about removing element 0 ...

    PluggableEditor ed = (PluggableEditor) activeEditors.remove(index);
    ed.unload();
    super.remove(index);
  }
 /**
  * Not all editors are capable of displaying new entries. This whips through and removes all
  * editors that can't.
  */
 private void trimNonNewEntryEditors() {
   int size = activeEditors.size();
   for (int i = size - 1; i >= 0; i--) {
     if (((DataSink) activeEditors.get(i)).canCreateEntry() == false) {
       remove(i);
     }
   }
   suggestTableEditor(); // use table editor as default for new entries...
 }
 /** If a purpose written pluggable editor is available, switch to that, */
 public boolean suggestPluggableEditor() {
   for (int i = activeEditors.size() - 1; i >= 0; i--) {
     // try to set to the first 'user written' pluggable editor
     // that can be found...
     PluggableEditor ed = (PluggableEditor) activeEditors.get(i);
     if ((ed != templateDisplay) && (ed != tableDisplay)) {
       setCurrentEditor(ed);
       return true;
     }
   }
   return false;
 }
  /**
   * This can be used to register Swing components that may be used by sub editors to affect the
   * outside environment.
   */
  public void registerComponents(
      JMenuBar menu, JToolBar buttons, JTree tree, JPopupMenu treeMenu, JFrame jxplorer) {
    registerMenu = menu;
    registerButtons = buttons;
    registerTree = tree;
    registerTreeMenu = treeMenu;
    registerJX = jxplorer;

    // reset the sub editors as well.

    for (int i = 0; i < activeEditors.size(); i++) {
      ((PluggableEditor) activeEditors.get(i))
          .registerComponents(menu, buttons, tree, treeMenu, jxplorer);
    }
  }
 /** Adds an editor to the current collection of active editors, and makes it a tab pane. */
 void addEditor(PluggableEditor ed) {
   if (activeEditors.contains(ed) == false) // don't add editors twice!
   {
     add(ed);
     ed.registerComponents(
         registerMenu, registerButtons, registerTree, registerTreeMenu, registerJX);
   }
 }
 // TODO: figure this out...
 public void clearEditors() {
   removeAll();
   activeEditors.removeAllElements();
   templateDisplay.setToDefault();
   addEditor(templateDisplay);
   tableDisplay.displayEntry(null, null);
   addEditor(tableDisplay);
 }
  /**
   * Sets the current editor to the specified editor, loads the current entry, and makes sure that
   * it is visible to the user.
   *
   * @param makeCurrent the editor to select.
   */
  protected void setCurrentEditor(PluggableEditor makeCurrent) {
    currentEditor = makeCurrent;
    if (currentEditor != null && currentEditor.getDataSink() != null)
      currentEditor.getDataSink().displayEntry(entry, dataSource);

    int index = activeEditors.indexOf(makeCurrent);

    if (index == -1) {
      clearPluggableEditors();
      addEditor(makeCurrent);

      setSelectedIndex(activeEditors.indexOf(makeCurrent));

    } else if (index != getSelectedIndex()) {
      setSelectedIndex(index);
    }
  }
  public boolean suggestHTMLEditor() {
    // if we can't find one of those, relapse to the table editor.

    if (activeEditors.contains(templateDisplay) == true) {
      setCurrentEditor(templateDisplay);
      return true;
    }
    return false;
  }
  /**
   * Removes all transient editors, and ensures that the table editor and the html editor are
   * available.
   */
  void clearPluggableEditors() {
    ignoreChangeEvents = true;

    for (int i = activeEditors.size() - 1; i >= 0; i--) {
      PluggableEditor ed = (PluggableEditor) activeEditors.get(i);
      if ((ed != templateDisplay) && (ed != tableDisplay)) {
        remove(i);
      }
    }

    if (activeEditors.contains(templateDisplay) == false) {
      addEditor(templateDisplay);
    }

    if (activeEditors.contains(tableDisplay) == false) {
      addEditor(tableDisplay);
    }

    if (currentEditor != tableDisplay && currentEditor != templateDisplay) {
      suggestHTMLEditor();
    }

    ignoreChangeEvents = false;
  }
  /** Parse Definition Attributes for a LDAP matching rule */
  static LDAPMatchingRuleSchema parseDefAttributes(Attributes attrs) throws NamingException {
    String name = null, oid = null, desc = null, syntax = null;
    boolean obsolete = false;
    Vector applies = new Vector();

    for (Enumeration attrEnum = attrs.getAll(); attrEnum.hasMoreElements(); ) {
      Attribute attr = (Attribute) attrEnum.nextElement();
      String attrName = attr.getID();
      if (attrName.equals(NAME)) {
        name = getSchemaAttrValue(attr);
      } else if (attrName.equals(NUMERICOID)) {
        oid = getSchemaAttrValue(attr);
      } else if (attrName.equals(SYNTAX)) {
        syntax = getSchemaAttrValue(attr);
      } else if (attrName.equals(DESC)) {
        desc = getSchemaAttrValue(attr);
      } else if (attrName.equals(APPLIES)) {
        for (Enumeration valEnum = attr.getAll(); valEnum.hasMoreElements(); ) {
          applies.addElement((String) valEnum.nextElement());
        }
      } else if (attrName.equals(OBSOLETE)) {
        obsolete = parseTrueFalseValue(attr);
      } else {
        throw new NamingException(
            "Invalid schema attribute type for matching rule definition " + attrName);
      }
    }

    LDAPMatchingRuleSchema mrule =
        new LDAPMatchingRuleSchema(name, oid, desc, vectorToStringAry(applies), syntax);

    if (obsolete) {
      mrule.setQualifier(OBSOLETE, "");
    }
    return mrule;
  }
  public void removeAll() {
    int size = activeEditors.size();
    for (int i = size - 1; i >= 0; i--) remove(i);

    super.removeAll(); // XXX this really shouldn't be necessary.
  }
 public void add(PluggableEditor ed, int index) {
   // add(ed.getName(), ed.getDisplayComponent()); // wierd array bounds error thrown here?
   insertTab(ed.getName(), ed.getIcon(), ed.getDisplayComponent(), ed.getToolTip(), index);
   activeEditors.add(index, ed);
 }
  /**
   * Clear out all the old editors, and get new editors corresponding to the new object classes.
   *
   * @param entry the entry to be displayed by all the editors
   * @param ds the datasource the editors may use for more info
   * @param ocs the object classes (in order) to find editors for.
   */
  protected void setEditors(DXEntry entry, DataBrokerQueryInterface ds, Vector ocs) {

    try {
      clearPluggableEditors(); // clear all extra editors

      // search for unique structural editors...

      if ("false".equalsIgnoreCase(JXConfig.getProperty("plugins.ignoreUniqueness"))) {
        if (ocs == null) // TE: may happen if virtual entry.
        return;

        int size = ocs.size();

        for (int i = 0; i < size; i++) {
          Object objectClass = ocs.get(i);
          if (objectClass != null) {
            PluggableEditor ed = getEditor(objectClass.toString());
            if (ed != null && ed.isUnique() == true) // found a unique editor
            { // so clear old ones,
              addUniqueEditor(ed); // and use the unique one
              refreshEditors(entry, ds); // to display the data
              setCurrentEditor(ed);
              return; // ... and exit.
            }
          }
        }
      } else log.warning("skipping uniqueness test for pluggable editors");

      boolean newEdSet = false;

      // search for non-unique structural editors
      for (int i = 0; i < ocs.size(); i++) {
        Object objectClass = ocs.get(i);
        if (objectClass != null) {
          PluggableEditor ed = getEditor(objectClass.toString());
          if (ed != null) {
            addEditor(ed);

            // Force the displayed editor to be the first pluggable one...
            if (newEdSet == false) {
              setCurrentEditor(ed);
              newEdSet = true;
            }
          }
        }
      }

      // search for non-structural editors
      try {
        Attribute allOCs = entry.getAllObjectClasses();
        if (allOCs != null) {
          Enumeration vals = allOCs.getAll();
          while (vals.hasMoreElements()) {
            Object oc = vals.nextElement();
            if (oc != null) {
              String ocName = oc.toString();
              if (ocs.contains(ocName)
                  == false) // don't bother with struct objectclasses dealt with above
              {
                PluggableEditor ed = getEditor(ocName);

                if (ed != null) {
                  addEditor(ed);

                  if (ed.isUnique()) // a special service to users...
                  log.warning(
                        "WARNING: Illegal unique editor defined for oc: "
                            + ocName
                            + " not allowed - (oc not in primary structural inheritance chain)");
                }
              }
            }
          }
        }
      } catch (NamingException e) {
        log.log(
            Level.WARNING,
            "WARNING: non-fatal exception getting object classes for plugin editors. ",
            e);
      }

      addEditor(templateDisplay); // and always add old faithfulls...
      // XXX
      if (entry.getStatus() != DXEntry.NEW) // well, almost always...
      addEditor(tableDisplay);
    } catch (Exception e) {
      log.warning("Unexpected Exception in AttributeDisplay\n" + e);
      e.printStackTrace();
    }
  }
  public void displayEntry(DXEntry dxentry, DataBrokerQueryInterface ds) {
    // Set the local data variables.

    dataSource = ds;
    entry = dxentry;

    // check that the default editors have been initialised.

    if (tableDisplay == null) initTableEditor();
    if (templateDisplay == null) initHTMLEditor();

    // check for a 'no data' display - if there is no data, revert
    // to the default html 'no data' template.

    if (entry
        == null) // || entry.size() == 0) //TE: This is commented out to allow virtual nodes to be
                 // edited.
    {
      if (oldOCSig != null) {
        clearPluggableEditors();

        if (activeEditors.size() == 0) {
          addEditor(templateDisplay);
        }
        oldOCSig = null;
      }
      refreshEditors(null, ds);
    } else {
      dataSource = ds; // may be null...
      Vector ocs = entry.getOrderedOCs();

      // try to create a unique 'signature' for a group of object classes
      // This relies on them being delivered in the same order though.  (Less
      // efficient if they aren't, but otherwise shouldn't be a big problem).
      String newOCSig = new String();

      if (ocs != null)
        for (int i = 0; i < ocs.size(); i++) {
          Object ocSig = ocs.get(i);
          if (ocSig != null) newOCSig += ocSig.toString();
        }

      // Check if signiture hasn't changed.  If it *has* changed,
      // reset the editors using 'setEditors', and update
      // the 'old object class signiture' variable.
      if (newOCSig.equals(oldOCSig) == false) {
        setEditors(entry, ds, ocs);
        oldOCSig = newOCSig;
      }

      // Some quick sanity checks...
      if (entry.getStatus() == DXEntry.NEW) // check for new entries (but *not* NEW_WRITTEN)...
      {
        // don't allow editors to appear that can't edit a new entry
        trimNonNewEntryEditors();
        suggestPluggableEditor();
      } else {
        // make sure that the html template display is around...
        // XXX (a bit of a hack - this should really check that *all*
        // XXX editor that can't handle new entries have been added back...
        // XXX (maybe set flag?)
        // TE: added '&& !currentEditor.isUnique()' b/c this code always made sure the HTML
        // TE: editor is visible, whereas with a unique plugin we only want that one visible...
        // TE: unless of course I am totally confused!  See bug 674.
        if (activeEditors.contains(templateDisplay) == false && !currentEditor.isUnique()) {
          add((PluggableEditor) templateDisplay, 0);
          if (currentEditor != null) // XXX hack hack.
          setCurrentEditor(currentEditor);
        }
      }

      if (activeEditors.contains(currentEditor) == false) {
        suggestPluggableEditor();
      }

      // now that the editor set we're using has been sorted out,
      // actually go and update the editors!  (Nb. this triggers an usaved changes check)
      refreshEditors(entry, ds);
    }
  }