1 /* QualifierEditor.java
2  *
3  * created: Tue Oct 23 2001
4  *
5  * This file is part of Artemis
6  *
7  * Copyright (C) 2000,2001,2002  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  * $Header: //tmp/pathsoft/artemis/uk/ac/sanger/artemis/components/QualifierEditor.java,v 1.5 2007-07-09 13:07:38 tjc Exp $
24  */
25 
26 package uk.ac.sanger.artemis.components;
27 
28 import uk.ac.sanger.artemis.*;
29 
30 import uk.ac.sanger.artemis.util.ReadOnlyException;
31 import uk.ac.sanger.artemis.io.GFFDocumentEntry;
32 import uk.ac.sanger.artemis.io.Qualifier;
33 import uk.ac.sanger.artemis.io.QualifierInfo;
34 import uk.ac.sanger.artemis.io.QualifierVector;
35 import uk.ac.sanger.artemis.io.QualifierParseException;
36 import uk.ac.sanger.artemis.io.EntryInformation;
37 import uk.ac.sanger.artemis.io.EntryInformationException;
38 
39 import java.awt.*;
40 import java.awt.event.*;
41 import java.util.Vector;
42 
43 import javax.swing.*;
44 
45 /**
46  *  This component allows qualifiers to be added to or replaced in several
47  *  features at once.
48  *
49  *  @author Kim Rutherford <kmr@sanger.ac.uk>
50  *  @version $Id: QualifierEditor.java,v 1.5 2007-07-09 13:07:38 tjc Exp $
51  **/
52 
53 public class QualifierEditor extends JFrame {
54   /**
55    *  Create a new QualifierEditor for the given features.
56    **/
QualifierEditor(final FeatureVector features, final EntryGroup entry_group)57   public QualifierEditor (final FeatureVector features,
58                           final EntryGroup entry_group) {
59     super (getFrameTitle (features));
60 
61     this.features = features;
62     this.entry_group = entry_group;
63 
64     final Font font = Options.getOptions ().getFont ();
65 
66     final Feature first_feature = features.elementAt (0);
67 
68     final EntryInformation entry_information =
69       first_feature.getEntry ().getEntryInformation ();
70 
71     setFont (font);
72 
73     boolean isGFF = false;
74     if(entry_group.getDefaultEntry().getEMBLEntry() instanceof GFFDocumentEntry)
75       isGFF = true;
76     final QualifierChoice qualifier_choice =
77       new QualifierChoice (entry_information, first_feature.getKey (), null, isGFF);
78 
79     final JPanel outer_qualifier_choice_panel = new JPanel ();
80     final JPanel qualifier_choice_panel = new JPanel ();
81     outer_qualifier_choice_panel.setLayout (new BorderLayout ());
82 
83     outer_qualifier_choice_panel.add (qualifier_choice_panel, "West");
84 
85     final JButton qualifier_button = new JButton ("Insert qualifier:");
86 
87     qualifier_button.addActionListener (new ActionListener () {
88       public void actionPerformed (ActionEvent e) {
89         final String qualifier_name =
90           (String) qualifier_choice.getSelectedItem ();
91         final QualifierInfo qualifier_info =
92           entry_information.getQualifierInfo (qualifier_name);
93 
94         if (qualifier_info == null) {
95           new MessageDialog (QualifierEditor.this, "internal error: no " +
96                              "qualifier info for " + qualifier_name);
97         } else {
98           qualifier_text_area.append ("/" + qualifier_name);
99 
100           switch (qualifier_info.getType ()) {
101           case QualifierInfo.QUOTED_TEXT:
102             qualifier_text_area.append ("=\"\"");
103             break;
104 
105           case QualifierInfo.NO_VALUE:
106           case QualifierInfo.OPTIONAL_QUOTED_TEXT:
107             break;
108 
109           default:
110             qualifier_text_area.append ("=");
111           }
112 
113           qualifier_text_area.append ("\n");
114         }
115       }
116 
117     });
118 
119     qualifier_choice_panel.add (qualifier_button);
120 
121     qualifier_choice_panel.add (qualifier_choice);
122 
123     getContentPane ().add (outer_qualifier_choice_panel, "North");
124 
125     qualifier_text_area = new QualifierTextArea ();
126 
127     add_button.setFont (getFont ());
128     replace_button.setFont (getFont ());
129     close_button.setFont (getFont ());
130 
131     add_button.addActionListener (new ActionListener () {
132       public void actionPerformed (ActionEvent e) {
133         addOrReplace (false);
134       }
135     });
136 
137     replace_button.addActionListener (new ActionListener () {
138       public void actionPerformed (ActionEvent e) {
139         addOrReplace (true);
140       }
141     });
142 
143     close_button.addActionListener (new ActionListener () {
144       public void actionPerformed (ActionEvent e) {
145         dispose ();
146       }
147     });
148 
149     button_panel.setFont (getFont ());
150 
151     button_panel.add (replace_button);
152     button_panel.add (add_button);
153     button_panel.add (close_button);
154 
155     getContentPane ().add (qualifier_text_area, "Center");
156     getContentPane ().add (button_panel, "South");
157 
158     addWindowListener (new WindowAdapter () {
159       public void windowClosing (WindowEvent event) {
160         dispose ();
161       }
162     });
163 
164     pack ();
165 
166     final Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
167     setLocation (new Point ((screen.width - getSize ().width) / 2,
168                             (screen.height - getSize ().height) / 2));
169   }
170 
171   /**
172    *  Add to or replace the qualifiers in all the features that were passed to
173    *  the constructor with the qualifiers from qualifier_text_area.
174    *  @param replace If false any existing qualifiers of the same name in the
175    *    features are left unchanged.  If true existing qualifiers of the same
176    *    name in the features will be deleted.
177    **/
addOrReplace(final boolean replace)178   private void addOrReplace (final boolean replace) {
179     try
180     {
181       entry_group.getActionController().startAction();
182 
183       // this will contain one QualifierVector object for each Feature in the
184       // features vector (in the same order)
185       final Vector qualifier_vector_vector = new Vector();
186       final int features_size = features.size();
187 
188       for(int i = 0; i<features_size; ++i)
189       {
190         final Feature this_feature = features.elementAt(i);
191 
192         final Entry this_feature_entry = this_feature.getEntry();
193 
194         if(this_feature_entry == null)
195         {
196           // feature has already been deleted
197           qualifier_vector_vector.addElement(null);
198         }
199         else
200         {
201           final EntryInformation entry_information =
202             this_feature_entry.getEntryInformation();
203 
204           try
205           {
206             final QualifierVector qualifiers =
207               qualifier_text_area.getParsedQualifiers(entry_information);
208 
209             qualifier_vector_vector.addElement(qualifiers);
210 
211           }
212           catch(QualifierParseException e)
213           {
214             new MessageDialog(this,
215                               "error while parsing: " + e.getMessage());
216             return;
217           }
218         }
219       }
220 
221       if(qualifier_vector_vector.size() != features_size)
222         throw new Error("Internal error in QualifierEditor.add() - " +
223                         "mismatched array sizes");
224 
225       for(int feature_index = 0; feature_index < features_size;
226           ++feature_index)
227       {
228         final Feature this_feature = features.elementAt(feature_index);
229         this_feature.resetColour();
230 
231         if(qualifier_vector_vector.elementAt(feature_index) == null)
232           continue;
233 
234         final QualifierVector qualifier_vector =
235           (QualifierVector)qualifier_vector_vector.elementAt(feature_index);
236 
237         final int qualifier_vector_size = qualifier_vector.size();
238 
239         for(int qualifier_index = 0; qualifier_index < qualifier_vector_size;
240             ++qualifier_index)
241         {
242           final Qualifier this_qualifier =
243             (Qualifier)qualifier_vector.elementAt(qualifier_index);
244 
245           if(replace)
246           {
247             try
248             {
249               this_feature.setQualifier(this_qualifier);
250             }
251             catch(EntryInformationException e)
252             {
253               new MessageDialog(this,
254                                 "failed to add qualifiers to: " +
255                                 this_feature.getIDString() + ": " +
256                                 e.getMessage());
257             }
258             catch(ReadOnlyException e)
259             {
260               new MessageDialog(this,
261                                 "failed to add qualifiers to read-only " +
262                                 "feature: " + this_feature.getIDString() +
263                                 ": " + e.getMessage());
264             }
265           }
266           else
267           {
268             try
269             {
270               this_feature.addQualifierValues(this_qualifier);
271             }
272             catch(EntryInformationException e)
273             {
274               new MessageDialog(this,
275                                 "failed to add qualifiers to: " +
276                                 this_feature.getIDString() + ": " +
277                                 e.getMessage());
278             }
279             catch(ReadOnlyException e)
280             {
281               new MessageDialog(this,
282                                 "failed to add qualifiers to read-only " +
283                                 "feature: " + this_feature.getIDString() +
284                                 ": " + e.getMessage());
285             }
286 
287           }
288         }
289       }
290     }
291     finally
292     {
293       entry_group.getActionController().endAction();
294     }
295   }
296 
297   /**
298    *  Return an appropriate String to use for the title of this JFrame.
299    **/
getFrameTitle(final FeatureVector features)300   static private String getFrameTitle (final FeatureVector features) {
301     boolean etc_flag = false;
302 
303     final StringBuffer buffer = new StringBuffer ();
304 
305     final int MAX_LENGTH = 80;
306 
307     for (int i = 0 ; i < features.size () ; ++i) {
308       final Feature this_feature = features.elementAt (i);
309 
310       final String feature_name = this_feature.getIDString ();
311 
312       if (feature_name == null) {
313         etc_flag = true;
314         continue;
315       }
316 
317       if (buffer.length () + feature_name.length () < MAX_LENGTH) {
318         if (buffer.length () == 0) {
319           buffer.append ("Add or replace qualifiers of: ");
320           buffer.append (feature_name);
321         } else {
322           buffer.append (", ").append (feature_name);
323         }
324       } else {
325         etc_flag = true;
326         break;
327       }
328     }
329 
330     if (buffer.length () == 0) {
331       buffer.append ("Add or replace qualifiers");
332     } else {
333       if (etc_flag) {
334         buffer.append (", ...");
335       }
336     }
337 
338     return buffer.toString ();
339   }
340 
341   private QualifierTextArea qualifier_text_area;
342 
343   private JButton add_button = new JButton ("Add");
344   private JButton replace_button = new JButton ("Replace");
345   private JButton close_button = new JButton ("Close");
346 
347   private FlowLayout flow_layout =
348     new FlowLayout (FlowLayout.CENTER, 25, 5);
349 
350   private JPanel button_panel = new JPanel (flow_layout);
351 
352   /**
353    *  The Feature objects that were passed to the constructor.
354    **/
355   private FeatureVector features = new FeatureVector ();
356 
357   /**
358    *  The EntryGroup that contains the Features (passed to the constructor).
359    **/
360   private EntryGroup entry_group;
361 }
362