5752fbfd6c6d16817adc45242bd87308a924b761
[jalview.git] / forester / java / src / org / forester / phylogeny / PhylogenyBranch.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 // Copyright (C) 2000-2001 Washington University School of Medicine
8 // and Howard Hughes Medical Institute
9 // All rights reserved
10 //
11 // This library is free software; you can redistribute it and/or
12 // modify it under the terms of the GNU Lesser General Public
13 // License as published by the Free Software Foundation; either
14 // version 2.1 of the License, or (at your option) any later version.
15 //
16 // This library is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 // Lesser General Public License for more details.
20 //
21 // You should have received a copy of the GNU Lesser General Public
22 // License along with this library; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 //
25 // Contact: phylosoft @ gmail . com
26 // WWW: www.phylosoft.org/forester
27
28 package org.forester.phylogeny;
29
30 import org.forester.phylogeny.data.PhylogenyData;
31
32 /*
33  * @author Christian M. Zmasek
34  */
35 public class PhylogenyBranch {
36
37     private final PhylogenyNode _node_1;
38     private final PhylogenyNode _node_2;
39     private PhylogenyData       _data;
40     private final boolean       _is_directed;
41     private boolean             _towards_1;
42
43     public PhylogenyBranch( final PhylogenyNode first_node, final PhylogenyNode second_node ) {
44         if ( ( first_node == null ) || ( second_node == null ) ) {
45             throw new IllegalArgumentException( "Attempt to create a branch with a null node" );
46         }
47         _node_1 = first_node;
48         _node_2 = second_node;
49         _is_directed = false;
50     }
51
52     public PhylogenyBranch( final PhylogenyNode first_node,
53                             final PhylogenyNode second_node,
54                             final boolean direction_towards_first ) {
55         if ( ( first_node == null ) || ( second_node == null ) ) {
56             throw new IllegalArgumentException( "Attempt to create a branch with a null node" );
57         }
58         _node_1 = first_node;
59         _node_2 = second_node;
60         _is_directed = true;
61         _towards_1 = direction_towards_first;
62     }
63
64     @Override
65     public boolean equals( final Object obj ) {
66         if ( this == obj ) {
67             return true;
68         }
69         if ( obj == null ) {
70             return false;
71         }
72         if ( getClass() != obj.getClass() ) {
73             return false;
74         }
75         final PhylogenyBranch other = ( PhylogenyBranch ) obj;
76         return hashCode() == other.hashCode();
77     }
78
79     public PhylogenyNode getConnectedNode( final PhylogenyNode node ) throws IllegalArgumentException {
80         if ( node == _node_1 ) {
81             return _node_2;
82         }
83         else if ( node == _node_2 ) {
84             return _node_1;
85         }
86         else {
87             throw new IllegalArgumentException( "Attempt to get " + "connected node on branch with node which is "
88                     + "not connected by the branch" );
89         }
90     }
91
92     public PhylogenyData getData() {
93         return _data;
94     }
95
96     public PhylogenyNode getFirstNode() {
97         return _node_1;
98     }
99
100     public PhylogenyNode getSecondNode() {
101         return _node_2;
102     }
103
104     @Override
105     public int hashCode() {
106         final int PRIME = 31;
107         int result = 1;
108         final int node_1_hc = _node_1.hashCode();
109         final int node_2_hc = _node_2.hashCode();
110         int hc_1 = 0;
111         int hc_2 = 0;
112         if ( !_is_directed ) {
113             if ( node_1_hc > node_2_hc ) {
114                 hc_1 = node_2_hc;
115                 hc_2 = node_1_hc;
116             }
117             else {
118                 hc_1 = node_1_hc;
119                 hc_2 = node_2_hc;
120             }
121         }
122         else {
123             if ( _towards_1 ) {
124                 hc_1 = node_2_hc;
125                 hc_2 = node_1_hc;
126             }
127             else {
128                 hc_1 = node_1_hc;
129                 hc_2 = node_2_hc;
130             }
131         }
132         result = ( PRIME * result ) + ( ( _data == null ) ? 0 : _data.hashCode() );
133         result = ( PRIME * result ) + ( _is_directed ? 1231 : 1237 );
134         result = ( PRIME * result ) + hc_1;
135         result = ( PRIME * result ) + hc_2;
136         return result;
137     }
138
139     public boolean isDirected() {
140         return _is_directed;
141     }
142
143     public boolean isDirectionTowards( final PhylogenyNode node ) throws RuntimeException {
144         if ( !isDirected() ) {
145             throw new RuntimeException( "Attempt to get direction of undirected branch" );
146         }
147         return ( ( node == _node_1 ) && _towards_1 );
148     }
149
150     public void setDirectionTowards( final PhylogenyNode node ) {
151         _towards_1 = node == _node_1;
152     }
153
154     @Override
155     public String toString() {
156         if ( isDirected() ) {
157             if ( isDirectionTowards( getFirstNode() ) ) {
158                 return ( getSecondNode().getName() + " -> " + getFirstNode().getName() );
159             }
160             else {
161                 return ( getFirstNode().getName() + " -> " + getSecondNode().getName() );
162             }
163         }
164         else {
165             return ( getFirstNode().getName() + " -- " + getSecondNode().getName() );
166         }
167     }
168 }