ae9a938b15bb893923528f05293f4b93550e1c44
[jalview.git] / src / jalview / rest / AbstractEndpoint.java
1 package jalview.rest;
2
3 import java.io.IOException;
4 import java.io.PrintWriter;
5 import java.util.HashMap;
6 import java.util.Map;
7 import java.util.Map.Entry;
8
9 import javax.servlet.http.HttpServletRequest;
10 import javax.servlet.http.HttpServletResponse;
11
12 import jalview.bin.Console;
13 import jalview.gui.AlignFrame;
14 import jalview.gui.Desktop;
15 import jalview.rest.RestHandler.EndpointI;
16
17 public abstract class AbstractEndpoint implements EndpointI
18 {
19   private final String path;
20
21   private API api;
22
23   private final String name;
24
25   private final String parameters;
26
27   private final String description;
28
29   private String[] pathParameters = null;
30
31   private Map<String, String[]> queryParameters = null;
32
33   private Map<String, String> options = null;
34
35   private String id = null;
36
37   private String fromId = null;
38
39   public AbstractEndpoint(API api, String path, String name,
40           String parameters, String description)
41   {
42     this.api = api;
43     this.path = path;
44     this.name = name;
45     this.parameters = parameters;
46     this.description = description;
47   }
48
49   public String getPath()
50   {
51     return this.path;
52   }
53
54   protected API getAPI()
55   {
56     return this.api;
57   }
58
59   public String getName()
60   {
61     return this.name;
62   }
63
64   public String getParameters()
65   {
66     return this.parameters;
67   }
68
69   public String getDescription()
70   {
71     return this.description;
72   }
73
74   public abstract void processEndpoint(HttpServletRequest request,
75           HttpServletResponse response);
76
77   /*
78    * Shared methods below here
79    */
80
81   protected String getId(HttpServletRequest request)
82   {
83     if (id != null)
84       return id;
85     id = getQueryParameter(request, "id");
86     return id;
87   }
88
89   protected String getFromId(HttpServletRequest request)
90   {
91     if (fromId != null)
92       return fromId;
93     fromId = getQueryParameter(request, "fromId");
94     return fromId;
95   }
96
97   protected Map<String, String[]> getQueryParameters(
98           HttpServletRequest request)
99   {
100     if (queryParameters != null)
101       return queryParameters;
102     queryParameters = request.getParameterMap();
103     return queryParameters;
104   }
105
106   protected String getQueryParameter(HttpServletRequest request,
107           String param)
108   {
109     String[] vals = getQueryParameters(request).get(param);
110     return (vals == null || vals.length < 1) ? null : vals[0];
111   }
112
113   protected String[] getEndpointPathParameters(HttpServletRequest request)
114   {
115     if (pathParameters != null)
116       return pathParameters;
117     String pathInfo = request.getPathInfo();
118     int slashpos = pathInfo.indexOf('/', 1);
119     if (slashpos < 1)
120       return null;
121
122     pathParameters = pathInfo.substring(slashpos + 1).split("/");
123     return pathParameters;
124   }
125
126   protected Map<String, String> getOptions(HttpServletRequest request)
127   {
128     if (this.options != null)
129       return this.options;
130     Map<String, String> opts = new HashMap<>();
131     for (Entry<String, String[]> e : getQueryParameters(null).entrySet())
132     {
133       if (e.getKey().startsWith("option:"))
134       {
135         for (int i = 0; i < e.getValue().length; i++)
136         {
137           opts.put(e.getKey().substring(7), e.getValue()[i]);
138         }
139       }
140     }
141
142     String[] params = getEndpointPathParameters(request);
143     if (params != null)
144     {
145       for (int i = 0; i < params.length; i++)
146       {
147         String param = params[i];
148         if (param.startsWith("option:"))
149         {
150           int ePos = param.indexOf("=");
151           if (ePos == -1)
152           {
153             opts.put(param.substring(7), null);
154           }
155           else
156           {
157             opts.put(param.substring(7, ePos), param.substring(ePos + 1));
158           }
159         }
160       }
161     }
162     this.options = opts;
163     return opts;
164   }
165
166   protected void returnError(HttpServletRequest request,
167           HttpServletResponse response, String message)
168   {
169     String okString = request.getParameter("ok");
170     boolean ok = (okString != null && okString.equalsIgnoreCase("true"));
171     /*
172      * Annoyingly jetty is not adding content to anything other than a few
173      * 20x status codes. Possibly it is closing the PrintWriter.
174      * Find a fix for this!
175      ****************************************************/
176     response.setStatus(ok ? HttpServletResponse.SC_OK : //
177     // HttpServletResponse.SC_BAD_REQUEST //
178             HttpServletResponse.SC_PARTIAL_CONTENT //
179     );
180
181     String endpointName = getPath();
182     Console.error(getAPI().getName() + " error: endpoint " + endpointName
183             + " failed: '" + message + "'");
184     try
185     {
186       PrintWriter writer = response.getWriter();
187       writer.write("message=Endpoint " + endpointName + ": " + message);
188     } catch (IOException e)
189     {
190       Console.info("Exception writing to REST response", e);
191     }
192   }
193
194   protected boolean checkParameters(HttpServletRequest request,
195           HttpServletResponse response, int i)
196   {
197     String[] parameters = getEndpointPathParameters(request);
198
199     // check we can run fetchsequence
200     if (parameters.length < i)
201     {
202       returnError(request, response,
203               "requires parameters:" + getParameters() + "\n" + getName()
204                       + ": " + getDescription());
205       return false;
206     }
207     return true;
208   }
209
210   public int[][] parseIntRanges(String rangesString)
211   {
212     if (rangesString.equals("*"))
213     {
214       return new int[][] { { -1 }, { -1 } };
215     }
216     String[] rangeStrings = rangesString.split(",");
217     int[][] ranges = new int[2][rangeStrings.length];
218     for (int i = 0; i < rangeStrings.length; i++)
219     {
220       String range = rangeStrings[i];
221       try
222       {
223         int hyphenpos = range.indexOf('-');
224         if (hyphenpos < 0)
225         {
226           ranges[0][i] = Integer.parseInt(range);
227           ranges[1][i] = ranges[0][i];
228         }
229         else
230         {
231           ranges[0][i] = Integer.parseInt(range.substring(0, hyphenpos));
232           ranges[1][i] = Integer.parseInt(range.substring(hyphenpos + 1));
233         }
234       } catch (NumberFormatException nfe)
235       {
236         return null;
237       }
238     }
239     return ranges;
240   }
241
242   /*
243    * Get all AlignFrames or just one if requested to work on a specific window (fromId query string parameter)
244    */
245   protected AlignFrame[] getAlignFrames(HttpServletRequest request,
246           boolean all)
247   {
248     return getAlignFrames(request, "fromId", all);
249   }
250
251   protected AlignFrame[] getAlignFrames(HttpServletRequest request,
252           String idParam, boolean all)
253   {
254     String fromIdString = this.getQueryParameter(request, idParam);
255
256     if (fromIdString != null)
257     {
258       AlignFrame af = AlignFrame.getAlignFrameFromRestId(fromIdString);
259       return af == null ? null : new AlignFrame[] { af };
260     }
261     else if (all)
262     {
263       return Desktop.getAlignFrames();
264     }
265     else
266     {
267       return null;
268     }
269   }
270
271   protected AlignFrame getAlignFrameFromId(HttpServletRequest request)
272   {
273     return getAlignFrameFromId(request, "fromId");
274   }
275
276   protected AlignFrame getAlignFrameFromId(HttpServletRequest request,
277           String idParam)
278   {
279     AlignFrame[] afs = getAlignFrames(request, idParam, false);
280     return (afs == null || afs.length < 1) ? null : afs[0];
281   }
282
283   protected boolean deleteFromCache()
284   {
285     return false;
286   }
287
288 }