private void myPostInit() {
    modelDataTypes = new HashMap<String, DataType>();
    List<DataType> dataTypes = ModelHelper.getModelDataTypes(diagramManager.getCurrentProject());
    for (DataType item : dataTypes) {
      modelDataTypes.put(item.getName(), item);
    }

    TableColumn typeColumn = table.getColumnModel().getColumn(1);
    typeColumn.setCellEditor(createEditor(modelDataTypes.keySet().toArray()));

    TableColumn typeColumn2 = table.getColumnModel().getColumn(2);
    typeColumn2.setCellEditor(createEditor(new String[] {"1", "0..1", "0..*", "1..*"}));

    table.setSurrendersFocusOnKeystroke(true);

    if (element instanceof DataType) {
      DataType dataType = (DataType) element;
      for (Property attribute : dataType.getAttribute()) {
        attributesTableModel.addEntry(attribute);
      }
    } else {
      Class umlclass = (Class) element;
      for (Property attribute : umlclass.getAttribute()) {
        attributesTableModel.addEntry(attribute);
      }
    }
  }
  /** Opens a dialog that displays the operational attributes of the current entry. */
  public void displayOperationalAttributes() {
    JXplorerBrowser jx = null;

    if (owner instanceof JXplorerBrowser) jx = (JXplorerBrowser) owner;
    else return;

    showingOperationalAttributes = !showingOperationalAttributes;

    // EJP 17 August 2010.
    // CB 14 August 2012 - some directories (looking at you Active Directory) don't support the '+'
    // operator... so do it manually as well...
    String[] opAttrs = {
      "+",
      "createTimeStamp",
      "creatorsName",
      "entryFlags",
      "federationBoundary",
      "localEntryID",
      "modifiersName",
      "modifyTimeStamp",
      "structuralObjectClass",
      "subordinateCount",
      "subschemaSubentry"
    };
    DXEntry entry = null;

    if (showingOperationalAttributes) {
      try {
        entry = (jx.getSearchBroker()).unthreadedReadEntry(currentDN, opAttrs);
        StringBuffer buffy = new StringBuffer("DN: " + currentDN.toString() + "\n\n");

        // Get the attribute values...
        // EJP 17 August 2010: use the actual attributes returned.
        NamingEnumeration ne = null;

        try {
          ne = entry.getAll();
          while (ne.hasMore()) {
            DXAttribute att = (DXAttribute) ne.next();
            buffy.append(att.getName() + ": " + att.get().toString() + "\n");

            tableData.insertOperationalAttribute(att);
          }
        } finally {
          if (ne != null) ne.close();
        }

        tableData.fireTableDataChanged();
      } catch (NamingException e) {
        CBUtility.error(
            TableAttributeEditor.this, CBIntText.get("Unable to read entry " + currentDN), e);
      }
    } else {
      tableData.removeOperationalAttributes();
      tableData.fireTableDataChanged();
    }
  }
  /** Writes the data currently in the table editor to the directory. */
  public void writeTableData() {

    myEditor.stopCellEditing();

    if (dataSource == null) // if ds is null, data is not modifiable...
    {
      CBUtility.error("no datasource to write data to in writeTableData()");
      return;
    } // shouldn't happen

    DXEntry oldEntry = tableData.getOldEntry();

    DXEntry newEntry = tableData.getNewEntry();

    /*   Check to see if major surgery is needed - whether the user has been
     *   messing with the object class list. */

    if (classChangedOriginalEntry != null) {

      // use the saved state of the pre-class-changed entry as the 'old entry'
      // state.
      oldEntry = classChangedOriginalEntry;
      classChangedOriginalEntry =
          null; // this is only used once! (either the object class change will
      // now succeed, or fail - either way, the entry state is reset to
      // match what's in the directory.)

      if (objectClassesChanged(oldEntry, newEntry)) {
        oldEntry.removeEmptyAttributes();

        newEntry.setStatus(oldEntry.getStatus());

        Object[] delSet =
            CBArray.difference(oldEntry.toIDStringArray(), newEntry.toIDStringArray());

        /* if there *are* attributes that should no longer exist, delete them by adding them (blanked)
         * to the complete 'newAtts' set of *all* known attributes. */

        if ((delSet != null) && (delSet.length > 0)) {
          for (int i = 0; i < delSet.length; i++) {
            newEntry.put(
                new DXAttribute(
                    delSet[i].toString())); // overwrite old values with an empty attribute
          }
        }
      }
    }

    dataSource.modifyEntry(oldEntry, newEntry);
  }
 private void moveDownAttribute() {
   int row = table.getSelectedRow();
   if (row >= 0 && row < table.getRowCount()) {
     attributesTableModel.moveDownEntry(row);
     table.setRowSelectionInterval(row + 1, row + 1);
   }
 }
  // Data Modification
  @Override
  public void newAttribute(
      String key, Object value, boolean isReadOnly, AttributeTableModel model) {
    AttributeContainer node = view.tree;

    if (node == null) {
      return;
    }

    model.keys.add(key);
    model.values.add(value);
    model.readOnly.add(new Boolean(isReadOnly));

    node.setAttribute(key, value);

    OutlinerDocument doc = view.tree.getDocument();
    doc.setModified(true);

    // undo
    Undoable undoable =
        new UndoableDocumentAttributeChange(view.tree, null, null, false, key, value, isReadOnly);
    undoable.setName("New Document Attribute");
    doc.getUndoQueue().add(undoable);

    model.fireTableDataChanged();
  }
  // Set Value
  @Override
  public void setValueAt(Object value, int row, AttributeTableModel model) {
    AttributeContainer node = view.tree;

    if (node == null) {
      return;
    }

    String key = (String) model.keys.get(row);

    boolean readOnly = node.isReadOnly(key);

    Object oldValue = node.getAttribute(key);

    model.values.set(row, value);
    node.setAttribute(key, value);

    OutlinerDocument doc = view.tree.getDocument();
    doc.setModified(true);

    // undo
    Undoable undoable =
        new UndoableDocumentAttributeChange(
            view.tree, key, oldValue, readOnly, key, value, readOnly);
    undoable.setName("Edit Document Attribute");
    doc.getUndoQueue().add(undoable);

    model.fireTableDataChanged();
  }
  /**
   * This notifies the user that they are about to lose entered data (i.e. they've made changes and
   * are about to a) change classes or b) go to another entry), and allows them to save their data
   * if they so choose...
   */
  public void checkForUnsavedChanges() {
    if (dataSource == null || dataSource.isActive() == false)
      return; // no point prompting - nothing to save with!

    /*
     *    Only ever check the entry once (sometimes promptForSave can be called
     *    multiple time - remember that the 'save' function gets called by a
     *    separate thread).
     */

    if (tableData.changedByUser()) {
      String save = CBIntText.get("Save");
      String discard = CBIntText.get("Discard");

      int result =
          JOptionPane.showOptionDialog(
              owner,
              CBIntText.get("Submit changes to the Directory?"),
              CBIntText.get("Save Data"),
              JOptionPane.DEFAULT_OPTION,
              JOptionPane.QUESTION_MESSAGE,
              null,
              new Object[] {save, discard},
              save);
      if (result == 0) {
        writeTableData(); // nb - this queues a request to the directory
      }
    }
  }
  // Delete Attribute
  @Override
  public void deleteAttribute(int row, AttributeTableModel model) {
    AttributeContainer node = view.tree;

    if (node == null) {
      return;
    }

    String key = (String) model.keys.get(row);

    Object oldValue = node.getAttribute(key);
    boolean oldReadOnly = node.isReadOnly(key);

    node.removeAttribute(key);
    model.keys.remove(row);
    model.values.remove(row);
    model.readOnly.remove(row);

    OutlinerDocument doc = view.tree.getDocument();
    doc.setModified(true);

    // undo
    Undoable undoable =
        new UndoableDocumentAttributeChange(
            view.tree, key, oldValue, oldReadOnly, null, null, false);
    undoable.setName("Delete Document Attribute");
    doc.getUndoQueue().add(undoable);

    model.fireTableRowsDeleted(row, row);
  }
  // Toggle Editability
  @Override
  public void toggleEditability(int row, AttributeTableModel model) {
    AttributeContainer node = view.tree;

    if (node == null) {
      return;
    }

    String key = (String) model.keys.get(row);
    Object oldAndNewValue = node.getAttribute(key);

    boolean oldReadOnly = node.isReadOnly(key);
    boolean readOnly = !oldReadOnly;

    boolean oldValue = true;
    ImageIcon isReadOnly = (ImageIcon) model.getValueAt(row, 1);
    if (isReadOnly == OutlineEditableIndicator.ICON_IS_NOT_PROPERTY) {
      oldValue = true;
    } else {
      oldValue = false;
    }

    // boolean oldValue = ((Boolean) model.getValueAt(row, 1)).booleanValue();
    boolean newValue = !oldValue;
    model.readOnly.set(row, new Boolean(newValue));
    node.setReadOnly(key, newValue);

    OutlinerDocument doc = view.tree.getDocument();
    doc.setModified(true);

    // undo
    Undoable undoable =
        new UndoableDocumentAttributeChange(
            view.tree, key, oldAndNewValue, oldReadOnly, key, oldAndNewValue, readOnly);
    undoable.setName("Toggle Document Attribute Editability");
    doc.getUndoQueue().add(undoable);

    model.fireTableDataChanged();
  }
  public void setVisible(boolean state) {
    super.setVisible(state);

    // has to be *after* previous call for SwingMagic reasons.
    if (state == false
        && tableData.changedByUser()) // user made changes - were they saved?  (i.e., are we
    {
      /*
       *    The setVisible() method may be called multiple time.  Only prompt
       *    the user the first time.
       */
      checkForUnsavedChanges();
    }
  }
  public void transferAttributesData() {
    List<Property> classAttributes = attributesTableModel.getEntries();

    if (cbxVisible.isSelected() == false) {
      if (classAttributes.size() > 0) {
        cbxVisible.setSelected(true);
      }
    }
    if (classElement != null) classElement.setShowAttributes(cbxVisible.isSelected());
    diagramManager.updateOLEDFromInclusion(element);

    transferDataTypes();
    deleteAttributes(classAttributes);
    transferAddedAttributes(classAttributes);

    classElement.reinitAttributesCompartment();
    classElement.invalidate();
  }
  /** Kicks off the entry modify/update & checks for manditory attributes. */
  public void doSubmit() {
    if (dataSource == null) {
      CBUtility.error("No dataSource available to write changes to in Table Attribute Editor");
      return;
    }

    myEditor.stopCellEditing();

    // If schema checking is on, make sure that all mandatory attributes are filled in.
    if ("false".equalsIgnoreCase(JXConfig.getProperty("option.ignoreSchemaOnSubmission"))
        && (tableData.checkMandatoryAttributesSet() == false)) {
      CBUtility.error(
          TableAttributeEditor.this,
          CBIntText.get("All Mandatory Attributes must have values!"),
          null);
      return;
    }

    writeTableData();
  }
  private void transferDataTypes() {
    List<Property> classAttributes = attributesTableModel.getEntries();
    ArrayList<Element> createdList = new ArrayList<Element>();
    for (Property property : classAttributes) {
      // Avoid the creation of duplicated types
      if (modelDataTypes.keySet().contains(property.getType().getName().trim()) == false) {
        UmlProject project = diagramManager.getCurrentProject();
        AddCommand cmd =
            new AddCommand(
                project.getEditingDomain(),
                project.getModel().getPackagedElement(),
                property.getType());
        project.getEditingDomain().getCommandStack().execute(cmd);
        modelDataTypes.put(property.getType().getName(), (DataType) property.getType());
        createdList.add((Element) property.getType());
      }
    }

    for (Element element : createdList) diagramManager.updateOLEDFromInclusion(element);
  }
 public void refreshData() {
   attributesTableModel.fireTableDataChanged();
 }
  private void displayEntry(
      DXEntry entry, DataBrokerQueryInterface ds, boolean storeOriginalEntry) {
    myEditor.stopCellEditing();

    //        checkedDN = null; // hack - resets promptForSave.
    // Store original Entry for reset
    if (entry != null && storeOriginalEntry && entry.getStatus() == DXEntry.NORMAL)
      originalEntry = new DXEntry(entry);

    // Set the globals...
    currentEntry = entry;
    dataSource = ds;

    if (entry != null && entry.size() == 0) {
      // If there is an entry and its size is zero - it's probably a virtual entry.
      // We need to give the user the option of adding an object class to it i.e. so that
      // it can be added to the directory as a real entry.
      //
      // Disable all the buttons except the 'Change Class' button - but rename this button
      // to 'Add Class' so the user hopefully has a bit more of an idea about what is going on.

      // Sets editor to a blank screen...
      tableData.clear();

      // Disable all buttons except the 'Change Class' button - rename this one...
      submit.setEnabled(false);
      reset.setEnabled(false);
      changeClass.setText(CBIntText.get("Add Class"));
      changeClass.setEnabled(true);
      opAttrs.setEnabled(false);

      virtualEntry = true;

      return;
    }

    virtualEntry = false;

    // Isn't a virtual entry...
    if (entry != null) currentDN = entry.getDN();

    // May have been changed to 'Add Class'...
    changeClass.setText(CBIntText.get("Change Class"));

    // Some quick faffing around, to see if we're coming back from a
    // change classes operation.
    if (classChangedOriginalEntry != null) {
      // If they have the same name, then we're reviewing the same entry - otherwise we've moved on
      if (entry == null || entry.getDN().equals(classChangedOriginalEntry.getDN()) == false)
        classChangedOriginalEntry = null;
    }

    /*
     *    Check that we're not displaying a new entry, and leaving unsaved changes
     *    behind.
     *
     *    This turns out to be quite tricky, and involves a bunch 'o special cases.
     *
     *    First check whether the table data has changed (if not, do nothing)
     *    ->  if the new entry is null, prompt user to save
     *    ->  OR if the DN has changed, and it wasn't due to a rename, prompt user to save
     *
     */
    if (tableData.changedByUser()) // user made changes - were they saved?  (i.e., are we
    { // displaying the result of those changes?)
      boolean prompt = false;

      DXEntry oldEntry = tableData.getOldEntry();

      if (oldEntry != null) {
        /*
         *    The code below is simply checking to see if the name of the
         *    new entry is different from the old entry, and if it is,
         *    whether that's due to the old entry being renamed.
         */
        if (entry == null) {
          prompt = true;
        }
        // TE: added the isEmpty check see bug: 3194.
        else if (!oldEntry.getDN().isEmpty() && entry.getDN().equals(oldEntry.getDN()) == false) {
          DN oldParent = oldEntry.getDN().getParent();

          DN newParent = entry.getDN().getParent();

          if (oldParent.equals(newParent) == false) {
            prompt = true;
          } else {
            if (entry.getDN().getLowestRDN().equals(tableData.getRDN()) == false) {
              prompt = true;
            }
          }
        }

        if (prompt) // yes, there is a risk of data loss - prompt the user.
        {
          checkForUnsavedChanges(); // see if the user wants to save their data
        }
      }
    }

    myEditor.setDataSource(
        ds); // Sets the DataBrokerQueryInterface in AttributeValueCellEditor used to get the syntax
             // of attributes.

    // only enable buttons if DataBrokerQueryInterface
    // is valid *and* we can modify data...

    if (dataSource == null || entry == null || dataSource.isModifiable() == false) {
      setReadWrite(false, entry);
    } else {
      setReadWrite(true, entry);
    }

    //        myEditor.stopCellEditing();

    if (entry != null) {
      entry.expandAllAttributes();
      currentDN = entry.getDN();

      tableData.insertAttributes(entry);
      popupTableTool.setDN(currentDN); // Sets the DN in SmartPopupTableTool.
      myEditor.setDN(
          currentDN); // Sets the DN in the attributeValueCellEditor which can be used to identify
                      // the entry that is being modified/
    } else {
      tableData.clear(); // Sets editor to a blank screen.
    }

    tableScroller.getVerticalScrollBar().setValue(0); // Sets the scroll bar back to the top.
  }
 protected void deleteAttribute(ActionEvent evt) {
   int selectedRow = table.getSelectedRow();
   if (selectedRow >= 0 && selectedRow < attributesTableModel.getRowCount()) {
     attributesTableModel.removeEntryAt(selectedRow);
   }
 }
  /** Opens the change class dialog. */
  public void changeClass() { // JPanel mainPanel
    /*
     *    MINOR MAGIC
     *
     *    This code reuses the 'new entry window'.  In order to make things
     *    sane, we prompt the user to save any serious changes before continuing.
     *    (Things can get really wierd if the user changes the name and then
     *    tries to change the objectclass - best to avoid the whole issue.)
     */
    myEditor.stopCellEditing();

    if (virtualEntry) {
      doVirtualEntryDisplay();
      return;
    }

    /*
     *    classChangedOriginalEntry saves the original state of the entry
     *    between visits to NewEntryWin.  (- I wonder if it would be neater
     *    to just reset the 'oldEntry' state of the table every time? ).
     *    Check it's not been set already (i.e. Pathological User is paying
     *    multiple visits to the NewEntryWin.)
     */
    if (classChangedOriginalEntry == null) classChangedOriginalEntry = tableData.getOldEntry();

    DXEntry newEntry = tableData.getNewEntry();
    DN newDN = newEntry.getDN();

    /*
     *    Pathalogical user has messed with the name, *and* wants to
     *    change the object classes...
     */
    if (newDN.equals(classChangedOriginalEntry.getDN()) == false) {
      checkForUnsavedChanges();
      /*
      if (promptForSave() == false)  // we may need to reset the 'newEntry' data
      {                                   // if the user discards their changes.

          tableData.reset();              // resets the table before going on.

          newEntry = tableData.getNewEntry();
          newDN = newEntry.getDN();
      }
      else // user has saved data - so now we need to reset the 'classChangedOriginalEntry'
      {
      */
      // to the changed (and hopefully saved!) data.
      // NB: If the directory write fails, then the change classes will also fail...
      classChangedOriginalEntry = tableData.getNewEntry();
    }

    /*
     *    Open NewEntryWin, allowing the user to reset the objectclass attribute.
     */

    /*
            NewEntryWin userData = new NewEntryWin(newDN.parentDN(), newDN,
                                    dataSource,
                                    newEntry.getAsNonNullAttributes(),
                                    newDN.getLowestRDN().toString(), TableAttributeEditor.this,
                                    CBUtility.getParentFrame(mainPanel));
    */
    if (dataSource.getSchemaOps() == null) {
      JOptionPane.showMessageDialog(
          owner,
          CBIntText.get(
              "Because there is no schema currently published by the\ndirectory, changing an entry's object class is unavailable."),
          CBIntText.get("No Schema"),
          JOptionPane.INFORMATION_MESSAGE);
      return;
    } else {
      ChangeObjectClassWin userData =
          new ChangeObjectClassWin(
              dataSource,
              newDN,
              newEntry.getAsNonNullAttributes(),
              this,
              CBUtility.getParentFrame(this),
              false);
      userData.setSize(400, 250);
      CBUtility.center(userData, owner); // TE: centres window.
      userData.setVisible(true);
    }
  }
 protected void addAttribute(ActionEvent evt) {
   attributesTableModel.addEmptyEntry();
 }