1 /* CVPanel.java
2  *
3  * created: 2006
4  *
5  * This file is part of Artemis
6  *
7  * Copyright (C) 2006  Genome Research Limited
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  **/
24 
25 package uk.ac.sanger.artemis.components.genebuilder.cv;
26 
27 import java.awt.Color;
28 import java.awt.Component;
29 import java.awt.BorderLayout;
30 import java.awt.Dimension;
31 import java.awt.Font;
32 import java.awt.FontMetrics;
33 import java.awt.event.ActionEvent;
34 import java.awt.event.ActionListener;
35 import java.util.Collections;
36 import java.util.Comparator;
37 import java.util.Vector;
38 
39 import javax.swing.Box;
40 import javax.swing.JLabel;
41 import javax.swing.JTextField;
42 import javax.swing.JPanel;
43 import javax.swing.JButton;
44 
45 import uk.ac.sanger.artemis.io.DatabaseDocumentEntry;
46 import uk.ac.sanger.artemis.io.GFFStreamFeature;
47 import uk.ac.sanger.artemis.io.Qualifier;
48 import uk.ac.sanger.artemis.io.QualifierVector;
49 import uk.ac.sanger.artemis.util.StringVector;
50 import uk.ac.sanger.artemis.util.DatabaseDocument;
51 import uk.ac.sanger.artemis.Feature;
52 import uk.ac.sanger.artemis.FeatureChangeEvent;
53 import uk.ac.sanger.artemis.FeatureChangeListener;
54 import uk.ac.sanger.artemis.chado.ChadoTransactionManager;
55 import uk.ac.sanger.artemis.components.genebuilder.GeneEditorPanel;
56 
57 import org.gmod.schema.cv.CvTerm;
58 
59 /**
60  * Panel for display controlled vocabulary terms for Chado
61  */
62 public class CVPanel extends JPanel
63              implements FeatureChangeListener
64 {
65   /** */
66   private static final long serialVersionUID = 1L;
67 
68   private QualifierVector cvQualifiers;
69   private Vector<AbstractCvBox> editableComponents;
70   public static org.apache.log4j.Logger logger4j =
71     org.apache.log4j.Logger.getLogger(CVPanel.class);
72 
73   private JButton hide_show_CC;
74   private JButton hide_show_GO;
75   private Feature feature;
76 
77   private DatabaseDocument doc;
78   //used to test if cv panel has contents
79   private boolean empty = true;
80 
CVPanel(final Feature feature)81   public CVPanel(final Feature feature)
82   {
83     super(new BorderLayout());
84     updateFromFeature(feature);
85     doc = (DatabaseDocument)
86       ((GFFStreamFeature)feature.getEmblFeature()).getDocumentEntry().getDocument();
87   }
88 
89   /**
90    * Return true if this is a CV qualifier
91    * @param qualifier
92    * @return
93    */
isCvTag(final Qualifier qualifier)94   public static boolean isCvTag(final Qualifier qualifier)
95   {
96     return isCvTag(qualifier.getName());
97   }
98 
99   /**
100    * Return true if this is a CV qualifier
101    * @param qualifierName
102    * @return
103    */
isCvTag(String qualifierName)104   public static boolean isCvTag(String qualifierName)
105   {
106     if(qualifierName.startsWith("/"))
107       qualifierName = qualifierName.substring(1);
108 
109     return ChadoTransactionManager.isCvTag(qualifierName);
110   }
111 
112   /**
113    * Create CV qualifier components
114    * @return
115    */
createCVQualifiersComponent()116   private Component createCVQualifiersComponent()
117   {
118     empty = true;
119     Vector<String> cv_tags = new Vector<String>();
120     cv_tags.add("GO");
121     cv_tags.add("controlled_curation");
122     cv_tags.add("product");
123     cv_tags.add("class");
124 
125     editableComponents = new Vector<AbstractCvBox>();
126 
127     final Dimension dimension  = new Dimension(100,
128         (new JTextField()).getPreferredSize().height);
129 
130     Box cvBox = Box.createVerticalBox();
131 
132     Box xBox = Box.createHorizontalBox();
133     JButton addRemove = new JButton("ADD");
134     addRemove.setOpaque(false);
135     addRemove.addActionListener(new ActionListener()
136     {
137       public void actionPerformed(ActionEvent e)
138       {
139         CvTermSelector cvTermSelector = new CvTermSelector();
140         if(cvTermSelector.showOptions(null, doc))
141         {
142           addCvTermQualifier(cvTermSelector.getCvTerm(),
143               cvTermSelector.getCvName(),
144               cvTermSelector.getCv(),
145               cvTermSelector.getEvidenceCode());
146         }
147 
148       }
149     });
150     xBox.add(addRemove);
151     JButton lookUp = new JButton("LOOK UP");
152     lookUp.setOpaque(false);
153     lookUp.addActionListener(new ActionListener()
154     {
155       public void actionPerformed(ActionEvent e)
156       {
157         DatabaseDocumentEntry entry =
158            (DatabaseDocumentEntry)feature.getEmblFeature().getEntry();
159         DatabaseDocument doc = (DatabaseDocument)entry.getDocument();
160 
161         doc.showCvTermLookUp();
162       }
163     });
164     xBox.add(lookUp);
165 
166     JButton addHistory = new JButton("ADD HISTORY");
167     addHistory.setOpaque(false);
168     addHistory.addActionListener(new ActionListener()
169     {
170       public void actionPerformed(ActionEvent e)
171       {
172         addHistoryQualifier();
173       }
174     });
175     if(ChadoTransactionManager.HISTORY_CV != null)
176       xBox.add(addHistory);
177 
178     xBox.add(Box.createHorizontalGlue());
179     cvBox.add(xBox);
180 
181     Dimension go_dimension = null;
182     Box goBox = null;
183     Box goHeadings = null;
184     for(Qualifier this_qualifier: cvQualifiers)
185     {
186       if(this_qualifier.getName().equals("GO"))
187       {
188         empty = false;
189 
190         if(hide_show_GO == null)
191           hide_show_GO = new JButton("-");
192 
193         if(goBox == null)
194           goBox = Box.createVerticalBox();
195 
196         addHideShowButton(goBox, hide_show_GO);
197 
198         if(goHeadings == null)
199           goHeadings = Box.createHorizontalBox();
200 
201         final StringVector qualifier_strings = this_qualifier.getValues();
202         for(int i = 0; i < qualifier_strings.size(); ++i)
203         {
204           GoBox go_box = new GoBox(this_qualifier, qualifier_strings.elementAt(i), i,
205                                    go_dimension, dimension);
206           go_dimension = go_box.getGoDimension();
207           editableComponents.add(go_box);
208 
209           xBox = go_box.getBox();
210           xBox.add(Box.createHorizontalGlue());
211           xBox.add(getRemoveButton(this_qualifier, i));
212 
213           goBox.add(xBox);
214         }
215 
216         // add column headings
217         final JLabel lab = new JLabel("GO terms");
218         lab.setPreferredSize(go_dimension);
219         lab.setFont(lab.getFont().deriveFont(Font.BOLD));
220         goHeadings.add(lab);
221         final JLabel withLabel = new JLabel("WITH/FROM");
222         withLabel.setPreferredSize(dimension);
223         goHeadings.add(withLabel);
224 
225         final JLabel dbxrefLabel = new JLabel("Dbxref");
226         dbxrefLabel.setPreferredSize(dimension);
227         goHeadings.add(dbxrefLabel);
228 
229         final JLabel evidenceLabel = new JLabel("Evidence");
230         evidenceLabel.setPreferredSize(GoBox.getEvidenceListDimension());
231         goHeadings.add(evidenceLabel);
232 
233         final JLabel qualLabel = new JLabel("Qualifier");
234         qualLabel.setPreferredSize(dimension);
235         goHeadings.add(qualLabel);
236         goHeadings.add(new JLabel("Date"));
237 
238         goHeadings.add(Box.createHorizontalGlue());
239         goHeadings.add(hide_show_GO);
240 
241         if(hide_show_GO.getText().equals("+"))
242           goBox.setVisible(false);
243       }
244     }
245 
246     int n = 0;
247     for(Qualifier this_qualifier: cvQualifiers)
248     {
249       if(this_qualifier.getName().equals("product"))
250       {
251         final StringVector qualifier_strings = this_qualifier.getValues();
252         for(int i = 0; i < qualifier_strings.size(); ++i)
253         {
254           empty = false;
255           final ProductBox productBox = new ProductBox(
256                     this_qualifier, qualifier_strings.elementAt(i),
257                     i, dimension, go_dimension);
258           editableComponents.add(productBox);
259 
260           if(qualifier_strings.size() == 1)
261             productBox.getRecommended().setEnabled(false);
262           xBox = productBox.getBox();
263           xBox.add(Box.createHorizontalGlue());
264           xBox.add(getRemoveButton(this_qualifier, i));
265           n++;
266           cvBox.add(productBox.getHeadingsBox());
267           cvBox.add(xBox);
268         }
269       }
270     }
271 
272     if(n > 0)
273       GeneEditorPanel.addLightSeparator(cvBox);
274 
275     // history field
276     n = 0;
277     for(Qualifier this_qualifier: cvQualifiers)
278     {
279       if(this_qualifier.getName().equals("history"))
280       {
281         final StringVector qualifier_strings = this_qualifier.getValues();
282 
283         for(int i = 0; i < qualifier_strings.size(); ++i)
284         {
285           empty = false;
286 
287           final HistoryBox historyBox = new HistoryBox(
288                     this_qualifier,
289                     qualifier_strings.elementAt(i), i,
290                     dimension, go_dimension);
291           editableComponents.add(historyBox);
292 
293           xBox = historyBox.getBox();
294           xBox.add(Box.createHorizontalGlue());
295           xBox.add(getRemoveButton(this_qualifier, i));
296 
297           if(n == 0)
298           {
299             final Box xLabel = Box.createHorizontalBox();
300             JLabel lab = new JLabel("History");
301             lab.setFont(lab.getFont().deriveFont(Font.BOLD));
302             xLabel.add(lab);
303             xLabel.add(Box.createHorizontalGlue());
304             cvBox.add(xLabel);
305           }
306           n++;
307           cvBox.add(xBox);
308         }
309       }
310     }
311 
312     if(n > 0)
313       GeneEditorPanel.addLightSeparator(cvBox);
314 
315     //
316     if(goBox != null)
317     {
318       cvBox.add(goHeadings);
319       cvBox.add(goBox);
320       GeneEditorPanel.addLightSeparator(cvBox);
321     }
322 
323 
324     n = 0;
325     for(Qualifier this_qualifier: cvQualifiers)
326     {
327       if(this_qualifier.getName().equals("controlled_curation"))
328       {
329         empty = false;
330 
331         final Box yBox = Box.createVerticalBox();
332         if(hide_show_CC == null)
333           hide_show_CC = new JButton("-");
334 
335         addHideShowButton(yBox, hide_show_CC);
336 
337         if(n == 0)
338         {
339           final Box xLabel = Box.createHorizontalBox();
340           JLabel lab = new JLabel("Controlled Curation");
341           lab.setFont(lab.getFont().deriveFont(Font.BOLD));
342           xLabel.add(lab);
343           xLabel.add(Box.createHorizontalGlue());
344           xLabel.add(hide_show_CC);
345           cvBox.add(xLabel);
346 
347 
348           final Box xHeadings = Box.createHorizontalBox();
349           yBox.add(xHeadings);
350 //        add column headings
351           final JLabel termLabel = new JLabel("Term");
352 
353           if(go_dimension != null)
354             termLabel.setPreferredSize(
355               new Dimension(go_dimension.width+dimension.width,
356                             dimension.height));
357           else
358             termLabel.setPreferredSize(
359                 new Dimension(getWidthOfGoField()+dimension.width,
360                               dimension.height));
361           xHeadings.add(termLabel);
362 
363 
364           final JLabel withLabel = new JLabel("WITH/FROM");
365           withLabel.setPreferredSize(dimension);
366           xHeadings.add(withLabel);
367 
368           final JLabel dbxrefLabel = new JLabel("Dbxref");
369           dbxrefLabel.setPreferredSize(dimension);
370           xHeadings.add(dbxrefLabel);
371 
372           final JLabel evidenceLabel = new JLabel("Evidence");
373           evidenceLabel.setPreferredSize(GoBox.getEvidenceListDimension());
374           xHeadings.add(evidenceLabel);
375 
376           final JLabel qualLabel = new JLabel("Qualifier");
377           qualLabel.setPreferredSize(dimension);
378           xHeadings.add(qualLabel);
379 
380           final JLabel dateLabel = new JLabel("Date");
381           xHeadings.add(dateLabel);
382 
383           xHeadings.add(Box.createHorizontalGlue());
384         }
385 
386         final StringVector qualifier_strings = this_qualifier.getValues();
387         for(int i = 0; i < qualifier_strings.size(); ++i)
388         {
389           n++;
390 
391           final ControlledCurationBox ccBox = new ControlledCurationBox(
392                   this_qualifier,
393                   qualifier_strings.elementAt(i), i,
394                   dimension, go_dimension);
395           editableComponents.add(ccBox);
396 
397           xBox = ccBox.getBox();
398           xBox.add(Box.createHorizontalGlue());
399           xBox.add(getRemoveButton(this_qualifier, i));
400           yBox.add(xBox);
401           yBox.add(Box.createVerticalStrut(2));
402         }
403 
404         // add CC rows
405         cvBox.add(yBox);
406         if(hide_show_CC.getText().equals("+"))
407           yBox.setVisible(false);
408       }
409     }
410 
411     if(n > 0)
412       GeneEditorPanel.addLightSeparator(cvBox);
413 
414     //
415     // RILEY
416     //
417 
418     if(go_dimension == null)
419       go_dimension = new JLabel("product ").getPreferredSize();
420     n = 0;
421     for(Qualifier this_qualifier: cvQualifiers)
422     {
423       if(this_qualifier.getName().equals("class"))
424       {
425         empty = false;
426         final StringVector qualifier_strings = this_qualifier.getValues();
427         n++;
428 
429         for(int i = 0; i < qualifier_strings.size(); ++i)
430         {
431           xBox = Box.createHorizontalBox();
432           final String qualifierStr = qualifier_strings.elementAt(i);
433 
434           JLabel label = new JLabel("class");
435           if(go_dimension != null)
436             label.setPreferredSize(go_dimension);
437           xBox.add(label);
438 
439           int index = qualifierStr.indexOf("::");
440           String classStr = qualifierStr.substring(0, index);
441           JLabel termTextField = new JLabel(classStr);
442           termTextField.setOpaque(false);
443 
444           termTextField
445               .setToolTipText(DatabaseDocument.getCvTermByCvTermId(
446                   Integer.parseInt(qualifierStr.substring(index + 2)), feature.getEmblFeature())
447                   .getDefinition());
448           termTextField.setPreferredSize(dimension);
449           termTextField.setMaximumSize(dimension);
450 
451           xBox.add(termTextField);
452           xBox.add(Box.createHorizontalGlue());
453           xBox.add(getRemoveButton(this_qualifier, i));
454           cvBox.add(xBox);
455         }
456       }
457     }
458 
459     cvBox.add(Box.createVerticalGlue());
460     validate();
461     return cvBox;
462   }
463 
464   /**
465    * Add hide/show button to CV section
466    * @param box
467    */
addHideShowButton(final Box box, final JButton hide_show)468   private void addHideShowButton(final Box box, final JButton hide_show)
469   {
470     hide_show.setOpaque(false);
471 
472     // remove any old listeners
473     ActionListener l[] = hide_show.getActionListeners();
474     if(l != null)
475       for(int i=0;i<l.length;i++)
476         hide_show.removeActionListener(l[i]);
477 
478     hide_show.addActionListener(new ActionListener()
479     {
480       public void actionPerformed(ActionEvent e)
481       {
482         if(hide_show.getText().equals("-"))
483         {
484           hide_show.setText("+");
485           box.setVisible(false);
486         }
487         else
488         {
489           hide_show.setText("-");
490           box.setVisible(true);
491         }
492       }
493     });
494   }
495 
496 
getWidthOfGoField()497   private static int getWidthOfGoField()
498   {
499     JTextField textField = new JTextField();
500     FontMetrics fm  = textField.getFontMetrics(textField.getFont());
501     return fm.stringWidth("GO:0001234 [F] ");
502   }
503 
getRemoveButton(final Qualifier this_qualifier, final int v_index)504   private JButton getRemoveButton(final Qualifier this_qualifier,
505                                   final int v_index)
506   {
507     JButton buttRemove = new JButton("X");
508     buttRemove.setOpaque(false);
509     Font font = buttRemove.getFont().deriveFont(Font.BOLD);
510     buttRemove.setFont(font);
511     buttRemove.setToolTipText("REMOVE");
512     buttRemove.setForeground(new Color(139,35,35));
513 
514     buttRemove.addActionListener(new ActionListener()
515     {
516       public void actionPerformed(ActionEvent e)
517       {
518         removeCvTerm(this_qualifier.getName(), v_index);
519       }
520     });
521     return buttRemove;
522   }
523 
updateFromFeature(final Feature feature)524   public void updateFromFeature(final Feature feature)
525   {
526     this.feature = feature;
527     if(cvQualifiers != null)
528       feature.removeFeatureChangeListener(this);
529     //cvQualifiers = feature.getQualifiers().copy();
530 
531     cvQualifiers = new QualifierVector();
532     final QualifierVector qualifiers = feature.getQualifiers();
533     for(int i = 0 ; i < qualifiers.size(); ++i)
534     {
535       Qualifier this_qualifier = (Qualifier)qualifiers.elementAt(i);
536 
537       if(this_qualifier.getName().equals("GO"))
538       {
539         final StringVector qualifier_strings = this_qualifier.getValues();
540         // sort by aspect (molecular_function, biological_process, cellular_component)
541         Collections.sort(qualifier_strings, new StringVectorComparator());
542         this_qualifier = new Qualifier("GO", qualifier_strings);
543       }
544 
545       if(isCvTag(this_qualifier))
546         cvQualifiers.addElement(this_qualifier.copy());
547     }
548 
549     feature.addFeatureChangeListener(this);
550 
551     removeAll();
552     add(createCVQualifiersComponent(),
553         BorderLayout.CENTER);
554   }
555 
updateFromQualifiers(final QualifierVector qualifiers)556   public void updateFromQualifiers(final QualifierVector qualifiers)
557   {
558     cvQualifiers = new QualifierVector();
559 
560     for(int i = 0 ; i < qualifiers.size(); ++i)
561     {
562       Qualifier this_qualifier = (Qualifier)qualifiers.elementAt(i);
563 
564       if(this_qualifier.getName().equals("GO"))
565       {
566         final StringVector qualifier_strings = this_qualifier.getValues();
567         // sort by aspect (molecular_function, biological_process, cellular_component)
568         Collections.sort(qualifier_strings, new StringVectorComparator());
569         this_qualifier = new Qualifier("GO", qualifier_strings);
570       }
571 
572       if(isCvTag(this_qualifier))
573         cvQualifiers.addElement(this_qualifier.copy());
574     }
575 
576     removeAll();
577     add(createCVQualifiersComponent(),
578         BorderLayout.CENTER);
579   }
580 
581   /**
582    * Add a history qualifier
583    */
addHistoryQualifier()584   private void addHistoryQualifier()
585   {
586     cvQualifiers = getCvQualifiers();
587     Qualifier cv_qualifier = cvQualifiers.getQualifierByName("history");
588 
589     final int index;
590     if(cv_qualifier == null)
591     {
592       cv_qualifier = new Qualifier("history");
593       index = -1;
594     }
595     else
596      index = cvQualifiers.indexOf(cv_qualifier);
597 
598     cv_qualifier.addValue(
599         "term="+HistoryBox.getDefaultTerm().getName()+";"+
600         "curatorName="+doc.getUserName()+";"+
601         "date="+ DatePanel.getDate());
602 
603     if(index > -1)
604     {
605       cvQualifiers.remove(index);
606       cvQualifiers.add(index, cv_qualifier);
607     }
608     else
609       cvQualifiers.add(cv_qualifier);
610 
611     removeAll();
612     add(createCVQualifiersComponent(),
613         BorderLayout.CENTER);
614     revalidate();
615     repaint();
616   }
617 
618   /**
619    * Add CvTerm qualifier
620    * @param cvterm
621    * @param go_name
622    * @param cv_type
623    */
addCvTermQualifier(CvTerm cvterm, final String go_name, String cv_type, final String evidenceCode)624   private void addCvTermQualifier(CvTerm cvterm,
625                                   final String go_name,
626                                   String cv_type,
627                                   final String evidenceCode)
628   {
629     if(!cv_type.equals("GO") &&
630        !cv_type.equals("controlled_curation") &&
631        !cv_type.equals("product") &&
632        !cv_type.equals("class"))
633       cv_type = "controlled_curation";
634 
635     cvQualifiers = getCvQualifiers();
636     Qualifier cv_qualifier = cvQualifiers.getQualifierByName(cv_type);
637 
638     final int index;
639     if(cv_qualifier == null)
640     {
641       cv_qualifier = new Qualifier(cv_type);
642       index = -1;
643     }
644     else
645      index = cvQualifiers.indexOf(cv_qualifier);
646 
647     if(cv_type.equals("GO"))
648       cv_qualifier.addValue("GOid=GO:"+cvterm.getDbXRef().getAccession()+";"+
649           "aspect="+go_name+";"+
650           "term="+cvterm.getName()+";"+
651           "evidence="+ evidenceCode+";"+
652           "date="+ DatePanel.getDate());
653     else if(cv_type.equals("controlled_curation"))
654       cv_qualifier.addValue("term="+cvterm.getName()+";cv="+cvterm.getCv().getName());
655     else if(cv_type.equals("product"))
656       cv_qualifier.addValue("term="+cvterm.getName());
657     else if(cv_type.equals("class"))
658       cv_qualifier.addValue(cvterm.getDbXRef().getAccession()+
659                             "::"+cvterm.getCvTermId());
660 
661     if(index > -1)
662     {
663       cvQualifiers.remove(index);
664       cvQualifiers.add(index, cv_qualifier);
665     }
666     else
667       cvQualifiers.add(cv_qualifier);
668 
669     removeAll();
670     add(createCVQualifiersComponent(),
671         BorderLayout.CENTER);
672     revalidate();
673     repaint();
674   }
675 
removeCvTerm(final String qualifier_name, final int value_index)676   private void removeCvTerm(final String qualifier_name,
677                             final int value_index)
678   {
679     cvQualifiers = getCvQualifiers();
680     Qualifier qual = cvQualifiers.getQualifierByName(qualifier_name);
681     StringVector values = qual.getValues();
682     values.remove(value_index);
683 
684     cvQualifiers.removeQualifierByName(qualifier_name);
685 
686     if(values.size() > 0)
687     {
688       qual = new Qualifier(qualifier_name, values);
689       cvQualifiers.addQualifierValues(qual);
690     }
691 
692     removeAll();
693 
694     add(createCVQualifiersComponent(),
695         BorderLayout.CENTER);
696     validate();
697   }
698 
699 
700   /**
701    * Get the latest (edited) controlled vocab qualifiers
702    * @return
703    */
getCvQualifiers()704   public QualifierVector getCvQualifiers()
705   {
706     // check editable components for changes
707 
708     if(editableComponents != null)
709     {
710       logger4j.debug("CV checking......");
711       for(int i=0; i<editableComponents.size(); i++)
712       {
713         AbstractCvBox cvBox = (AbstractCvBox)editableComponents.get(i);
714         if(cvBox.isQualifierChanged())
715         {
716           logger4j.debug("CV QUALIFIER CHANGED");
717           cvBox.updateQualifier(cvQualifiers);
718         }
719       }
720     }
721 
722     return cvQualifiers;
723   }
724 
getDescription()725   public static String getDescription()
726   {
727     final StringBuffer buff = new StringBuffer();
728     buff.append("Section for controlled vocabulary qualifiers:\n");
729     buff.append("GO, controlled_curation, product, Riley class");
730 
731     return buff.toString();
732   }
733 
734   /**
735    *  Implementation of the FeatureChangeListener interface.  We need to
736    *  listen to feature change events from the Features in this object so that
737    *  we can update the display.
738    *  @param event The change event.
739    **/
featureChanged(FeatureChangeEvent event)740   public void featureChanged(FeatureChangeEvent event)
741   {
742     // re-read the information from the feature
743     switch(event.getType())
744     {
745       case FeatureChangeEvent.QUALIFIER_CHANGED:
746         /*if(qualifier_text_area.getText().equals(orig_qualifier_text))
747           updateFromFeature();
748         else
749         {
750           final String message =
751             "warning: the qualifiers have changed outside the editor - " +
752             "view now?";
753 
754           final YesNoDialog yes_no_dialog =
755             new YesNoDialog(frame, message);
756 
757           if(yes_no_dialog.getResult())
758             new FeatureViewer(getFeature());
759         }*/
760         break;
761       default:
762         break;
763     }
764   }
765 
766 
767   class StringVectorComparator implements Comparator<String>
768   {
compare(String a, String b)769     public final int compare(String a, String b)
770     {
771       int result;
772 
773       String strA = getField("aspect", a);
774       String strB = getField("aspect", b);
775       result = strA.compareTo(strB);
776 
777       return result;
778     }
779 
780     /**
781      * Strip out the value of a field of interest from a qualifier string
782      *
783      * @param fieldName
784      * @param qualifierString
785      * @return
786      */
getField(final String fieldName, final String qualifierString)787     private String getField(final String fieldName, final String qualifierString)
788     {
789       String field = "";
790 
791       int ind1 = qualifierString.toLowerCase().indexOf(fieldName.toLowerCase());
792       int ind2 = qualifierString.indexOf(";", ind1);
793 
794       int len = fieldName.length();
795 
796       if(ind2 > ind1 && ind1 > -1)
797         field = qualifierString.substring(ind1+len,ind2);
798       else if(ind1 > -1)
799         field = qualifierString.substring(ind1+len);
800 
801       return field;
802     }
803   }
804 
isEmpty()805   public boolean isEmpty()
806   {
807     return empty;
808   }
809 
setEmpty(boolean empty)810   public void setEmpty(boolean empty)
811   {
812     this.empty = empty;
813   }
814 
815 }
816