in progress...
[jalview.git] / forester / java / src / org / forester / phylogeny / data / Sequence.java
index b9e6aa3..3561edc 100644 (file)
@@ -37,39 +37,71 @@ import org.forester.io.parsers.phyloxml.PhyloXmlDataFormatException;
 import org.forester.io.parsers.phyloxml.PhyloXmlMapping;
 import org.forester.io.parsers.phyloxml.PhyloXmlUtil;
 import org.forester.io.writers.PhylogenyWriter;
+import org.forester.sequence.MolecularSequence;
+import org.forester.sequence.MolecularSequence.TYPE;
 import org.forester.util.ForesterUtil;
 
-public class Sequence implements PhylogenyData, MultipleUris {
+public class Sequence implements PhylogenyData, MultipleUris, Comparable<Sequence> {
 
+    private Accession              _accession;
+    private SortedSet<Annotation>  _annotations;
+    private DomainArchitecture     _da;
+    private String                 _gene_name;
+    private String                 _location;
     private String                 _mol_sequence;
     private boolean                _mol_sequence_is_aligned;
     private String                 _name;
+    private List<SequenceRelation> _seq_relations;
     private String                 _source_id;
-    private Accession              _accession;
     private String                 _symbol;
-    private String                 _location;
     private String                 _type;
-    private SortedSet<Annotation>  _annotations;
-    private DomainArchitecture     _da;
     private List<Uri>              _uris;
-    private List<SequenceRelation> _seq_relations;
+    private SortedSet<Accession>   _xrefs;
 
     public Sequence() {
         init();
     }
 
-    public boolean isEmpty() {
-        return ( getAccession() == null ) && ForesterUtil.isEmpty( getName() ) && ForesterUtil.isEmpty( getSymbol() )
-                && ForesterUtil.isEmpty( getType() ) && ForesterUtil.isEmpty( getLocation() )
-                && ForesterUtil.isEmpty( getSourceId() ) && ForesterUtil.isEmpty( getMolecularSequence() )
-                && ( getDomainArchitecture() == null ) && ForesterUtil.isEmpty( _annotations )
-                && ForesterUtil.isEmpty( _uris ) && ForesterUtil.isEmpty( _seq_relations );
+    public Sequence( final MolecularSequence mol_seq ) {
+        init();
+        setMolecularSequence( mol_seq.getMolecularSequenceAsString() );
+        setName( mol_seq.getIdentifier() );
+        String type;
+        if ( mol_seq.getType() == TYPE.AA ) {
+            type = "protein";
+        }
+        else if ( mol_seq.getType() == TYPE.DNA ) {
+            type = "dna";
+        }
+        else if ( mol_seq.getType() == TYPE.RNA ) {
+            type = "rna";
+        }
+        else {
+            throw new IllegalArgumentException( "unknown sequence type " + mol_seq.getType() );
+        }
+        try {
+            setType( type );
+        }
+        catch ( final PhyloXmlDataFormatException e ) {
+            throw new IllegalArgumentException( "don't know how to handle type " + mol_seq.getType() );
+        }
     }
 
     public void addAnnotation( final Annotation annotation ) {
         getAnnotations().add( annotation );
     }
 
+    public void addCrossReference( final Accession cross_reference ) {
+        if ( getCrossReferences() == null ) {
+            setCrossReferences( new TreeSet<Accession>() );
+        }
+        getCrossReferences().add( cross_reference );
+    }
+
+    public void addSequenceRelation( final SequenceRelation sr ) {
+        getSequenceRelations().add( sr );
+    }
+
     @Override
     public void addUri( final Uri uri ) {
         if ( getUris() == null ) {
@@ -78,10 +110,6 @@ public class Sequence implements PhylogenyData, MultipleUris {
         getUris().add( uri );
     }
 
-    public void addSequenceRelation( final SequenceRelation sr ) {
-        _seq_relations.add( sr );
-    }
-
     @Override
     public StringBuffer asSimpleText() {
         final StringBuffer sb = new StringBuffer();
@@ -105,15 +133,39 @@ public class Sequence implements PhylogenyData, MultipleUris {
         return asSimpleText();
     }
 
+    @Override
+    public int compareTo( final Sequence o ) {
+        if ( ( !ForesterUtil.isEmpty( getName() ) ) && ( !ForesterUtil.isEmpty( o.getName() ) ) ) {
+            return getName().compareTo( o.getName() );
+        }
+        if ( ( !ForesterUtil.isEmpty( getSymbol() ) ) && ( !ForesterUtil.isEmpty( o.getSymbol() ) ) ) {
+            return getSymbol().compareTo( o.getSymbol() );
+        }
+        if ( ( !ForesterUtil.isEmpty( getGeneName() ) ) && ( !ForesterUtil.isEmpty( o.getGeneName() ) ) ) {
+            return getGeneName().compareTo( o.getGeneName() );
+        }
+        if ( ( getAccession() != null ) && ( o.getAccession() != null )
+                && !ForesterUtil.isEmpty( getAccession().getValue() )
+                && !ForesterUtil.isEmpty( o.getAccession().getValue() ) ) {
+            return getAccession().getValue().compareTo( o.getAccession().getValue() );
+        }
+        if ( ( !ForesterUtil.isEmpty( getMolecularSequence() ) )
+                && ( !ForesterUtil.isEmpty( o.getMolecularSequence() ) ) ) {
+            return getMolecularSequence().compareTo( o.getMolecularSequence() );
+        }
+        return 0;
+    }
+
     /**
      * Not a deep copy.
-     * 
+     *
      */
     @Override
     public PhylogenyData copy() {
         final Sequence seq = new Sequence();
         seq.setAnnotations( getAnnotations() );
         seq.setName( getName() );
+        seq.setGeneName( getGeneName() );
         try {
             seq.setSymbol( getSymbol() );
         }
@@ -149,6 +201,14 @@ public class Sequence implements PhylogenyData, MultipleUris {
         else {
             seq.setDomainArchitecture( null );
         }
+        if ( getCrossReferences() != null ) {
+            seq.setCrossReferences( new TreeSet<Accession>() );
+            for( final Accession x : getCrossReferences() ) {
+                if ( x != null ) {
+                    seq.getCrossReferences().add( x );
+                }
+            }
+        }
         return seq;
     }
 
@@ -184,10 +244,18 @@ public class Sequence implements PhylogenyData, MultipleUris {
         return _annotations;
     }
 
+    public SortedSet<Accession> getCrossReferences() {
+        return _xrefs;
+    }
+
     public DomainArchitecture getDomainArchitecture() {
         return _da;
     }
 
+    public String getGeneName() {
+        return _gene_name;
+    }
+
     public String getLocation() {
         return _location;
     }
@@ -196,10 +264,6 @@ public class Sequence implements PhylogenyData, MultipleUris {
         return _mol_sequence;
     }
 
-    public boolean isMolecularSequenceAligned() {
-        return _mol_sequence_is_aligned;
-    }
-
     public String getName() {
         return _name;
     }
@@ -211,10 +275,6 @@ public class Sequence implements PhylogenyData, MultipleUris {
         return _seq_relations;
     }
 
-    private void setSequenceRelations( final List<SequenceRelation> seq_relations ) {
-        _seq_relations = seq_relations;
-    }
-
     public String getSourceId() {
         return _source_id;
     }
@@ -228,13 +288,13 @@ public class Sequence implements PhylogenyData, MultipleUris {
     }
 
     @Override
-    public List<Uri> getUris() {
-        return _uris;
+    public Uri getUri( final int index ) {
+        return getUris().get( index );
     }
 
     @Override
-    public Uri getUri( final int index ) {
-        return getUris().get( index );
+    public List<Uri> getUris() {
+        return _uris;
     }
 
     @Override
@@ -242,23 +302,26 @@ public class Sequence implements PhylogenyData, MultipleUris {
         if ( getAccession() != null ) {
             return getAccession().hashCode();
         }
-        int result = getSymbol().hashCode();
-        if ( getName().length() > 0 ) {
+        int result = getName().hashCode();
+        if ( getSymbol().length() > 0 ) {
             result ^= getName().hashCode();
         }
+        if ( getGeneName().length() > 0 ) {
+            result ^= getGeneName().hashCode();
+        }
         if ( getMolecularSequence().length() > 0 ) {
             result ^= getMolecularSequence().hashCode();
         }
         return result;
     }
 
-    public boolean hasSequenceRelations() {
-        return _seq_relations.size() > 0;
+    public boolean isHasSequenceRelations() {
+        return _seq_relations != null && _seq_relations.size() > 0;
     }
 
     public void init() {
-        setAnnotations( null );
         setName( "" );
+        setGeneName( "" );
         setMolecularSequence( "" );
         setMolecularSequenceAligned( false );
         setLocation( "" );
@@ -279,6 +342,18 @@ public class Sequence implements PhylogenyData, MultipleUris {
         setUris( null );
         setSequenceRelations( null );
         setSourceId( null );
+        setCrossReferences( null );
+        setAnnotations( null );
+    }
+
+    public boolean isEmpty() {
+        return ( getAccession() == null ) && ForesterUtil.isEmpty( getName() ) && ForesterUtil.isEmpty( getSymbol() )
+                && ForesterUtil.isEmpty( getGeneName() ) && ForesterUtil.isEmpty( getType() )
+                && ForesterUtil.isEmpty( getLocation() ) && ForesterUtil.isEmpty( getSourceId() )
+                && ForesterUtil.isEmpty( getMolecularSequence() ) && ( getDomainArchitecture() == null )
+                && ForesterUtil.isEmpty( _annotations ) && ForesterUtil.isEmpty( _uris )
+                && ForesterUtil.isEmpty( _seq_relations )
+                && ( ( getCrossReferences() == null ) || getCrossReferences().isEmpty() );
     }
 
     @Override
@@ -291,21 +366,25 @@ public class Sequence implements PhylogenyData, MultipleUris {
             return getAccession().isEqual( s.getAccession() );
         }
         return s.getMolecularSequence().equals( getMolecularSequence() ) && s.getName().equals( getName() )
-                && s.getSymbol().equals( getSymbol() );
+                && s.getSymbol().equals( getSymbol() ) && s.getGeneName().equals( getGeneName() );
     }
 
-    public void setAccession( final Accession accession ) {
-        _accession = accession;
+    public boolean isMolecularSequenceAligned() {
+        return _mol_sequence_is_aligned;
     }
 
-    private void setAnnotations( final SortedSet<Annotation> annotations ) {
-        _annotations = annotations;
+    public void setAccession( final Accession accession ) {
+        _accession = accession;
     }
 
     public void setDomainArchitecture( final DomainArchitecture ds ) {
         _da = ds;
     }
 
+    public void setGeneName( final String gene_name ) {
+        _gene_name = gene_name;
+    }
+
     public void setLocation( final String description ) {
         _location = description;
     }
@@ -356,9 +435,6 @@ public class Sequence implements PhylogenyData, MultipleUris {
         if ( getAccession() != null ) {
             getAccession().toNHX();
         }
-        if ( getDomainArchitecture() != null ) {
-            sb.append( getDomainArchitecture().toNHX() );
-        }
         return sb;
     }
 
@@ -380,6 +456,9 @@ public class Sequence implements PhylogenyData, MultipleUris {
         if ( !ForesterUtil.isEmpty( getName() ) ) {
             PhylogenyDataUtil.appendElement( writer, PhyloXmlMapping.SEQUENCE_NAME, getName(), indentation );
         }
+        if ( !ForesterUtil.isEmpty( getGeneName() ) ) {
+            PhylogenyDataUtil.appendElement( writer, PhyloXmlMapping.SEQUENCE_GENE_NAME, getGeneName(), indentation );
+        }
         if ( !ForesterUtil.isEmpty( getLocation() ) ) {
             PhylogenyDataUtil.appendElement( writer, PhyloXmlMapping.SEQUENCE_LOCATION, getLocation(), indentation );
         }
@@ -391,18 +470,29 @@ public class Sequence implements PhylogenyData, MultipleUris {
                                              String.valueOf( isMolecularSequenceAligned() ),
                                              indentation );
         }
-        if ( getUris() != null ) {
+        if ( ( getUris() != null ) && !getUris().isEmpty() ) {
             for( final Uri uri : getUris() ) {
                 if ( uri != null ) {
                     uri.toPhyloXML( writer, level, indentation );
                 }
             }
         }
-        if ( _annotations != null ) {
+        if ( ( getAnnotations() != null ) && !getAnnotations().isEmpty() ) {
             for( final PhylogenyData annotation : getAnnotations() ) {
                 annotation.toPhyloXML( writer, level, my_ind );
             }
         }
+        if ( ( getCrossReferences() != null ) && !getCrossReferences().isEmpty() ) {
+            writer.write( ForesterUtil.LINE_SEPARATOR );
+            writer.write( my_ind );
+            PhylogenyDataUtil.appendOpen( writer, PhyloXmlMapping.SEQUENCE_X_REFS );
+            for( final PhylogenyData x : getCrossReferences() ) {
+                x.toPhyloXML( writer, level, my_ind );
+            }
+            writer.write( ForesterUtil.LINE_SEPARATOR );
+            writer.write( my_ind );
+            PhylogenyDataUtil.appendClose( writer, PhyloXmlMapping.SEQUENCE_X_REFS );
+        }
         if ( getDomainArchitecture() != null ) {
             getDomainArchitecture().toPhyloXML( writer, level, my_ind );
         }
@@ -415,4 +505,16 @@ public class Sequence implements PhylogenyData, MultipleUris {
     public String toString() {
         return asText().toString();
     }
+
+    private void setAnnotations( final SortedSet<Annotation> annotations ) {
+        _annotations = annotations;
+    }
+
+    private void setCrossReferences( final TreeSet<Accession> cross_references ) {
+        _xrefs = cross_references;
+    }
+
+    private void setSequenceRelations( final List<SequenceRelation> seq_relations ) {
+        _seq_relations = seq_relations;
+    }
 }