applied LGPLv3 and source code formatting.
[vamsas.git] / src / uk / ac / vamsas / client / picking / SelectionMessage.java
1 /*\r
2  * This file is part of the Vamsas Client version 0.1. \r
3  * Copyright 2009 by Jim Procter, Iain Milne, Pierre Marguerite, \r
4  *  Andrew Waterhouse and Dominik Lindner.\r
5  * \r
6  * Earlier versions have also been incorporated into Jalview version 2.4 \r
7  * since 2008, and TOPALi version 2 since 2007.\r
8  * \r
9  * The Vamsas Client is free software: you can redistribute it and/or modify\r
10  * it under the terms of the GNU Lesser General Public License as published by\r
11  * the Free Software Foundation, either version 3 of the License, or\r
12  * (at your option) any later version.\r
13  *  \r
14  * The Vamsas Client is distributed in the hope that it will be useful,\r
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
17  * GNU Lesser General Public License for more details.\r
18  * \r
19  * You should have received a copy of the GNU Lesser General Public License\r
20  * along with the Vamsas Client.  If not, see <http://www.gnu.org/licenses/>.\r
21  */\r
22 package uk.ac.vamsas.client.picking;\r
23 \r
24 import uk.ac.vamsas.objects.core.Input;\r
25 import uk.ac.vamsas.objects.core.Pos;\r
26 import uk.ac.vamsas.objects.core.RangeType;\r
27 import uk.ac.vamsas.objects.core.Seg;\r
28 \r
29 /**\r
30  * Send and receive details about vamsas object selections and selection ranges\r
31  * defined on one or more objects.\r
32  * \r
33  * @author J.B. Procter\r
34  * \r
35  */\r
36 public class SelectionMessage extends Message {\r
37   private String selectionID;\r
38 \r
39   private String[] vorbaIDs;\r
40 \r
41   RangeType ranges;\r
42 \r
43   private boolean none = false;\r
44 \r
45   /**\r
46    * parse a message payload as a selection message\r
47    * \r
48    * @param str\r
49    */\r
50   public SelectionMessage(String str) {\r
51     message = str;\r
52     // Parse message into ...\r
53     String[] elements = str.split("\t");\r
54     String positions[] = null, segs[] = null;\r
55     for (int i = 0; i < elements.length; i++) {\r
56       if (elements[i].startsWith("selectionID="))\r
57         selectionID = elements[i].substring(12);\r
58       if (elements[i].startsWith("vorbaIDs="))\r
59         vorbaIDs = elements[i].substring(9).split("\\|");\r
60       if (elements[i].startsWith("positions=")) {\r
61         positions = elements[i].substring(10).split(",");\r
62       }\r
63       if (elements[i].startsWith("ranges=")) {\r
64         segs = elements[i].substring(7).split(",");\r
65       }\r
66       if (elements[i].equals("none")) {\r
67         none = true;\r
68       }\r
69     }\r
70     if (none) {\r
71       ranges = null;\r
72       vorbaIDs = null;\r
73     }\r
74     if (positions != null) {\r
75       ranges = new Input();\r
76       for (int i = 0; i < positions.length; i++) {\r
77         Pos p = new Pos();\r
78         try {\r
79           p.setI(Integer.parseInt(positions[i]));\r
80           ranges.addPos(p);\r
81         } catch (Exception e) {\r
82           // invalid message - ignore element\r
83         }\r
84       }\r
85     } else if (segs != null) {\r
86       ranges = new Input();\r
87       for (int i = 0; i < segs.length; i += 2) {\r
88         Seg s = new Seg();\r
89         s.setInclusive(segs[i].startsWith("["));\r
90         try {\r
91           s.setStart(Integer.parseInt(segs[i].substring(1)));\r
92           s.setEnd(Integer.parseInt(segs[i + 1]));\r
93           ranges.addSeg(s);\r
94         } catch (Exception e) {\r
95           // invalid message - again ignore element\r
96         }\r
97       }\r
98     }\r
99 \r
100   }\r
101 \r
102   /**\r
103    * create a new selection message\r
104    * \r
105    * @param selectionID\r
106    *          - (may be null) optional handle (or ID) to refer to selection by\r
107    * @param vorbaIDs\r
108    *          - one or more objects to be selected, or null for the empty\r
109    *          selection\r
110    * @param ranges\r
111    *          optional rangetype specifying positions or intervals over\r
112    *          object(s) coordinate system.\r
113    */\r
114   public SelectionMessage(String selectionID, String[] vorbaIDs,\r
115       RangeType ranges) {\r
116     this(selectionID, vorbaIDs, ranges, false);\r
117   }\r
118 \r
119   public SelectionMessage(String selectionID, String[] vorbaIDs,\r
120       RangeType ranges, boolean none) {\r
121     super();\r
122     this.selectionID = selectionID;\r
123     if (selectionID != null && selectionID.indexOf("\t") > -1) {\r
124       throw new Error(\r
125           "VAMSAS Selection Messages are not allowed to have Tab Characters in their selection ID");\r
126     }\r
127     this.vorbaIDs = vorbaIDs;\r
128     this.ranges = ranges;\r
129     this.none = none;\r
130     StringBuffer message = new StringBuffer();\r
131     message.append("SELECTION\t");\r
132     if (selectionID != null) {\r
133       message.append("selectionID=" + selectionID);\r
134       message.append("\t");\r
135     }\r
136     message.append("vorbaIDs=");\r
137     for (int ids = 0; ids < vorbaIDs.length; ids++) {\r
138       if (ids > 0) {\r
139         message.append("|");\r
140       }\r
141       if (vorbaIDs[ids] == null) {\r
142         throw new Error("null vorbaID in SelectionMessage ID vector.(" + ids\r
143             + ")");\r
144       }\r
145       if (vorbaIDs[ids].indexOf("\t") > -1) {\r
146         throw new Error(\r
147             "Invalid vorbaID string in SelectionMessage ID vector. ("\r
148                 + vorbaIDs[ids] + ")");\r
149       }\r
150       message.append(vorbaIDs[ids]);\r
151     }\r
152     if (none) {\r
153       // must have only IDs for the selection or the selection scope - no range\r
154       if (ranges != null) {\r
155         throw new Error("Empty selection cannot specify a range.");\r
156       }\r
157       if ((selectionID == null || selectionID.length() == 0)\r
158           && (vorbaIDs == null || vorbaIDs.length == 0)) {\r
159         throw new Error(\r
160             "Empty selection must have at least a selection ID or at least one vorbaID indicating selection scope.");\r
161       }\r
162       message.append("none");\r
163       return;\r
164     }\r
165     // Verify that the range has at least one valid vorbaID for it to be defined\r
166     // on.\r
167     if (vorbaIDs == null || vorbaIDs.length == 0) {\r
168       throw new Error(\r
169           "You must specify at least one vorbaID for the selection.");\r
170     }\r
171     if (ranges != null) {\r
172       if (ranges.getPosCount() > 0) {\r
173         message.append("\tpositions=");\r
174         Pos[] pos = ranges.getPos();\r
175         for (int p = 0; p < pos.length; p++) {\r
176           if (p > 0) {\r
177             message.append(",");\r
178           }\r
179           message.append(pos[p].getI());\r
180         }\r
181       } else if (ranges.getSegCount() > 0) {\r
182         message.append("\tranges=");\r
183         Seg[] rng = ranges.getSeg();\r
184         for (int p = 0; p < rng.length; p++) {\r
185           boolean inc = rng[p].getInclusive();\r
186           if (p > 0) {\r
187             message.append(",");\r
188           }\r
189           if (inc) {\r
190             message.append("[");\r
191           } else {\r
192             message.append("(");\r
193           }\r
194           message.append(rng[p].getStart());\r
195           message.append(",");\r
196           message.append(rng[p].getEnd());\r
197         }\r
198       }\r
199     }\r
200     message.append("\n");\r
201     this.message = message.toString();\r
202   }\r
203 \r
204   /**\r
205    * @return the selectionID\r
206    */\r
207   public String getSelectionID() {\r
208     return selectionID;\r
209   }\r
210 \r
211   /**\r
212    * @return the vorbaIDs\r
213    */\r
214   public String[] getVorbaIDs() {\r
215     return vorbaIDs;\r
216   }\r
217 \r
218   /**\r
219    * @return the ranges\r
220    */\r
221   public RangeType getRanges() {\r
222     return ranges;\r
223   }\r
224 \r
225   /**\r
226    * @return the none\r
227    */\r
228   public boolean isNone() {\r
229     return none;\r
230   }\r
231 }\r