new UI types?
[jalview.git] / forester / java / src / org / forester / archaeopteryx / NodePanel.java
1 // $Id:
2 // FORESTER -- software libraries and applications
3 // for evolutionary biology research and applications.
4 //
5 // Copyright (C) 2008-2009 Christian M. Zmasek
6 // Copyright (C) 2008-2009 Burnham Institute for Medical Research
7 // All rights reserved
8 //
9 // This library is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU Lesser General Public
11 // License as published by the Free Software Foundation; either
12 // version 2.1 of the License, or (at your option) any later version.
13 //
14 // This library 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 GNU
17 // Lesser General Public License for more details.
18 //
19 // You should have received a copy of the GNU Lesser General Public
20 // License along with this library; if not, write to the Free Software
21 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 //
23 // Contact: phylosoft @ gmail . com
24 // WWW: www.phylosoft.org/
25
26 package org.forester.archaeopteryx;
27
28 import java.util.List;
29 import java.util.SortedMap;
30 import java.util.SortedSet;
31
32 import javax.swing.JEditorPane;
33 import javax.swing.JPanel;
34 import javax.swing.JScrollPane;
35 import javax.swing.JSplitPane;
36 import javax.swing.JTree;
37 import javax.swing.event.TreeSelectionEvent;
38 import javax.swing.event.TreeSelectionListener;
39 import javax.swing.text.Position;
40 import javax.swing.tree.DefaultMutableTreeNode;
41 import javax.swing.tree.TreePath;
42
43 import org.forester.phylogeny.PhylogenyMethods;
44 import org.forester.phylogeny.PhylogenyNode;
45 import org.forester.phylogeny.data.Annotation;
46 import org.forester.phylogeny.data.BinaryCharacters;
47 import org.forester.phylogeny.data.Date;
48 import org.forester.phylogeny.data.Distribution;
49 import org.forester.phylogeny.data.Event;
50 import org.forester.phylogeny.data.PhylogenyData;
51 import org.forester.phylogeny.data.Point;
52 import org.forester.phylogeny.data.PropertiesMap;
53 import org.forester.phylogeny.data.Property;
54 import org.forester.phylogeny.data.Reference;
55 import org.forester.phylogeny.data.Sequence;
56 import org.forester.phylogeny.data.Taxonomy;
57 import org.forester.phylogeny.data.Uri;
58 import org.forester.util.ForesterUtil;
59
60 class NodePanel extends JPanel implements TreeSelectionListener {
61
62     static final String       DIST_ALTITUDE            = "Altitude";
63     static final String       DIST_ALT_UNIT            = "Altitude unit";
64     static final String       DIST_LONGITUDE           = "Longitude";
65     static final String       DIST_LATITUDE            = "Latitude";
66     static final String       DIST_GEODETIC_DATUM      = "Geodetic datum";
67     static final String       DIST_DESCRIPTION         = "Description";
68     static final String       DATE_UNIT                = "Unit";
69     static final String       DATE_MAX                 = "Max";
70     static final String       DATE_MIN                 = "Min";
71     static final String       DATE_VALUE               = "Value";
72     static final String       DATE_DESCRIPTION         = "Description";
73     static final String       TAXONOMY_IDENTIFIER      = "Identifier";
74     static final String       SEQ_ACCESSION            = "Accession";
75     static final String       CONFIDENCE               = "Confidence";
76     static final String       PROP                     = "Properties";
77     static final String       BINARY_CHARACTERS        = "Binary characters";
78     static final String       REFERENCE                = "Reference";
79     static final String       LIT_REFERENCE            = "Reference";
80     static final String       LIT_REFERENCE_DESC       = "Description";
81     static final String       LIT_REFERENCE_DOI        = "DOI";
82     static final String       DISTRIBUTION             = "Distribution";
83     static final String       DATE                     = "Date";
84     static final String       EVENTS                   = "Events";
85     static final String       SEQUENCE                 = "Sequence";
86     static final String       TAXONOMY                 = "Taxonomy";
87     static final String       BASIC                    = "Basic";
88     static final String       TAXONOMY_SCIENTIFIC_NAME = "Scientific name";
89     static final String       SEQ_MOL_SEQ              = "Mol seq";
90     static final String       SEQ_TYPE                 = "Type";
91     static final String       SEQ_LOCATION             = "Location";
92     static final String       SEQ_SYMBOL               = "Symbol";
93     static final String       SEQ_URI                  = "URI";
94     static final String       NODE_BRANCH_LENGTH       = "Branch length";
95     static final String       NODE_NAME                = "Name";
96     static final String       TAXONOMY_URI             = "URI";
97     static final String       TAXONOMY_RANK            = "Rank";
98     static final String       TAXONOMY_SYNONYM         = "Synonym";
99     static final String       TAXONOMY_COMMON_NAME     = "Common name";
100     static final String       TAXONOMY_AUTHORITY       = "Authority";
101     static final String       TAXONOMY_CODE            = "Code";
102     static final String       SEQ_NAME                 = "Name";
103     static final String       EVENTS_GENE_LOSSES       = "Gene losses";
104     static final String       EVENTS_SPECIATIONS       = "Speciations";
105     static final String       EVENTS_DUPLICATIONS      = "Duplications";
106     private static final long serialVersionUID         = 5120159904388100771L;
107     static final String       CONFIDENCE_TYPE          = "type";
108     private final JTree       _tree;
109     private final JEditorPane _pane;
110
111     public NodePanel( final PhylogenyNode phylogeny_node ) {
112         String node_name = "";
113         if ( !ForesterUtil.isEmpty( phylogeny_node.getName() ) ) {
114             node_name = phylogeny_node.getName() + " ";
115         }
116         final DefaultMutableTreeNode top = new DefaultMutableTreeNode( "Node " + node_name );
117         createNodes( top, phylogeny_node );
118         _tree = new JTree( top );
119         _tree.setEditable( false );
120         getJTree().setToggleClickCount( 1 );
121         expandPath( BASIC );
122         expandPath( TAXONOMY );
123         expandPath( SEQUENCE );
124         expandPath( EVENTS );
125         final JScrollPane tree_view = new JScrollPane( getJTree() );
126         _pane = new JEditorPane();
127         _pane.setEditable( false );
128         final JScrollPane data_view = new JScrollPane( _pane );
129         final JSplitPane split_pane = new JSplitPane( JSplitPane.VERTICAL_SPLIT );
130         split_pane.setTopComponent( tree_view );
131         split_pane.setBottomComponent( data_view );
132         data_view.setMinimumSize( Constants.NODE_PANEL_SPLIT_MINIMUM_SIZE );
133         tree_view.setMinimumSize( Constants.NODE_PANEL_SPLIT_MINIMUM_SIZE );
134         split_pane.setDividerLocation( 400 );
135         split_pane.setPreferredSize( Constants.NODE_PANEL_SIZE );
136         add( split_pane );
137     }
138
139     private void expandPath( final String name ) {
140         final TreePath tp = getJTree().getNextMatch( name, 0, Position.Bias.Forward );
141         if ( tp != null ) {
142             getJTree().expandPath( tp );
143         }
144     }
145
146     private JTree getJTree() {
147         return _tree;
148     }
149
150     @Override
151     public void valueChanged( final TreeSelectionEvent e ) {
152         // Do nothing.
153     }
154
155     private static void addAnnotation( final DefaultMutableTreeNode top, final Annotation ann, final String name ) {
156         DefaultMutableTreeNode category;
157         category = new DefaultMutableTreeNode( name );
158         top.add( category );
159         addSubelement( category, REFERENCE, ann.getRef() );
160         addSubelement( category, "Description", ann.getDesc() );
161         addSubelement( category, "Source", ann.getSource() );
162         addSubelement( category, "Type", ann.getType() );
163         addSubelement( category, "Evidence", ann.getEvidence() );
164         if ( ann.getConfidence() != null ) {
165             addSubelement( category, CONFIDENCE, ann.getConfidence().asText().toString() );
166         }
167         if ( ann.getProperties() != null ) {
168             addProperties( category, ann.getProperties(), PROP );
169         }
170     }
171
172     private static void addUri( final DefaultMutableTreeNode top, final Uri uri, final String name ) {
173         DefaultMutableTreeNode category;
174         category = new DefaultMutableTreeNode( name );
175         top.add( category );
176         addSubelement( category, "Description", uri.getDescription() );
177         addSubelement( category, "Type", uri.getType() );
178         addSubelement( category, "URI", uri.getValue().toString() );
179     }
180
181     private static void addAnnotations( final DefaultMutableTreeNode top,
182                                         final SortedSet<Annotation> annotations,
183                                         final DefaultMutableTreeNode category ) {
184         if ( ( annotations != null ) && ( annotations.size() > 0 ) ) {
185             category.add( new DefaultMutableTreeNode( "Annotations" ) );
186             final DefaultMutableTreeNode last = top.getLastLeaf();
187             int i = 0;
188             for( final PhylogenyData ann : annotations ) {
189                 addAnnotation( last, ( Annotation ) ann, "Annotation " + ( i++ ) );
190             }
191         }
192     }
193
194     private static void addUris( final DefaultMutableTreeNode top,
195                                  final List<Uri> uris,
196                                  final DefaultMutableTreeNode category ) {
197         if ( ( uris != null ) && ( uris.size() > 0 ) ) {
198             category.add( new DefaultMutableTreeNode( "URIs" ) );
199             final DefaultMutableTreeNode last = top.getLastLeaf();
200             int i = 0;
201             for( final Uri uri : uris ) {
202                 if ( uri != null ) {
203                     addUri( last, uri, "URI " + ( i++ ) );
204                 }
205             }
206         }
207     }
208
209     private static void addBasics( final DefaultMutableTreeNode top,
210                                    final PhylogenyNode phylogeny_node,
211                                    final String name ) {
212         final DefaultMutableTreeNode category = new DefaultMutableTreeNode( name );
213         top.add( category );
214         addSubelement( category, NODE_NAME, phylogeny_node.getName() );
215         if ( phylogeny_node.getDistanceToParent() != PhylogenyNode.DISTANCE_DEFAULT ) {
216             addSubelement( category,
217                            NODE_BRANCH_LENGTH,
218                            ForesterUtil.FORMATTER_6.format( phylogeny_node.getDistanceToParent() ) );
219         }
220         if ( phylogeny_node.getBranchData().isHasConfidences() ) {
221             for( final PhylogenyData conf : phylogeny_node.getBranchData().getConfidences() ) {
222                 addSubelement( category, CONFIDENCE, conf.asText().toString() );
223             }
224         }
225         if ( !phylogeny_node.isExternal() ) {
226             addSubelement( category, "Children", String.valueOf( phylogeny_node.getNumberOfDescendants() ) );
227             addSubelement( category,
228                            "External children",
229                            String.valueOf( phylogeny_node.getAllExternalDescendants().size() ) );
230             final SortedMap<Taxonomy, Integer> distinct_tax = PhylogenyMethods
231                     .obtainDistinctTaxonomyCounts( phylogeny_node );
232             if ( distinct_tax != null ) {
233                 final int no_tax = PhylogenyMethods.calculateNumberOfExternalNodesWithoutTaxonomy( phylogeny_node );
234                 final int tax_count = distinct_tax.size();
235                 addSubelement( category, "Distinct external taxonomies", String.valueOf( tax_count ) );
236                 if ( no_tax > 0 ) {
237                     addSubelement( category, "External nodes without taxonomy", String.valueOf( no_tax ) );
238                 }
239                 //TODO remove me...
240                 for( final Taxonomy taxonomy : distinct_tax.keySet() ) {
241                     System.out.println( taxonomy + ": " + distinct_tax.get( taxonomy ) );
242                 }
243             }
244         }
245         if ( !phylogeny_node.isRoot() ) {
246             addSubelement( category, "Depth", String.valueOf( PhylogenyMethods.calculateDepth( phylogeny_node ) ) );
247             final double d = PhylogenyMethods.calculateDistanceToRoot( phylogeny_node );
248             if ( d > 0 ) {
249                 addSubelement( category, "Distance to root", String.valueOf( ForesterUtil.FORMATTER_6.format( d ) ) );
250             }
251         }
252     }
253
254     private static void addBinaryCharacters( final DefaultMutableTreeNode top,
255                                              final BinaryCharacters bc,
256                                              final String name ) {
257         DefaultMutableTreeNode category;
258         category = new DefaultMutableTreeNode( name );
259         top.add( category );
260         addSubelement( category, "Gained", String.valueOf( bc.getGainedCount() ) );
261         addSubelement( category, "Lost", String.valueOf( bc.getLostCount() ) );
262         addSubelement( category, "Present", String.valueOf( bc.getPresentCount() ) );
263         final DefaultMutableTreeNode chars = new DefaultMutableTreeNode( "Lists" );
264         category.add( chars );
265         addSubelement( chars, "Gained", bc.getGainedCharactersAsStringBuffer().toString() );
266         addSubelement( chars, "Lost", bc.getLostCharactersAsStringBuffer().toString() );
267         addSubelement( chars, "Present", bc.getPresentCharactersAsStringBuffer().toString() );
268     }
269
270     private static void addDate( final DefaultMutableTreeNode top, final Date date, final String name ) {
271         DefaultMutableTreeNode category;
272         category = new DefaultMutableTreeNode( name );
273         top.add( category );
274         addSubelement( category, DATE_DESCRIPTION, date.getDesc() );
275         addSubelement( category, DATE_VALUE, String.valueOf( date.getValue() ) );
276         addSubelement( category, DATE_MIN, String.valueOf( date.getMin() ) );
277         addSubelement( category, DATE_MAX, String.valueOf( date.getMax() ) );
278         addSubelement( category, DATE_UNIT, date.getUnit() );
279     }
280
281     private static void addDistribution( final DefaultMutableTreeNode top, final Distribution dist, final String name ) {
282         DefaultMutableTreeNode category;
283         category = new DefaultMutableTreeNode( name );
284         top.add( category );
285         addSubelement( category, DIST_DESCRIPTION, dist.getDesc() );
286         if ( ( dist.getPoints() != null ) && ( dist.getPoints().size() > 0 ) ) {
287             final Point p0 = dist.getPoints().get( 0 );
288             if ( p0 != null ) {
289                 addSubelement( category, DIST_GEODETIC_DATUM, p0.getGeodeticDatum() );
290                 addSubelement( category, DIST_LATITUDE, String.valueOf( p0.getLatitude() ) );
291                 addSubelement( category, DIST_LONGITUDE, String.valueOf( p0.getLongitude() ) );
292                 String alt_unit = p0.getAltiudeUnit();
293                 if ( ForesterUtil.isEmpty( alt_unit ) ) {
294                     alt_unit = "?";
295                 }
296                 addSubelement( category, DIST_ALTITUDE, String.valueOf( p0.getAltitude() ) + alt_unit );
297             }
298         }
299     }
300
301     private static void addEvents( final DefaultMutableTreeNode top, final Event events, final String name ) {
302         DefaultMutableTreeNode category;
303         category = new DefaultMutableTreeNode( name );
304         top.add( category );
305         if ( events.getNumberOfDuplications() > 0 ) {
306             addSubelement( category, EVENTS_DUPLICATIONS, String.valueOf( events.getNumberOfDuplications() ) );
307         }
308         if ( events.getNumberOfSpeciations() > 0 ) {
309             addSubelement( category, EVENTS_SPECIATIONS, String.valueOf( events.getNumberOfSpeciations() ) );
310         }
311         if ( events.getNumberOfGeneLosses() > 0 ) {
312             addSubelement( category, EVENTS_GENE_LOSSES, String.valueOf( events.getNumberOfGeneLosses() ) );
313         }
314         addSubelement( category, "Type", events.getEventType().toString() );
315         if ( events.getConfidence() != null ) {
316             addSubelement( category, CONFIDENCE, events.getConfidence().asText().toString() );
317         }
318     }
319
320     private static void addProperties( final DefaultMutableTreeNode top,
321                                        final PropertiesMap properties,
322                                        final String string ) {
323         final SortedMap<String, Property> properties_map = properties.getProperties();
324         final DefaultMutableTreeNode category = new DefaultMutableTreeNode( "Properties " );
325         top.add( category );
326         for( final String key : properties_map.keySet() ) {
327             final Property prop = properties_map.get( key );
328             category.add( new DefaultMutableTreeNode( prop.getRef() + " " + prop.getValue() + " " + prop.getUnit()
329                     + " [" + prop.getAppliesTo().toString() + "]" ) );
330         }
331     }
332
333     private static void addReference( final DefaultMutableTreeNode top, final Reference ref, final String name ) {
334         final DefaultMutableTreeNode category = new DefaultMutableTreeNode( name );
335         top.add( category );
336         addSubelement( category, LIT_REFERENCE_DOI, ref.getDoi() );
337         addSubelement( category, LIT_REFERENCE_DESC, ref.getDescription() );
338     }
339
340     private static void addSequence( final DefaultMutableTreeNode top, final Sequence seq, final String name ) {
341         final DefaultMutableTreeNode category = new DefaultMutableTreeNode( name );
342         top.add( category );
343         addSubelement( category, SEQ_NAME, seq.getName() );
344         addSubelement( category, SEQ_SYMBOL, seq.getSymbol() );
345         if ( seq.getAccession() != null ) {
346             addSubelement( category, SEQ_ACCESSION, seq.getAccession().asText().toString() );
347         }
348         addSubelement( category, SEQ_LOCATION, seq.getLocation() );
349         addSubelement( category, SEQ_TYPE, seq.getType() );
350         addSubelement( category, SEQ_MOL_SEQ, seq.getMolecularSequence() );
351         if ( ( seq.getUris() != null ) && !seq.getUris().isEmpty() ) {
352             addUris( top, seq.getUris(), category );
353         }
354         addAnnotations( top, seq.getAnnotations(), category );
355     }
356
357     private static void addSubelement( final DefaultMutableTreeNode node, final String name, final String value ) {
358         if ( !ForesterUtil.isEmpty( value ) ) {
359             node.add( new DefaultMutableTreeNode( name + ": " + value ) );
360         }
361     }
362
363     private static void addTaxonomy( final DefaultMutableTreeNode top, final Taxonomy tax, final String name ) {
364         final DefaultMutableTreeNode category = new DefaultMutableTreeNode( name );
365         top.add( category );
366         if ( tax.getIdentifier() != null ) {
367             addSubelement( category, TAXONOMY_IDENTIFIER, tax.getIdentifier().asText().toString() );
368         }
369         addSubelement( category, TAXONOMY_CODE, tax.getTaxonomyCode() );
370         addSubelement( category, TAXONOMY_SCIENTIFIC_NAME, tax.getScientificName() );
371         addSubelement( category, TAXONOMY_AUTHORITY, tax.getAuthority() );
372         addSubelement( category, TAXONOMY_COMMON_NAME, tax.getCommonName() );
373         for( final String syn : tax.getSynonyms() ) {
374             addSubelement( category, TAXONOMY_SYNONYM, syn );
375         }
376         addSubelement( category, TAXONOMY_RANK, tax.getRank() );
377         if ( ( tax.getUris() != null ) && !tax.getUris().isEmpty() ) {
378             addUris( top, tax.getUris(), category );
379         }
380     }
381
382     private static void createNodes( final DefaultMutableTreeNode top, final PhylogenyNode phylogeny_node ) {
383         addBasics( top, phylogeny_node, BASIC );
384         // Taxonomy
385         if ( phylogeny_node.getNodeData().isHasTaxonomy() ) {
386             addTaxonomy( top, phylogeny_node.getNodeData().getTaxonomy(), TAXONOMY );
387         }
388         // Sequence
389         if ( phylogeny_node.getNodeData().isHasSequence() ) {
390             addSequence( top, phylogeny_node.getNodeData().getSequence(), SEQUENCE );
391         }
392         // Events
393         if ( phylogeny_node.getNodeData().isHasEvent() ) {
394             addEvents( top, phylogeny_node.getNodeData().getEvent(), EVENTS );
395         }
396         // Date
397         if ( phylogeny_node.getNodeData().isHasDate() ) {
398             addDate( top, phylogeny_node.getNodeData().getDate(), DATE );
399         }
400         // Distribution
401         if ( phylogeny_node.getNodeData().isHasDistribution() ) {
402             addDistribution( top, phylogeny_node.getNodeData().getDistribution(), DISTRIBUTION );
403         }
404         // Reference
405         if ( phylogeny_node.getNodeData().isHasReference() ) {
406             addReference( top, phylogeny_node.getNodeData().getReference(), LIT_REFERENCE );
407         }
408         // BinaryCharacters
409         if ( phylogeny_node.getNodeData().isHasBinaryCharacters() ) {
410             addBinaryCharacters( top, phylogeny_node.getNodeData().getBinaryCharacters(), BINARY_CHARACTERS );
411         }
412         // Properties
413         if ( phylogeny_node.getNodeData().isHasProperties() ) {
414             addProperties( top, phylogeny_node.getNodeData().getProperties(), PROP );
415         }
416     }
417 }