Adding changes from JWS2 branch. Fixes for Limit in particular
[jabaws.git] / datamodel / compbio / metadata / Limit.java
1 /* Copyright (c) 2009 Peter Troshin\r
2  *  \r
3  *  JAva Bioinformatics Analysis Web Services (JABAWS) @version: 1.0\r
4  * \r
5  *  This library is free software; you can redistribute it and/or modify it under the terms of the\r
6  *  Apache License version 2 as published by the Apache Software Foundation\r
7  * \r
8  *  This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without\r
9  *  even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Apache \r
10  *  License for more details.\r
11  * \r
12  *  A copy of the license is in apache_license.txt. It is also available here:\r
13  * @see: http://www.apache.org/licenses/LICENSE-2.0.txt\r
14  * \r
15  * Any republication or derived work distributed in source code form\r
16  * must include this copyright and license notice.\r
17  */\r
18 \r
19 package compbio.metadata;\r
20 \r
21 import java.util.List;\r
22 \r
23 import javax.xml.bind.annotation.XmlAccessType;\r
24 import javax.xml.bind.annotation.XmlAccessorType;\r
25 import javax.xml.bind.annotation.XmlAttribute;\r
26 \r
27 import compbio.data.sequence.FastaSequence;\r
28 import compbio.util.SysPrefs;\r
29 \r
30 /**\r
31  * A value object containing a maximum number of sequences and a maximum average\r
32  * sequence length for a preset. Also contains static method for determining the\r
33  * number of sequence and their average length in the List<FastaSequence>\r
34  * \r
35  * \r
36  * @author pvtroshin\r
37  * \r
38  * @version 1.0 January 2010\r
39  * \r
40  * @param <T>\r
41  *            the type of an executable for which this limit is defined.\r
42  * \r
43  * @see LimitsManager\r
44  */\r
45 @XmlAccessorType(XmlAccessType.FIELD)\r
46 public class Limit<T> {\r
47 \r
48         // Allowed to be null\r
49         private String preset;\r
50         // Cannot be 0 or below\r
51         private int seqNumber;\r
52         // Can be 0 - i.e. undefined\r
53         private int seqLength;\r
54 \r
55         @XmlAttribute\r
56         boolean isDefault;\r
57 \r
58         private Limit() {\r
59                 // JAXB default constructor\r
60         }\r
61 \r
62         /**\r
63          * Instantiate the limit\r
64          * \r
65          * @param seqNumber\r
66          *            the maximum number of sequences allowed for calculation.\r
67          *            Required\r
68          * @param seqLength\r
69          *            the average length of the sequence, optional\r
70          * @param preset\r
71          *            the name of preset if any, optional\r
72          * @throws IllegalArgumentException\r
73          *             if the seqNumber is not supplied or the seqLength is negative\r
74          */\r
75         public Limit(int seqNumber, int seqLength, String preset) {\r
76                 if (seqNumber <= 0) {\r
77                         throw new IllegalArgumentException(\r
78                                         "seqNumber - a maximum number of sequences to align must be greater than 0. Value given:"\r
79                                                         + seqNumber);\r
80                 }\r
81                 if (seqLength < 0) {\r
82                         throw new IllegalArgumentException(\r
83                                         "seqLength - an average sequence length must be greater than 0. Value given:"\r
84                                                         + seqLength);\r
85                 }\r
86                 this.seqNumber = seqNumber;\r
87                 this.seqLength = seqLength;\r
88                 this.preset = preset;\r
89                 this.isDefault = false;\r
90         }\r
91 \r
92         public Limit(int seqNumber, int seqLength, String preset, boolean isDefault) {\r
93                 this(seqNumber, seqNumber, preset);\r
94                 this.isDefault = isDefault;\r
95         }\r
96 \r
97         public String getPreset() {\r
98                 return preset;\r
99         }\r
100 \r
101         /**\r
102          * \r
103          * @return the allowed average sequence length\r
104          */\r
105         public int getAvgSeqLength() {\r
106                 return seqLength;\r
107         }\r
108 \r
109         /**\r
110          * \r
111          * @return the maximum number of sequences allowed\r
112          */\r
113         public int getSeqNumber() {\r
114                 return seqNumber;\r
115         }\r
116 \r
117         /**\r
118          * \r
119          * @return true is this is a default limit to be used, false otherwise\r
120          */\r
121         public boolean isDefault() {\r
122                 return isDefault;\r
123         }\r
124 \r
125         @Override\r
126         public int hashCode() {\r
127                 final int prime = 31;\r
128                 int result = 1;\r
129                 result = prime * result + ((preset == null) ? 0 : preset.hashCode());\r
130                 result = prime * result + seqLength;\r
131                 result = prime * result + seqNumber;\r
132                 return result;\r
133         }\r
134 \r
135         @Override\r
136         public boolean equals(Object obj) {\r
137                 if (this == obj)\r
138                         return true;\r
139                 if (obj == null)\r
140                         return false;\r
141                 if (getClass() != obj.getClass())\r
142                         return false;\r
143                 Limit other = (Limit) obj;\r
144                 if (preset == null) {\r
145                         if (other.preset != null)\r
146                                 return false;\r
147                 } else if (!preset.equals(other.preset))\r
148                         return false;\r
149                 if (seqLength != other.seqLength)\r
150                         return false;\r
151                 if (seqNumber != other.seqNumber)\r
152                         return false;\r
153                 return true;\r
154         }\r
155 \r
156         @Override\r
157         public String toString() {\r
158                 String value = "";\r
159                 if (isDefault) {\r
160                         value = "Default Limit" + SysPrefs.newlinechar;\r
161                 } else {\r
162                         value = "Limit for Preset '" + preset + "'" + SysPrefs.newlinechar;\r
163                 }\r
164                 value += "Maximum sequence number=" + seqNumber + SysPrefs.newlinechar;\r
165                 value += "Average sequence length=" + seqLength + SysPrefs.newlinechar;\r
166                 value += SysPrefs.newlinechar;\r
167                 return value;\r
168         }\r
169 \r
170         /*\r
171          * Calculates total number of letters allowed\r
172          */\r
173         long numberOfLetters() {\r
174                 return this.seqNumber * this.seqLength;\r
175         }\r
176 \r
177         /**\r
178          * Checks if the number of sequences or their average length in the dataset\r
179          * exceeds this limit.\r
180          * \r
181          * @param data\r
182          *            the dataset to measure\r
183          * @return true if a limit is exceeded (what is the dataset is larger then\r
184          *         the limit), false otherwise. First check the number of sequences\r
185          *         in the dataset and if it exceeds the limit return true\r
186          *         irrespective of the average length. If the number of sequences in\r
187          *         the dataset is less than the limit and average length is defined,\r
188          *         then check whether the total number of letters (number of\r
189          *         sequence multiplied by the average sequence length) is greater\r
190          *         then the total number of letters in the dataset. Returns true if\r
191          *         the total number of letters in the dataset is greater than the\r
192          *         limit, false otherwise.\r
193          */\r
194         public boolean isExceeded(List<FastaSequence> data) {\r
195                 if (data == null) {\r
196                         throw new NullPointerException(\r
197                                         "List of fasta sequences is expected!");\r
198                 }\r
199                 if (data.size() > this.seqNumber) {\r
200                         return true;\r
201                 }\r
202                 if (this.seqLength != 0 && data.size() > 0) {\r
203                         if ((long) getAvgSequenceLength(data) * data.size() > numberOfLetters()) {\r
204                                 return true;\r
205                         }\r
206                 }\r
207                 return false;\r
208         }\r
209 \r
210         /**\r
211          * Calculates an average sequence length of the dataset\r
212          * \r
213          * @param data\r
214          * @return an average sequence length in the input dataset\r
215          */\r
216         public static int getAvgSequenceLength(List<FastaSequence> data) {\r
217                 long length = 0;\r
218                 for (FastaSequence seq : data) {\r
219                         length += seq.getLength();\r
220                 }\r
221                 return (int) (length / data.size());\r
222         }\r
223 \r
224         void validate() {\r
225                 if (this.seqNumber < 1) {\r
226                         throw new AssertionError(\r
227                                         "Maximum number of sequences must be defined and be positive! Set value is: "\r
228                                                         + this.seqNumber);\r
229                 }\r
230                 if (this.seqLength != 0 && this.seqLength < 1) {\r
231                         throw new AssertionError(\r
232                                         "Average sequence length must be positive! Set value is: "\r
233                                                         + this.seqLength);\r
234                 }\r
235         }\r
236 }\r