JAL-3060 entry points for createFeatures, amendFeatures
[jalview.git] / src / jalview / io / BioJsHTMLOutput.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.io;
22
23 import jalview.exceptions.NoFileSelectedException;
24 import jalview.gui.AlignmentPanel;
25 import jalview.gui.OOMWarning;
26 import jalview.json.binding.biojs.BioJSReleasePojo;
27 import jalview.json.binding.biojs.BioJSRepositoryPojo;
28 import jalview.util.MessageManager;
29
30 import java.io.BufferedInputStream;
31 import java.io.BufferedReader;
32 import java.io.File;
33 import java.io.IOException;
34 import java.io.InputStream;
35 import java.io.InputStreamReader;
36 import java.io.PrintWriter;
37 import java.net.URISyntaxException;
38 import java.net.URL;
39 import java.util.Objects;
40 import java.util.TreeMap;
41
42 public class BioJsHTMLOutput extends HTMLOutput
43 {
44
45   private static File currentBJSTemplateFile;
46
47   private static TreeMap<String, File> bioJsMSAVersions;
48
49   public static final String DEFAULT_DIR = System.getProperty("user.home")
50           + File.separatorChar + ".biojs_templates" + File.separatorChar;
51
52   public static final String BJS_TEMPLATES_LOCAL_DIRECTORY = jalview.bin.Cache
53           .getDefault("biojs_template_directory", DEFAULT_DIR);
54
55   public static final String BJS_TEMPLATE_GIT_REPO = jalview.bin.Cache
56           .getDefault("biojs_template_git_repo",
57                   "https://raw.githubusercontent.com/jalview/exporter-templates/master/biojs/package.json");
58
59   public BioJsHTMLOutput(AlignmentPanel ap)
60   {
61     super(ap);
62   }
63
64   @Override
65   public void exportHTML(String outputFile)
66   {
67     exportStarted();
68     try
69     {
70       if (outputFile == null)
71       {
72         outputFile = getOutputFile();
73       }
74       generatedFile = new File(outputFile);
75     } catch (NoFileSelectedException e)
76     {
77       setProgressMessage(MessageManager.formatMessage(
78               "status.cancelled_image_export_operation", "BioJS MSA"));
79       return;
80     } catch (Exception e)
81     {
82       setProgressMessage(MessageManager
83               .formatMessage("info.error_creating_file", "BioJS MSA"));
84       e.printStackTrace();
85       return;
86     }
87     new Thread(this).start();
88
89   }
90
91   public static void refreshVersionInfo(String dirName)
92           throws URISyntaxException
93   {
94     File directory = new File(BJS_TEMPLATES_LOCAL_DIRECTORY);
95     Objects.requireNonNull(dirName, "dirName MUST not be null!");
96     Objects.requireNonNull(directory, "directory MUST not be null!");
97     TreeMap<String, File> versionFileMap = new TreeMap<String, File>();
98
99     for (File file : directory.listFiles())
100     {
101       if (file.isFile())
102       {
103         String fileName = file.getName().substring(0,
104                 file.getName().lastIndexOf("."));
105         String fileMeta[] = fileName.split("_");
106         if (fileMeta.length > 2)
107         {
108           setCurrentBJSTemplateFile(file);
109           versionFileMap.put(fileMeta[2], file);
110         }
111         else if (fileMeta.length > 1)
112         {
113           versionFileMap.put(fileMeta[1], file);
114         }
115       }
116     }
117     if (getCurrentBJSTemplateFile() == null && versionFileMap.size() > 0)
118     {
119       setCurrentBJSTemplateFile(versionFileMap.lastEntry().getValue());
120     }
121     setBioJsMSAVersions(versionFileMap);
122   }
123
124   public static void updateBioJS()
125   {
126     Thread updateThread = new Thread()
127     {
128       @Override
129       public void run()
130       {
131         try
132         {
133           String gitRepoPkgJson = getURLContentAsString(
134                   BJS_TEMPLATE_GIT_REPO);
135           if (gitRepoPkgJson != null)
136           {
137             BioJSRepositoryPojo release = new BioJSRepositoryPojo(
138                     gitRepoPkgJson);
139             syncUpdates(BJS_TEMPLATES_LOCAL_DIRECTORY, release);
140             refreshVersionInfo(BJS_TEMPLATES_LOCAL_DIRECTORY);
141           }
142         } catch (URISyntaxException e)
143         {
144           e.printStackTrace();
145         }
146       }
147     };
148     updateThread.start();
149
150   }
151
152   public static void syncUpdates(String localDir, BioJSRepositoryPojo repo)
153   {
154     for (BioJSReleasePojo bjsRelease : repo.getReleases())
155     {
156       String releaseUrl = bjsRelease.getUrl();
157       String releaseVersion = bjsRelease.getVersion();
158       String releaseFile = "BioJsMSA_" + releaseVersion + ".txt";
159       if (releaseVersion.equals(repo.getLatestReleaseVersion()))
160       {
161         releaseFile = "Latest_BioJsMSA_" + releaseVersion + ".txt";
162       }
163
164       File biojsDirectory = new File(BJS_TEMPLATES_LOCAL_DIRECTORY);
165       if (!biojsDirectory.exists())
166       {
167         if (!biojsDirectory.mkdirs())
168         {
169           System.out.println("Couldn't create local directory : "
170                   + BJS_TEMPLATES_LOCAL_DIRECTORY);
171           return;
172         }
173       }
174
175       File file = new File(BJS_TEMPLATES_LOCAL_DIRECTORY + releaseFile);
176       if (!file.exists())
177       {
178
179         PrintWriter out = null;
180         try
181         {
182           out = new java.io.PrintWriter(new java.io.FileWriter(file));
183           out.print(getURLContentAsString(releaseUrl));
184         } catch (IOException e)
185         {
186           e.printStackTrace();
187         } finally
188         {
189           if (out != null)
190           {
191             out.flush();
192             out.close();
193           }
194         }
195       }
196     }
197
198   }
199
200   public static String getURLContentAsString(String url)
201           throws OutOfMemoryError
202   {
203     StringBuilder responseStrBuilder = null;
204     InputStream is = null;
205     try
206     {
207       URL resourceUrl = new URL(url);
208       is = new BufferedInputStream(resourceUrl.openStream());
209       BufferedReader br = new BufferedReader(new InputStreamReader(is));
210       responseStrBuilder = new StringBuilder();
211       String lineContent;
212
213       while ((lineContent = br.readLine()) != null)
214       {
215         responseStrBuilder.append(lineContent).append("\n");
216       }
217     } catch (OutOfMemoryError er)
218     {
219       er.printStackTrace();
220     } catch (Exception ex)
221     {
222       ex.printStackTrace();
223     } finally
224     {
225       if (is != null)
226       {
227         try
228         {
229           is.close();
230         } catch (IOException e)
231         {
232           e.printStackTrace();
233         }
234       }
235     }
236     return responseStrBuilder == null ? null
237             : responseStrBuilder.toString();
238   }
239
240   public static File getCurrentBJSTemplateFile()
241   {
242     return currentBJSTemplateFile;
243   }
244
245   public static void setCurrentBJSTemplateFile(File currentBJSTemplateFile)
246   {
247     BioJsHTMLOutput.currentBJSTemplateFile = currentBJSTemplateFile;
248   }
249
250   public static TreeMap<String, File> getBioJsMSAVersions()
251   {
252     return bioJsMSAVersions;
253   }
254
255   public static void setBioJsMSAVersions(
256           TreeMap<String, File> bioJsMSAVersions)
257   {
258     BioJsHTMLOutput.bioJsMSAVersions = bioJsMSAVersions;
259   }
260
261   @Override
262   public boolean isEmbedData()
263   {
264     return true;
265   }
266
267   @Override
268   public boolean isLaunchInBrowserAfterExport()
269   {
270     return true;
271   }
272
273   @Override
274   public File getExportedFile()
275   {
276     return generatedFile;
277   }
278
279   @Override
280   public void run()
281   {
282     try
283     {
284       String bioJSON = getBioJSONData();
285       String bioJSTemplateString = HTMLOutput
286               .readFileAsString(getCurrentBJSTemplateFile());
287       String generatedBioJsWithJalviewAlignmentAsJson = bioJSTemplateString
288               .replaceAll("#sequenceData#", bioJSON).toString();
289
290       PrintWriter out = new java.io.PrintWriter(
291               new java.io.FileWriter(generatedFile));
292       out.print(generatedBioJsWithJalviewAlignmentAsJson);
293       out.flush();
294       out.close();
295       setProgressMessage(MessageManager
296               .formatMessage("status.export_complete", "BioJS"));
297       exportCompleted();
298
299     } catch (OutOfMemoryError err)
300     {
301       System.out.println("########################\n" + "OUT OF MEMORY "
302               + generatedFile + "\n" + "########################");
303       new OOMWarning("Creating Image for " + generatedFile, err);
304     } catch (Exception e)
305     {
306       setProgressMessage(MessageManager
307               .formatMessage("info.error_creating_file", "HTML"));
308       e.printStackTrace();
309     }
310
311   }
312
313 }