KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > ca > directory > jxplorer > tree > NewEntryWin


1 package com.ca.directory.jxplorer.tree;
2
3 import com.ca.commons.cbutil.*;
4 import com.ca.commons.naming.*;
5 import com.ca.directory.jxplorer.*;
6
7 import javax.naming.InvalidNameException JavaDoc;
8 import javax.naming.NamingException JavaDoc;
9 import javax.naming.directory.*;
10 import javax.swing.*;
11 import java.awt.*;
12 import java.awt.event.*;
13 import java.util.*;
14 import java.util.logging.Logger JavaDoc;
15 import java.util.logging.Level JavaDoc;
16
17 /**
18  * This class allows a user to create the details of a new entry.
19  * These details are then passed to the table editor (usually)
20  * where the user can make further modifications, before finally
21  * submitting the result to the directory.
22  */

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

31
32 public class NewEntryWin extends CBDialog implements ActionListener, DataListener
33 {
34     JTextField rdnField,parentDNField;
35     
36     JScrollPane possiblePanel; // holds the selection list
37
JList possibleList; // list of possible object classes to be selected
38

39     JScrollPane selectedPanel; // holds the results list
40
JList selectedList; // list of user-selected object classes
41

42     DefaultListModel selDataModel; // dataModel for selected list
43
DefaultListModel posDataModel; // dataModel for possible list
44

45     DataSink entryEditor; // the table display the larval entry is (finally) displayed within.
46

47     JCheckBox autoSuggest;
48     
49     CBButton select, remove;
50     
51     static boolean suggest = true;
52     
53     Vector suggestedClasses = new Vector();
54     
55     DataSource dataSource;
56     
57     /*
58      * Only used in 'new entry' mode.
59      */

60      
61     DN parentDN;
62     DN childDN;
63     
64     /*
65      * Only used in 'change classes' mode.
66      */

67      
68     DN entryDN = null;
69     DXAttributes defaultAttributes = null;
70     
71     protected CBHelpSystem helpBroker;
72         
73     String JavaDoc objectClassName = null; // is it 'objectclass' or 'objectClass'
74

75     private static Logger JavaDoc log = Logger.getLogger(NewEntryWin.class.getName());
76
77     /**
78      * this sets whether the window needs to worry about the entry name.
79      * IF we're modifying an existing entry, we don't.
80      */

81      
82     protected boolean simpleMode;
83
84     /*
85      * Whether the child/parent name fields are disabled (implying that
86      * they must have been set externally!)
87      */

88      
89     protected boolean disableName = false;
90     
91     
92     boolean virtualEntry = false; //TE: a flag representing a virtual entry.
93

94     public BasicAttribute newObjectClasses = null;
95     
96       /**
97      * This creates the GUI, using the passed parameters
98      * to set up the default name and default object classes
99      * (if possible), and the destination of the prepared
100      * data.
101      *
102      * @param pDN the parent DN. This is the DN under which the new entry will
103      * be created.
104      * @param cDN an arbitrary child DN of a sibling of the to-be-created entry.
105      * This may be null, but if present is used to 'guess' what object
106      * classes may be wanted for the new entry.
107      * @param dSource a link to the directory, which is queried to discover
108      * what object classes are available for the new entry.
109      * @param attDisplay where the resulting half-finished entry is sent for the
110      * user to modify, and finally submit to the directory.
111      * @param parent the usual parent GUI for swing look and feel propogation etc.
112      */

113
114          
115     public NewEntryWin(DN pDN, DN cDN, DataSource dSource,
116                             DataSink attDisplay, Frame parent)
117     {
118         this(pDN, cDN, dSource, null, null, attDisplay, parent);
119         disableName = false;
120         rdnField.setEnabled(true);
121         parentDNField.setEnabled(true);
122     }
123
124     
125     /**
126      * This creates the GUI, using the passed parameters
127      * to set up the default name and default object classes
128      * (if possible), and the destination of the prepared
129      * data.
130      *
131      * @param pDN the parent DN. This is the DN under which the new entry will
132      * be created.
133      * @param cDN an arbitrary child DN of a sibling of the to-be-created entry.
134      * This may be null, but if present is used to 'guess' what object
135      * classes may be wanted for the new entry.
136      * @param dSource a link to the directory, which is queried to discover
137      * what object classes are available for the new entry.
138      * @param defaultValues - sometimes the 'new' entry is really just an update
139      * of an old one, with the object classes changing. If this is non
140      * null, it is used to initialise the attributes of the new entry.
141      * @param rdn an optional default name for an entry (again, mainly used if
142      * we're over-hauling an old entry, rather than creating a new one
143      * from scratch.
144      * @param attDisplay where the resulting half-finished entry is sent for the
145      * user to modify, and finally submit to the directory.
146      * @param parent the usual parent GUI for swing look and feel propogation etc.
147      */

148          
149     public NewEntryWin(DN pDN, DN cDN,
150             DataSource dSource, Attributes defaultValues,
151             String JavaDoc rdn, DataSink attDisplay, Frame parent)
152     {
153         super(parent, CBIntText.get("Set Entry Object Classes"), HelpIDs.ENTRY_NEW);
154
155         simpleMode = false;
156         
157         dataSource = dSource;
158             
159         entryEditor = attDisplay;
160             
161         if (defaultValues!=null)
162         {
163             if (defaultValues instanceof DXAttributes)
164                 defaultAttributes = (DXAttributes)defaultValues;
165             else
166                 defaultAttributes = new DXAttributes(defaultAttributes);
167         }
168         
169         // try to figure out what the capitalisation of 'objectClass' is today...
170
try
171         {
172             objectClassName = dataSource.getSchemaOps().getNameOfObjectClassAttribute();
173         }
174         catch (Exception JavaDoc e)
175         {
176         } // do nothing...
177

178         parentDN = pDN;
179         childDN = cDN;
180             
181         getContentPane().add(display);
182  
183         autoSuggest = new JCheckBox(CBIntText.get("Suggest Classes?"), suggest);
184         display.add(autoSuggest,3,0);
185         display.newLine();
186         
187         display.add(new JLabel(CBIntText.get("Parent DN") + ": "));
188         display.addLine(parentDNField = new JTextField(parentDN.toString(), 20));
189         
190         parentDNField.setEnabled(false); // disable, (but this is over-ridden if we are called from the other constructor)
191

192         display.add(new JLabel(CBIntText.get("Enter RDN") + ": "));
193         display.addLine(rdnField = new JTextField("=", 20));
194
195         // try to set some meaningful default values for the rdn field
196
if (rdn != null)
197         {
198             rdnField.setText(rdn);
199             rdnField.setEnabled(false); // disable, (but this is over-ridden if we are called from the other constructor)
200
}
201         else if ((suggest == true)&&(childDN != null))
202         {
203            rdnField.setText(childDN.getLowestRDN().getAtt() + "=");
204         }
205         
206         setupObjectClassPanels(null);
207         
208     
209         
210         autoSuggest.addActionListener(this);
211
212         registerMouseListeners();
213     }
214
215    /**
216      * This creates the GUI, using the passed parameters
217      * to set up the default name and default object classes
218      * (if possible), and the destination of the prepared
219      * data.
220      *
221      * @param dSource a link to the directory, which is queried to discover
222      * what object classes are available for the entry.
223      * @param entryDN the DN of the (existing) entry to be modified.
224      * @param defaultValues - sometimes the 'new' entry is really just an update
225      * of an old one, with the object classes changing. If this is non
226      * null, it is used to initialise the attributes of the new entry.
227      * @param attDisplay where the resulting half-finished entry is sent for the
228      * user to modify, and finally submit to the directory.
229      * @param parent the usual parent GUI for swing look and feel propogation etc.
230      */

231          
232     public NewEntryWin(DataSource dSource, DN entryDN, Attributes defaultValues,
233             DataSink attDisplay, Frame parent)
234     {
235         super(parent, CBIntText.get("Set Entry Object Classes"), HelpIDs.CLASS_CHANGE);
236
237         simpleMode = true;
238         
239         this.entryDN = entryDN;
240         
241         dataSource = dSource;
242             
243         entryEditor = attDisplay;
244             
245         if (defaultValues instanceof DXAttributes)
246             defaultAttributes = (DXAttributes) defaultValues;
247         else
248             defaultAttributes = new DXAttributes(defaultAttributes);
249         
250         // try to figure out what the capitalisation of 'objectClass' is today...
251
try
252         {
253             objectClassName = dataSource.getSchemaOps().getNameOfObjectClassAttribute();
254         }
255         catch (Exception JavaDoc e) {} // do nothing...
256

257         getContentPane().add(display);
258  
259         setupObjectClassPanels(defaultAttributes);
260         
261         registerMouseListeners();
262     }
263     
264     
265     
266    /**
267     * This creates the GUI, using the passed parameters
268     * to set up the default name and default object classes
269     * (if possible), and the destination of the prepared
270     * data.
271     *
272     * @param dSource a link to the directory, which is queried to discover
273     * what object classes are available for the entry.
274     * @param entryDN the DN of the (existing) entry to be modified.
275     * @param attDisplay - where the data is to be displayed; usually the entry Editor.
276     * @param parent the usual parent GUI for swing look and feel propogation etc.
277     * @param virtualEntry flag representing if the entry is a virtual entry (should always
278     * be true b/c currently this constructor will only be called under that condition).
279     */

280         
281     public NewEntryWin(DataSource dSource, DN entryDN, DataSink attDisplay, Frame parent, boolean virtualEntry)
282     {
283         super(parent, CBIntText.get("Set Entry Object Classes"), HelpIDs.CLASS_CHANGE);
284
285         this.virtualEntry = virtualEntry;
286         
287         simpleMode = true;
288         
289         this.entryDN = entryDN;
290         
291         dataSource = dSource;
292     
293         entryEditor = attDisplay;
294         getContentPane().add(display);
295         
296         setupObjectClassPanels(null);
297         registerMouseListeners();
298     }
299
300
301
302     protected void setupObjectClassPanels(Attributes currentAtts)
303     {
304
305         display.addWide(new JLabel(CBIntText.get("Available Classes") + ": "),2);
306         display.addWide(new JLabel(CBIntText.get("Selected Classes") + ": "),2);
307         display.newLine();
308
309         selDataModel = new DefaultListModel();
310         selectedList = new JList(selDataModel);
311         selectedList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
312         selectedList.setSelectionModel(new CBSingleSelectionModel(selectedList)); //TE: tries to ensure that the selected item is visible.
313

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

319         possiblePanel = new JScrollPane(possibleList);
320         selectedPanel = new JScrollPane(selectedList);
321
322         /*
323          * If we've passed in an existing entry to get the 'recommended' object
324          * classes from, then read them off immediately.
325          */

326
327         if (currentAtts != null)
328         {
329             Attribute objectClasses = currentAtts.get(objectClassName);
330             try
331             {
332                 Enumeration recommendedObjectClasses = objectClasses.getAll();
333                 while (recommendedObjectClasses.hasMoreElements())
334                 {
335                     String JavaDoc oc = (String JavaDoc)recommendedObjectClasses.nextElement();
336                     selDataModel.addElement(oc);
337                     suggestedClasses.add(oc);
338                 }
339             }
340             catch (Exception JavaDoc e) {}
341         }
342
343         /*
344          * If we haven't got a list of ocs, but we know the DN of a sibling
345          * entry (confusing called 'childDN' here) then we try to copy
346          * the object classes of that entry (on the grounds that similar
347          * entries often occupy the same level of a directory.
348          *
349          * The results of this query are returned (eventually & asynchronously)
350          * in 'dataReady()' below.
351          */

352
353         else if (childDN != null)
354         {
355             DataQuery myQuery = dataSource.getRecommendedObjectClasses(childDN);
356             myQuery.addDataListener(this);
357         }
358
359         /*
360          * Post a query to get all the available object classes known to the
361          * directory.
362          *
363          * The results of this query are returned (eventually & asynchronously)
364          * in 'dataReady()' below.
365          */

366         try
367         {
368             ArrayList allObjectClasses = dataSource.getSchemaOps().objectClasses();
369
370             for (int i=0; i<allObjectClasses.size(); i++)
371             {
372                 posDataModel.addElement(allObjectClasses.get(i));
373             }
374         }
375         catch (NamingException JavaDoc e)
376         {
377             //TODO add a manual way for the user to manually add object classes
378
}
379         Enumeration existing = selDataModel.elements();
380         while (existing.hasMoreElements())
381         {
382             posDataModel.removeElement(existing.nextElement());
383         }
384
385         display.makeHeavy();
386         display.add(possiblePanel,0,4,2,2);
387         display.add(selectedPanel,2,4,2,2);
388         display.makeLight();
389         display.newLine();
390
391         select = new CBButton(CBIntText.get("Add"), CBIntText.get("Click to add the selection."));
392         remove = new CBButton(CBIntText.get("Remove"), CBIntText.get("Click to remove the selection."));
393         display.addWide(select, 2);
394         display.addWide(remove, 2);
395         display.newLine();
396
397         validate();
398
399         select.addActionListener(this);
400         remove.addActionListener(this);
401     }
402
403
404     /**
405      * Callback from directory request to find possible object classes.
406      */

407      
408     public void dataReady(DataQuery result)
409     {
410         try
411         {
412 /*
413             if (result.getType() == DataQuery.GETALLOC)
414             {
415                 Vector allObjectClasses = result.getObjectClasses();
416                 
417                 //XXX every performance mistake in the book is committed here.
418                 for (int i=0; i<allObjectClasses.size(); i++)
419                 {
420                     posDataModel.addElement(allObjectClasses.get(i));
421                 }
422                 
423                 Enumeration existing = selDataModel.elements();
424                 while (existing.hasMoreElements())
425                 {
426                     posDataModel.removeElement(existing.nextElement());
427                 }
428                     
429                 //possibleList.setListData(allObjectClasses);
430             }
431 */

432             if (result.getType() == DataQuery.GETRECOC)
433             {
434                 if (suggestedClasses.size() < 1) // only add suggestions if none have already been added!
435
{
436                     ArrayList recommendedObjectClasses = result.getObjectClasses();
437                     for (int i=0; i<recommendedObjectClasses.size(); i++)
438                         suggestedClasses.addElement(recommendedObjectClasses.get(i));
439                 }
440
441                 checkSuggestedList();
442             }
443         }
444         catch (NamingException JavaDoc e) {CBUtility.error(CBIntText.get("threaded broker error: "), e); } // XXXTHREAD
445
}
446
447     /**
448      *
449      */

450      
451     protected void checkSuggestedList()
452     {
453         if (suggest == true && suggestedClasses.size() > 0)
454         {
455             for (int i=0; i<suggestedClasses.size(); i++)
456             {
457                 selectClass((String JavaDoc)suggestedClasses.get(i));
458             }
459         }
460     }
461
462
463
464     public void registerMouseListeners()
465     {
466         // 'add' list mouse listener
467
possibleList.addMouseListener(new MouseAdapter()
468         {
469             public void mouseClicked(MouseEvent e)
470             {
471                if (e.getClickCount() == 2)
472                {
473                    selectClass((String JavaDoc)possibleList.getSelectedValue());
474                }
475                else
476                    super.mouseClicked(e);
477             }
478         });
479
480         selectedList.addMouseListener(new MouseAdapter()
481         {
482             public void mouseClicked(MouseEvent e)
483             {
484                if (e.getClickCount() == 2)
485                {
486                    removeClass((String JavaDoc)selectedList.getSelectedValue());
487                }
488                else
489                    super.mouseClicked(e);
490             }
491         });
492     }
493     
494
495     public void selectClass(String JavaDoc value)
496     {
497         if (selDataModel.contains(value)==false)
498         {
499             selDataModel.addElement(value);
500             posDataModel.removeElement(value);
501         }
502     }
503
504     public void removeClass(String JavaDoc value)
505     {
506         if (selDataModel.contains(value))
507         {
508             selDataModel.removeElement(value);
509             if (posDataModel.contains(value) == false)
510             {
511                 // add element to the correct alphabetial position...
512
Object JavaDoc[] possibleValues = posDataModel.toArray();
513                 int len = possibleValues.length;
514                 for (int i=0; i<len; i++)
515                 {
516                     if (value.compareTo(possibleValues[i].toString()) <= 0)
517                     {
518                         posDataModel.add(i, value);
519                         break;
520                     }
521                 }
522             }
523         }
524     }
525     
526
527     /**
528      * <p>This creates the new entry</p>
529      *
530      * <p>This method is extended from the base class, and is called
531      * whenever the OK button is pressed.</p>
532      */

533      
534     public void doOK()
535     {
536         // XXX maybe improve so user doesn't need to spec rdn at this stage.
537

538         String JavaDoc rdnText = null;
539         
540         if (simpleMode == false)
541         {
542         
543             rdnText = rdnField.getText().trim();
544
545             int equalpos = rdnText.indexOf('=');
546             rdnText = rdnText.substring(0, equalpos+1) + NameUtility.escape(rdnText.substring(equalpos+1)); // fix for bug 5515
547

548             try // do sanity check
549
{
550 // if (RDN==null || "".equals(RDN)) return;
551
if (rdnText==null || "".equals(rdnText)) //TE: empty RDN.
552
throw new InvalidNameException JavaDoc(CBIntText.get("Empty RDN, please enter a valid RDN. ") + ((rdnText==null)?"<null>":CBIntText.get("The RDN value entered was: '")+rdnText) + "'");
553
554                 if (NameUtility.next(rdnText,0,'=')<0) //TE: no '='.
555
throw new InvalidNameException JavaDoc(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) + "'");
556                 else if (NameUtility.next(rdnText,0,'=')<1) //TE: no naming attribute.
557
throw new InvalidNameException JavaDoc(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) + "'");
558             }
559             catch (InvalidNameException JavaDoc ine)
560             {
561                 CBUtility.warning(this, CBIntText.get("Please Fill in the RDN field with a valid RDN."), CBIntText.get("Invalid RDN"));
562                 log.log(Level.WARNING, "Invalid RDN value in the New Entry dialog: ", ine);
563                 return;
564             }
565
566             String JavaDoc dn;
567             if (parentDNField.getText().trim().length() > 0)
568                 dn = rdnText + "," + parentDNField.getText();
569             else
570                 dn = rdnText;
571                 
572             //DN newObjectDN = new DN(dn);
573
entryDN = new DN(dn);
574         }
575                                 
576         Enumeration atts = selDataModel.elements();
577         
578         if (atts == null) // error: force user to use cancel to exit
579
{CBUtility.warning(this, CBIntText.get("At least one object class must be selected!"),CBIntText.get("Need ObjectClass(s)"));return;}
580             
581         
582         BasicAttribute obclasses = new BasicAttribute((objectClassName==null)?"objectClass":objectClassName);
583         while (atts.hasMoreElements())
584         {
585             String JavaDoc oc = atts.nextElement().toString();
586
587             obclasses.add(oc);
588         }
589         if (obclasses.size()==0)
590             {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
591

592         if (virtualEntry)
593         {
594             //TE: if it is a virtual entry we don't want to add a new entry it at this stage. We just want
595
// to get the object class(es) that the user has selected.
596
newObjectClasses = obclasses;
597             doCancel();
598         }
599             
600         if (createNewEntry(obclasses, rdnText, entryDN) == true)
601             doCancel();
602         // otherwise something went wrong, so keep dialog window around...
603
}
604
605     /**
606      * When Cancel is pressed (or the window is finished)
607      * this method shuts the window down, and prompts the
608      * parent to repaint (avoiding those nasty paint artifacts).
609      */

610      
611     public void doCancel()
612     {
613         setVisible(false);
614         dispose();
615         this.getParent().repaint();
616     }
617
618     
619     public void actionPerformed(ActionEvent e)
620     {
621         Object JavaDoc src = e.getSource();
622     
623         if (src == select)
624         {
625             if (possibleList.getSelectedValue() != null)
626                 selectClass(possibleList.getSelectedValue().toString());
627         }
628         else if (src == remove)
629         {
630             if (selectedList.getSelectedValue() != null)
631                 removeClass(selectedList.getSelectedValue().toString());
632         }
633         else if (src == autoSuggest)
634         {
635             suggest = autoSuggest.isSelected();
636             if (suggest == true)
637                 checkSuggestedList();
638             else
639             {
640                 if (suggestedClasses.size() > 0)
641                 {
642                     for (int i=0; i<suggestedClasses.size(); i++)
643                         removeClass((String JavaDoc)suggestedClasses.get(i));
644                 }
645             }
646         }
647     }
648     
649     
650     /**
651      * create a new Entry, by constructing a DXAttributes object
652      * using the list of objectclasses, and the rdn text, and
653      * passing it to a TreeEntryCreator
654      */

655      
656     public boolean createNewEntry(Attribute obclasses, String JavaDoc rdnText, DN newObjectDN)
657     {
658         // create a schema aware DXAttributes object, use it to get the list of all
659
// parent object classes as an attribute, and add it to the DXAttributes
660

661         DXAttributes attlist = new DXAttributes(obclasses);
662         Attribute allObjectClasses = attlist.getAllObjectClasses();
663
664         if (allObjectClasses == null) return false; // should never happen
665

666         //DXNamingEnumeration bloop = new DXNamingEnumeration(allObjectClasses.getAll());
667
attlist.put(allObjectClasses);
668         attlist.expandAllAttributes();
669
670         // copy appropriate default values (if any)
671
if (defaultAttributes !=null)
672         {
673             DXNamingEnumeration defAtts = (DXNamingEnumeration)defaultAttributes.getAllNonNull();
674             while (defAtts.hasMore())
675             {
676                 Attribute defAtt = (Attribute)defAtts.next();
677                 String JavaDoc defAttName = defAtt.getID();
678                 if (defAttName.equalsIgnoreCase("objectclass")==false)
679                 {
680                     if (attlist.get(defAttName)!=null) // only use defaults for valid attribute
681
attlist.put(defAtt);
682                 }
683             }
684         }
685
686         
687         if (rdnText != null)
688         {
689             RDN rdn = new RDN(rdnText);
690         
691             if (rdn.size()==0 || "".equals(rdn.getRawVal(0)))
692             {
693                 CBUtility.warning(this, CBIntText.get("Please fill in a valid name for the entry"), CBIntText.get("Can't read RDN"));
694                 return false;
695             }
696         
697             String JavaDoc rdnAttribute = rdn.getAtt(0);
698             String JavaDoc rdnValue = rdn.getRawVal(0);
699             
700             if (rdn.isMultiValued()==false)
701             {
702                 BasicAttribute rdnAtt = new BasicAttribute(rdnAttribute, rdnValue);
703                 attlist.put(rdnAtt);
704             }
705             else // multi valued rdn...
706
{
707                 for (int i=0; i<rdn.size(); i++)
708                 {
709                     BasicAttribute rdnAtt = new BasicAttribute(rdn.getAtt(i), rdn.getRawVal(i));
710                     attlist.put(rdnAtt);
711                 }
712             }
713             if (rdn.validate() == false)
714             {
715                 CBUtility.warning(this, CBIntText.get("Couldn't parse entry's name - please try again"), CBIntText.get("Can't read RDN"));
716                 return false;
717             }
718         }
719         
720         setVisible(false);
721         this.getParent().repaint();
722         
723         if (dataSource == null) // rare error (should be never)
724
{
725             CBUtility.error(CBIntText.get("unusual error:") + "\nno Data Source registered in NewEntryWin.", null);
726             return false;
727         }
728         
729 // CBUtility.setWaitCursor(this);
730
log.fine("creating entry " + newObjectDN);
731         DXEntry newEntry = new DXEntry(attlist, newObjectDN);
732         
733         newEntry.setStatus(DXEntry.NEW);
734         entryEditor.displayEntry(newEntry, dataSource);
735         
736 // dataSource.modifyEntry(null, newEntry);
737
// CBUtility.setNormalCursor(this);
738
return true;
739     }
740 }
Popular Tags