Package com.ca.directory.jxplorer.tree

Source Code of com.ca.directory.jxplorer.tree.NewEntryWin

package com.ca.directory.jxplorer.tree;

import com.ca.commons.cbutil.*;
import com.ca.commons.naming.*;
import com.ca.directory.jxplorer.*;

import javax.naming.InvalidNameException;
import javax.naming.NamingException;
import javax.naming.directory.*;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.util.logging.Logger;
import java.util.logging.Level;

/**
*   This class allows a user to create the details of a new entry.
*   These details are then passed to the table editor (usually)
*   where the user can make further modifications, before finally
*   submitting the result to the directory.
*/

// XXX
// XXX    This class is being pressed into service to do two similar
// XXX    things - create new entries, and change the object classes of
// XXX    Existing entries.  It gets a bit ugly, and should probably be
// XXX    Be rewritten.  - Chris
// XXX   


public class NewEntryWin extends CBDialog implements ActionListener, DataListener
{
    JTextField rdnField,parentDNField;
   
    JScrollPane possiblePanel;     // holds the selection list
    JList possibleList;            // list of possible object classes to be selected
   
    JScrollPane selectedPanel;     // holds the results list
    JList selectedList;            // list of user-selected object classes
   
    DefaultListModel selDataModel; // dataModel for selected list
    DefaultListModel posDataModel; // dataModel for possible list

    DataSink entryEditor;          // the table display the larval entry is (finally) displayed within.   
   
    JCheckBox autoSuggest;
   
    CBButton select, remove;
   
    static boolean suggest = true;
   
    Vector suggestedClasses = new Vector();
   
    DataSource dataSource;
   
    /*
     *    Only used in 'new entry' mode.
     */
    
    DN parentDN;
    DN childDN;
   
    /*
     *    Only used in 'change classes' mode.
     */
    
    DN entryDN = null;
    DXAttributes defaultAttributes = null;
   
    protected CBHelpSystem helpBroker;    
       
    String objectClassName = null; // is it 'objectclass' or 'objectClass'

    private static Logger log = Logger.getLogger(NewEntryWin.class.getName());

    /**
     *    this sets whether the window needs to worry about the entry name.
     *    IF we're modifying an existing entry, we don't.
     */
    
    protected boolean simpleMode; 

    /*
     *    Whether the child/parent name fields are disabled (implying that
     *    they must have been set externally!)
     */
    
    protected boolean disableName = false;
   
 
  boolean virtualEntry = false;    //TE: a flag representing a virtual entry.
 
    public BasicAttribute newObjectClasses = null;
 
      /**
     *    This creates the GUI, using the passed parameters
     *    to set up the default name and default object classes
     *    (if possible), and the destination of the prepared
     *    data.
     *
     *    @param pDN the parent DN.  This is the DN under which the new entry will
     *               be created.
     *    @param cDN an arbitrary child DN of a sibling of the to-be-created entry.
     *               This may be null, but if present is used to 'guess' what object
     *               classes may be wanted for the new entry.
     *    @param dSource a link to the directory, which is queried to discover
     *               what object classes are available for the new entry.
     *    @param attDisplay where the resulting half-finished entry is sent for the
     *               user to modify, and finally submit to the directory.
     *    @param parent the usual parent GUI for swing look and feel propogation etc.
     */

        
    public NewEntryWin(DN pDN, DN cDN, DataSource dSource,
                            DataSink attDisplay, Frame parent)
    {
        this(pDN, cDN, dSource, null, null, attDisplay, parent);
        disableName = false;
        rdnField.setEnabled(true);
        parentDNField.setEnabled(true);
    }

   
    /**
     *    This creates the GUI, using the passed parameters
     *    to set up the default name and default object classes
     *    (if possible), and the destination of the prepared
     *    data.
     *
     *    @param pDN the parent DN.  This is the DN under which the new entry will
     *               be created.
     *    @param cDN an arbitrary child DN of a sibling of the to-be-created entry.
     *               This may be null, but if present is used to 'guess' what object
     *               classes may be wanted for the new entry.
     *    @param dSource a link to the directory, which is queried to discover
     *               what object classes are available for the new entry.
     *    @param defaultValues - sometimes the 'new' entry is really just an update
     *               of an old one, with the object classes changing.  If this is non
     *               null, it is used to initialise the attributes of the new entry.
     *    @param rdn an optional default name for an entry (again, mainly used if
     *               we're over-hauling an old entry, rather than creating a new one
     *               from scratch.
     *    @param attDisplay where the resulting half-finished entry is sent for the
     *               user to modify, and finally submit to the directory.
     *    @param parent the usual parent GUI for swing look and feel propogation etc.
     */
        
    public NewEntryWin(DN pDN, DN cDN,
            DataSource dSource, Attributes defaultValues,
            String rdn, DataSink attDisplay, Frame parent)
    {
        super(parent, CBIntText.get("Set Entry Object Classes"), HelpIDs.ENTRY_NEW);

        simpleMode = false;
       
        dataSource = dSource;
           
        entryEditor = attDisplay;           
           
        if (defaultValues!=null
        {
            if (defaultValues instanceof DXAttributes)
                defaultAttributes = (DXAttributes)defaultValues;
            else
                defaultAttributes = new DXAttributes(defaultAttributes);
        }
       
        // try to figure out what the capitalisation of 'objectClass' is today...
        try
        {
            objectClassName = dataSource.getSchemaOps().getNameOfObjectClassAttribute();
        }
        catch (Exception e)
        {
        } // do nothing...
   
        parentDN = pDN;
        childDN = cDN;
           
        getContentPane().add(display);
        autoSuggest = new JCheckBox(CBIntText.get("Suggest Classes?"), suggest);
        display.add(autoSuggest,3,0);
        display.newLine();
       
        display.add(new JLabel(CBIntText.get("Parent DN") + ": "));
        display.addLine(parentDNField = new JTextField(parentDN.toString(), 20));
       
        parentDNField.setEnabled(false);      // disable, (but this is over-ridden if we are called from the other constructor)
       
        display.add(new JLabel(CBIntText.get("Enter RDN") + ": "));
        display.addLine(rdnField = new JTextField("=", 20));

        // try to set some meaningful default values for the rdn field
        if (rdn != null)
        {
            rdnField.setText(rdn);
            rdnField.setEnabled(false);      // disable, (but this is over-ridden if we are called from the other constructor)
        }   
        else if ((suggest == true)&&(childDN != null))
    {
           rdnField.setText(childDN.getLowestRDN().getAtt() + "=");
    }
   
        setupObjectClassPanels(null);
       
   
       
        autoSuggest.addActionListener(this);

        registerMouseListeners();
    }

   /**
     *    This creates the GUI, using the passed parameters
     *    to set up the default name and default object classes
     *    (if possible), and the destination of the prepared
     *    data.
     *
     *    @param dSource a link to the directory, which is queried to discover
     *               what object classes are available for the entry.
     *    @param entryDN the DN of the (existing) entry to be modified.
     *    @param defaultValues - sometimes the 'new' entry is really just an update
     *               of an old one, with the object classes changing.  If this is non
     *               null, it is used to initialise the attributes of the new entry.
     *    @param attDisplay where the resulting half-finished entry is sent for the
     *               user to modify, and finally submit to the directory.
     *    @param parent the usual parent GUI for swing look and feel propogation etc.
     */
        
    public NewEntryWin(DataSource dSource, DN entryDN, Attributes defaultValues,
            DataSink attDisplay, Frame parent)
    {
        super(parent, CBIntText.get("Set Entry Object Classes"), HelpIDs.CLASS_CHANGE);

        simpleMode = true;
       
        this.entryDN = entryDN;
       
        dataSource = dSource;
           
        entryEditor = attDisplay;           
           
        if (defaultValues instanceof DXAttributes)
            defaultAttributes = (DXAttributes) defaultValues;
        else
            defaultAttributes = new DXAttributes(defaultAttributes);
       
        // try to figure out what the capitalisation of 'objectClass' is today...
        try
        {
            objectClassName = dataSource.getSchemaOps().getNameOfObjectClassAttribute();
        }
        catch (Exception e) {} // do nothing...
   
        getContentPane().add(display);
        setupObjectClassPanels(defaultAttributes);
       
        registerMouseListeners();
    }
 
 
 
   /**
  *   This creates the GUI, using the passed parameters
  *   to set up the default name and default object classes
  *   (if possible), and the destination of the prepared
  *   data.
  *
  *   @param dSource a link to the directory, which is queried to discover
  *           what object classes are available for the entry.
  *   @param entryDN the DN of the (existing) entry to be modified.
  *   @param attDisplay - where the data is to be displayed; usually the entry Editor.
  *   @param parent the usual parent GUI for swing look and feel propogation etc.
  *  @param virtualEntry flag representing if the entry is a virtual entry (should always
  *      be true b/c currently this constructor will only be called under that condition).
  */
    
    public NewEntryWin(DataSource dSource, DN entryDN, DataSink attDisplay, Frame parent, boolean virtualEntry)
    {
        super(parent, CBIntText.get("Set Entry Object Classes"), HelpIDs.CLASS_CHANGE);

    this.virtualEntry = virtualEntry;
   
    simpleMode = true;
       
        this.entryDN = entryDN;
   
    dataSource = dSource;
 
    entryEditor = attDisplay;
    getContentPane().add(display);
   
    setupObjectClassPanels(null);
    registerMouseListeners();   
    }



    protected void setupObjectClassPanels(Attributes currentAtts)           
    {

        display.addWide(new JLabel(CBIntText.get("Available Classes") + ": "),2);
        display.addWide(new JLabel(CBIntText.get("Selected Classes") + ": "),2);
        display.newLine();

        selDataModel = new DefaultListModel();
        selectedList = new JList(selDataModel);
        selectedList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        selectedList.setSelectionModel(new CBSingleSelectionModel(selectedList));   //TE: tries to ensure that the selected item is visible.

        posDataModel = new DefaultListModel();
        possibleList = new JList(posDataModel);
        possibleList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        possibleList.setSelectionModel(new CBSingleSelectionModel(possibleList));   //TE: tries to ensure that the selected item is visible.

        possiblePanel = new JScrollPane(possibleList);
        selectedPanel = new JScrollPane(selectedList);

    /*
     *  If we've passed in an existing entry to get the 'recommended' object
     *  classes from, then read them off immediately.
     */

        if (currentAtts != null)
        {
            Attribute objectClasses = currentAtts.get(objectClassName);
            try
            {
                Enumeration recommendedObjectClasses = objectClasses.getAll();
                while (recommendedObjectClasses.hasMoreElements())
                {
                    String oc = (String)recommendedObjectClasses.nextElement();
                    selDataModel.addElement(oc);
                    suggestedClasses.add(oc);
                }
            }
            catch (Exception e) {}
        }

    /*
     *  If we haven't got a list of ocs, but we know the DN of a sibling
     *  entry (confusing called 'childDN' here) then we try to copy
     *  the object classes of that entry (on the grounds that similar
     *  entries often occupy the same level of a directory.
     *
     *  The results of this query are returned (eventually & asynchronously)
     *  in 'dataReady()' below.
     */

        else if (childDN != null)
        {
            DataQuery myQuery = dataSource.getRecommendedObjectClasses(childDN);
            myQuery.addDataListener(this);
        }

    /*
     *  Post a query to get all the available object classes known to the
     *  directory.
     *
     *  The results of this query are returned (eventually & asynchronously)
     *  in 'dataReady()' below.
     */
        try
        {
            ArrayList allObjectClasses = dataSource.getSchemaOps().objectClasses();

            for (int i=0; i<allObjectClasses.size(); i++)
            {
                posDataModel.addElement(allObjectClasses.get(i));
            }
        }
        catch (NamingException e)
        {
            //TODO add a manual way for the user to manually add object classes
        }
        Enumeration existing = selDataModel.elements();
        while (existing.hasMoreElements())
        {
            posDataModel.removeElement(existing.nextElement());
        }

        display.makeHeavy();
        display.add(possiblePanel,0,4,2,2);
        display.add(selectedPanel,2,4,2,2);
        display.makeLight();
        display.newLine();

        select = new CBButton(CBIntText.get("Add"), CBIntText.get("Click to add the selection."));
        remove = new CBButton(CBIntText.get("Remove"), CBIntText.get("Click to remove the selection."));
        display.addWide(select, 2);
        display.addWide(remove, 2);
        display.newLine();

        validate();

        select.addActionListener(this);
        remove.addActionListener(this);
    }


    /**
     *    Callback from directory request to find possible object classes.
     */
    
    public void dataReady(DataQuery result)
    {
        try
        {
/*
            if (result.getType() == DataQuery.GETALLOC)
            {
                Vector allObjectClasses = result.getObjectClasses();
               
                //XXX every performance mistake in the book is committed here.
                for (int i=0; i<allObjectClasses.size(); i++)
                {
                    posDataModel.addElement(allObjectClasses.get(i));
                }
               
                Enumeration existing = selDataModel.elements();
                while (existing.hasMoreElements())
                {
                    posDataModel.removeElement(existing.nextElement());
                }
                   
        //possibleList.setListData(allObjectClasses);           
            }
*/
            if (result.getType() == DataQuery.GETRECOC)
            {
                if (suggestedClasses.size() < 1// only add suggestions if none have already been added!
                {
                    ArrayList recommendedObjectClasses = result.getObjectClasses();
                    for (int i=0; i<recommendedObjectClasses.size(); i++)
                        suggestedClasses.addElement(recommendedObjectClasses.get(i));
                }

                checkSuggestedList();
            }
        }
        catch (NamingException e) {CBUtility.error(CBIntText.get("threaded broker error") + ": ", e); } // XXXTHREAD
    }       

    /**
     *
     */
    
    protected void checkSuggestedList()
    {
        if (suggest == true && suggestedClasses.size() > 0)
        {
            for (int i=0; i<suggestedClasses.size(); i++)
            {
                selectClass((String)suggestedClasses.get(i));
            }
        }       
    }



    public void registerMouseListeners()
    {
        // 'add' list mouse listener
        possibleList.addMouseListener(new MouseAdapter()
        {
            public void mouseClicked(MouseEvent e)
            {
               if (e.getClickCount() == 2)
               {
                   selectClass((String)possibleList.getSelectedValue());
               }
               else
                   super.mouseClicked(e);
            }
        });

        selectedList.addMouseListener(new MouseAdapter()
        {
            public void mouseClicked(MouseEvent e)
            {
               if (e.getClickCount() == 2)
               {
                   removeClass((String)selectedList.getSelectedValue());
               }
               else
                   super.mouseClicked(e);
            }
        });      
    }
   

    public void selectClass(String value)
    {
        if (selDataModel.contains(value)==false)
        {
            selDataModel.addElement(value);
            posDataModel.removeElement(value);
        }   
    }

    public void removeClass(String value)
    {
        if (selDataModel.contains(value))
        {
            selDataModel.removeElement(value);  
            if (posDataModel.contains(value) == false)
            {
                // add element to the correct alphabetial position...
                Object[] possibleValues = posDataModel.toArray();
                int len = possibleValues.length;
                for (int i=0; i<len; i++)
                {
                    if (value.compareTo(possibleValues[i].toString()) <= 0)
                    {
                        posDataModel.add(i, value);
                        break;
                    }   
                }
            }               
        }   
    }
   

    /**
     *    <p>This creates the new entry</p>
     *
     *    <p>This method is extended from the base class, and is called
     *    whenever the OK button is pressed.</p>
     */
    
    public void doOK()
    {
        // XXX maybe improve so user doesn't need to spec rdn at this stage.
       
        String rdnText = null;
       
        if (simpleMode == false)
        {
       
            rdnText = rdnField.getText().trim();

            int equalpos = rdnText.indexOf('=');
            rdnText = rdnText.substring(0, equalpos+1) + NameUtility.escape(rdnText.substring(equalpos+1))// fix for bug 5515

            try                             // do sanity check
            {
//        if (RDN==null || "".equals(RDN)) return;
                if (rdnText==null || "".equals(rdnText))  //TE: empty RDN.
                    throw new InvalidNameException(CBIntText.get("Empty RDN, please enter a valid RDN.") + " " + ((rdnText==null)?"<null>":CBIntText.get("The RDN value entered was: '")+rdnText) + "'");

                if (NameUtility.next(rdnText,0,'=')<0//TE: no '='.
                    throw new InvalidNameException(CBIntText.get("Invalid RDN, please enter a naming attribute followed by '=' followed by a name in the RDN field (for example, 'cn=Trudi). '") + ((rdnText==null)?"<null>":CBIntText.get("The RDN value entered was: '")+rdnText) + "'");
                else if (NameUtility.next(rdnText,0,'=')<1//TE: no naming attribute.
                    throw new InvalidNameException(CBIntText.get("Invalid RDN, please enter a naming attribute in the RDN field (for example, cn: 'cn=Trudi). '") + ((rdnText==null)?"<null>":CBIntText.get("The RDN value entered was: '")+rdnText) + "'");
            }
            catch (InvalidNameException ine)
            {
                CBUtility.warning(this, CBIntText.get("Please Fill in the RDN field with a valid RDN."), CBIntText.get("Invalid RDN"));
                log.log(Level.WARNING, "Invalid RDN value in the New Entry dialog: ", ine);
                return;
            }

            String dn;
            if (parentDNField.getText().trim().length() > 0)
                dn = rdnText + "," + parentDNField.getText();
            else
                dn = rdnText;               
               
            //DN newObjectDN = new DN(dn);
            entryDN = new DN(dn);
        }                               
                               
        Enumeration atts = selDataModel.elements();
       
        if (atts == null// error: force user to use cancel to exit
            {CBUtility.warning(this, CBIntText.get("At least one object class must be selected!"),CBIntText.get("Need ObjectClass(s)"));return;}
           
       
        BasicAttribute obclasses = new BasicAttribute((objectClassName==null)?"objectClass":objectClassName);
        while (atts.hasMoreElements())
        {
            String oc = atts.nextElement().toString();

            obclasses.add(oc);
        }
        if (obclasses.size()==0)
            {CBUtility.warning(this, CBIntText.get("At least one object class must be selected.")+ " ", CBIntText.get("Need ObjectClass(s)")); return;}// error: force user to use cancel to exit
           
    if (virtualEntry
    {       
      //TE: if it is a virtual entry we don't want to add a new entry it at this stage.  We just want
      //    to get the object class(es) that the user has selected.
      newObjectClasses = obclasses;
      doCancel();
    }   
     
        if (createNewEntry(obclasses, rdnText, entryDN) == true)
            doCancel();
        // otherwise something went wrong, so keep dialog window around...               
    }

    /**
     *    When Cancel is pressed (or the window is finished)
     *    this method shuts the window down, and prompts the
     *    parent to repaint (avoiding those nasty paint artifacts).
     */
    
    public void doCancel()
    {
        setVisible(false);
        dispose();
        this.getParent().repaint();
    }

   
    public void actionPerformed(ActionEvent e)
    {
        Object src = e.getSource();
   
        if (src == select)
        {
            if (possibleList.getSelectedValue() != null)
                selectClass(possibleList.getSelectedValue().toString());
        }
        else if (src == remove)
        {
            if (selectedList.getSelectedValue() != null)
                removeClass(selectedList.getSelectedValue().toString());
        }
        else if (src == autoSuggest)
        {
            suggest = autoSuggest.isSelected();
            if (suggest == true)
                checkSuggestedList();
            else
            {
                if (suggestedClasses.size() > 0)
                {
                    for (int i=0; i<suggestedClasses.size(); i++)
                        removeClass((String)suggestedClasses.get(i));
                }
            }
        }
    }
   
   
    /**
     *    create a new Entry, by constructing a DXAttributes object
     *    using the list of objectclasses, and the rdn text, and
     *    passing it to a TreeEntryCreator
     */
    
    public boolean createNewEntry(Attribute obclasses, String rdnText, DN newObjectDN)
    {      
        // create a schema aware DXAttributes object, use it to get the list of all
        // parent object classes as an attribute, and add it to the DXAttributes
       
        DXAttributes attlist = new DXAttributes(obclasses);
        Attribute allObjectClasses = attlist.getAllObjectClasses();

        if (allObjectClasses == null) return false// should never happen

        //DXNamingEnumeration bloop = new DXNamingEnumeration(allObjectClasses.getAll());
        attlist.put(allObjectClasses);
        attlist.expandAllAttributes();

        // copy appropriate default values (if any)
        if (defaultAttributes !=null)
        {
            DXNamingEnumeration defAtts = (DXNamingEnumeration)defaultAttributes.getAllNonNull();
            while (defAtts.hasMore())
            {
                Attribute defAtt = (Attribute)defAtts.next();
                String defAttName = defAtt.getID();
                if (defAttName.equalsIgnoreCase("objectclass")==false)
                {
                    if (attlist.get(defAttName)!=null)    // only use defaults for valid attribute
                        attlist.put(defAtt);
                }
            }
        }

       
        if (rdnText != null)
        {
            RDN rdn = new RDN(rdnText);
       
            if (rdn.size()==0 || "".equals(rdn.getRawVal(0)))
            {
                CBUtility.warning(this, CBIntText.get("Please fill in a valid name for the entry"), CBIntText.get("Can't read RDN"));
                return false;
            }
       
            String rdnAttribute = rdn.getAtt(0);
            String rdnValue = rdn.getRawVal(0);
           
            if (rdn.isMultiValued()==false)
            {
                BasicAttribute rdnAtt = new BasicAttribute(rdnAttribute, rdnValue);
                attlist.put(rdnAtt);
            }
            else    // multi valued rdn...
            {
                for (int i=0; i<rdn.size(); i++)
                {
                    BasicAttribute rdnAtt = new BasicAttribute(rdn.getAtt(i), rdn.getRawVal(i));
                    attlist.put(rdnAtt);
                }
            }
            if (rdn.validate() == false)           
            {
                CBUtility.warning(this, CBIntText.get("Couldn't parse entry's name - please try again"), CBIntText.get("Can't read RDN"));
                return false;
            }
        }
       
        setVisible(false);
        this.getParent().repaint();
       
        if (dataSource == null// rare error (should be never)
        {
            CBUtility.error(CBIntText.get("unusual error") + ":\nno Data Source registered in NewEntryWin.", null);
            return false;
        }
       
//        CBUtility.setWaitCursor(this);
        log.fine("creating entry " + newObjectDN);
        DXEntry newEntry = new DXEntry(attlist, newObjectDN);
       
        newEntry.setStatus(DXEntry.NEW);
        entryEditor.displayEntry(newEntry, dataSource);
       
//        dataSource.modifyEntry(null, newEntry);
//        CBUtility.setNormalCursor(this);
        return true;
   
}
TOP

Related Classes of com.ca.directory.jxplorer.tree.NewEntryWin

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.