file format enum wip changes
[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.api.AlignExportSettingI;
24 import jalview.api.AlignmentViewPanel;
25 import jalview.datamodel.AlignmentExportData;
26 import jalview.exceptions.NoFileSelectedException;
27 import jalview.gui.AlignFrame;
28 import jalview.gui.IProgressIndicator;
29 import jalview.gui.OOMWarning;
30 import jalview.json.binding.biojs.BioJSReleasePojo;
31 import jalview.json.binding.biojs.BioJSRepositoryPojo;
32 import jalview.util.MessageManager;
33
34 import java.io.BufferedInputStream;
35 import java.io.BufferedReader;
36 import java.io.File;
37 import java.io.IOException;
38 import java.io.InputStream;
39 import java.io.InputStreamReader;
40 import java.io.PrintWriter;
41 import java.net.URISyntaxException;
42 import java.net.URL;
43 import java.util.Objects;
44 import java.util.TreeMap;
45
46 public class BioJsHTMLOutput
47 {
48   private AlignmentViewPanel ap;
49
50   private long pSessionId;
51
52   private IProgressIndicator pIndicator;
53
54   private boolean headless;
55
56   private static File currentBJSTemplateFile;
57
58   private static TreeMap<String, File> bioJsMSAVersions;
59
60   public static final String DEFAULT_DIR = System.getProperty("user.home")
61           + File.separatorChar + ".biojs_templates" + File.separatorChar;
62
63   public static final String BJS_TEMPLATES_LOCAL_DIRECTORY = jalview.bin.Cache
64           .getDefault("biojs_template_directory", DEFAULT_DIR);
65
66   public static final String BJS_TEMPLATE_GIT_REPO = jalview.bin.Cache
67           .getDefault(
68                   "biojs_template_git_repo",
69                   "https://raw.githubusercontent.com/jalview/exporter-templates/master/biojs/package.json");
70
71   public BioJsHTMLOutput(AlignmentViewPanel ap,
72           IProgressIndicator pIndicator)
73   {
74     if (ap != null)
75     {
76       this.ap = ap;
77       this.pSessionId = System.currentTimeMillis();
78       this.pIndicator = pIndicator;
79       this.headless = (System.getProperty("java.awt.headless") != null && System
80               .getProperty("java.awt.headless").equals("true"));
81     }
82   }
83
84   public void exportJalviewAlignmentAsBioJsHtmlFile()
85   {
86     String outputFile = null;
87     try
88     {
89       outputFile = getOutputFile();
90       AlignExportSettingI exportSettings = new AlignExportSettingI()
91       {
92         @Override
93         public boolean isExportHiddenSequences()
94         {
95           return true;
96         }
97
98         @Override
99         public boolean isExportHiddenColumns()
100         {
101           return true;
102         }
103
104         @Override
105         public boolean isExportAnnotations()
106         {
107           return true;
108         }
109
110         @Override
111         public boolean isExportFeatures()
112         {
113           return true;
114         }
115
116         @Override
117         public boolean isExportGroups()
118         {
119           return true;
120         }
121
122         @Override
123         public boolean isCancelled()
124         {
125           return false;
126         }
127
128       };
129       AlignmentExportData exportData = AlignFrame
130               .getAlignmentForExport(FileFormat.Json,
131                       ap.getAlignViewport(), exportSettings);
132       String bioJSON = new FormatAdapter(ap, exportData.getSettings())
133               .formatSequences(FileFormat.Json, exportData
134                       .getAlignment(), exportData.getOmitHidden(),
135                       exportData.getStartEndPostions(), ap
136                               .getAlignViewport().getColumnSelection());
137
138       String bioJSTemplateString = getBioJsTemplateAsString();
139       String generatedBioJsWithJalviewAlignmentAsJson = bioJSTemplateString
140               .replaceAll("#sequenceData#", bioJSON).toString();
141
142       PrintWriter out = new java.io.PrintWriter(new java.io.FileWriter(
143               outputFile));
144       out.print(generatedBioJsWithJalviewAlignmentAsJson);
145       out.flush();
146       out.close();
147       jalview.util.BrowserLauncher.openURL("file:///" + outputFile);
148       if (pIndicator != null && !headless)
149       {
150         pIndicator.setProgressBar(MessageManager.formatMessage(
151                 "status.export_complete", "BioJS"), pSessionId);
152       }
153     } catch (NoFileSelectedException ex)
154     {
155       // do noting if no file was selected
156     } catch (OutOfMemoryError err)
157     {
158       System.out.println("########################\n" + "OUT OF MEMORY "
159               + outputFile + "\n" + "########################");
160       new OOMWarning("Creating Image for " + outputFile, err);
161     } catch (Exception e)
162     {
163       pIndicator.setProgressBar(MessageManager.formatMessage(
164               "info.error_creating_file", "HTML"), pSessionId);
165       e.printStackTrace();
166     }
167   }
168
169   public String getOutputFile() throws NoFileSelectedException
170   {
171     String selectedFile = null;
172     if (pIndicator != null && !headless)
173     {
174       pIndicator.setProgressBar(MessageManager.formatMessage(
175               "status.waiting_for_user_to_select_output_file", "HTML"),
176               pSessionId);
177     }
178
179     JalviewFileChooser jvFileChooser = new JalviewFileChooser(
180             jalview.bin.Cache.getProperty("LAST_DIRECTORY"),
181             new String[] { "html" }, new String[] { "HTML files" },
182             "HTML files");
183     jvFileChooser.setFileView(new JalviewFileView());
184
185     jvFileChooser.setDialogTitle(MessageManager
186             .getString("label.save_as_biojs_html"));
187     jvFileChooser.setToolTipText(MessageManager.getString("action.save"));
188
189     int fileChooserOpt = jvFileChooser.showSaveDialog(null);
190     if (fileChooserOpt == JalviewFileChooser.APPROVE_OPTION)
191     {
192       jalview.bin.Cache.setProperty("LAST_DIRECTORY", jvFileChooser
193               .getSelectedFile().getParent());
194       selectedFile = jvFileChooser.getSelectedFile().getPath();
195     }
196     else
197     {
198       pIndicator.setProgressBar(MessageManager.formatMessage(
199               "status.cancelled_image_export_operation", "BioJS"),
200               pSessionId);
201       throw new NoFileSelectedException("No file was selected.");
202     }
203     return selectedFile;
204   }
205
206   public static String getBioJsTemplateAsString() throws IOException
207   {
208     InputStreamReader isReader = null;
209     BufferedReader buffReader = null;
210     StringBuilder sb = new StringBuilder();
211     Objects.requireNonNull(getCurrentBJSTemplateFile(),
212             "BioJsTemplate File not initialized!");
213     @SuppressWarnings("deprecation")
214     URL url = getCurrentBJSTemplateFile().toURL();
215     if (url != null)
216     {
217       try
218       {
219         isReader = new InputStreamReader(url.openStream());
220         buffReader = new BufferedReader(isReader);
221         String line;
222         String lineSeparator = System.getProperty("line.separator");
223         while ((line = buffReader.readLine()) != null)
224         {
225           sb.append(line).append(lineSeparator);
226         }
227
228       } catch (Exception ex)
229       {
230         ex.printStackTrace();
231       } finally
232       {
233         if (isReader != null)
234         {
235           isReader.close();
236         }
237
238         if (buffReader != null)
239         {
240           buffReader.close();
241         }
242       }
243     }
244     return sb.toString();
245   }
246
247   public static void refreshBioJSVersionsInfo(String dirName)
248           throws URISyntaxException
249   {
250     File directory = new File(BJS_TEMPLATES_LOCAL_DIRECTORY);
251     Objects.requireNonNull(dirName, "dirName MUST not be null!");
252     Objects.requireNonNull(directory, "directory MUST not be null!");
253     TreeMap<String, File> versionFileMap = new TreeMap<String, File>();
254
255     for (File file : directory.listFiles())
256     {
257       if (file.isFile())
258       {
259         String fileName = file.getName().substring(0,
260                 file.getName().lastIndexOf("."));
261         String fileMeta[] = fileName.split("_");
262         if (fileMeta.length > 2)
263         {
264           setCurrentBJSTemplateFile(file);
265           versionFileMap.put(fileMeta[2], file);
266         }
267         else if (fileMeta.length > 1)
268         {
269           versionFileMap.put(fileMeta[1], file);
270         }
271       }
272     }
273     if (getCurrentBJSTemplateFile() == null && versionFileMap.size() > 0)
274     {
275       setCurrentBJSTemplateFile(versionFileMap.lastEntry().getValue());
276     }
277     setBioJsMSAVersions(versionFileMap);
278   }
279
280   public static void updateBioJS()
281   {
282     Thread updateThread = new Thread()
283     {
284       @Override
285       public void run()
286       {
287         try
288         {
289           String gitRepoPkgJson = getURLContentAsString(BJS_TEMPLATE_GIT_REPO);
290           if (gitRepoPkgJson != null)
291           {
292             BioJSRepositoryPojo release = new BioJSRepositoryPojo(
293                     gitRepoPkgJson);
294             syncUpdates(BJS_TEMPLATES_LOCAL_DIRECTORY, release);
295             refreshBioJSVersionsInfo(BJS_TEMPLATES_LOCAL_DIRECTORY);
296           }
297         } catch (URISyntaxException e)
298         {
299           e.printStackTrace();
300         }
301       }
302     };
303     updateThread.start();
304
305   }
306
307   public static void syncUpdates(String localDir, BioJSRepositoryPojo repo)
308   {
309     for (BioJSReleasePojo bjsRelease : repo.getReleases())
310     {
311       String releaseUrl = bjsRelease.getUrl();
312       String releaseVersion = bjsRelease.getVersion();
313       String releaseFile = "BioJsMSA_" + releaseVersion + ".txt";
314       if (releaseVersion.equals(repo.getLatestReleaseVersion()))
315       {
316         releaseFile = "Latest_BioJsMSA_" + releaseVersion + ".txt";
317       }
318
319       File biojsDirectory = new File(BJS_TEMPLATES_LOCAL_DIRECTORY);
320       if (!biojsDirectory.exists())
321       {
322         if (!biojsDirectory.mkdirs())
323         {
324           System.out.println("Couldn't create local directory : "
325                   + BJS_TEMPLATES_LOCAL_DIRECTORY);
326           return;
327         }
328       }
329
330       File file = new File(BJS_TEMPLATES_LOCAL_DIRECTORY + releaseFile);
331       if (!file.exists())
332       {
333
334         PrintWriter out = null;
335         try
336         {
337           out = new java.io.PrintWriter(new java.io.FileWriter(file));
338           out.print(getURLContentAsString(releaseUrl));
339         } catch (IOException e)
340         {
341           e.printStackTrace();
342         } finally
343         {
344           if (out != null)
345           {
346             out.flush();
347             out.close();
348           }
349         }
350       }
351     }
352
353   }
354
355   public static String getURLContentAsString(String url)
356           throws OutOfMemoryError
357   {
358     StringBuilder responseStrBuilder = null;
359     InputStream is = null;
360     try
361     {
362       URL resourceUrl = new URL(url);
363       is = new BufferedInputStream(resourceUrl.openStream());
364       BufferedReader br = new BufferedReader(new InputStreamReader(is));
365       responseStrBuilder = new StringBuilder();
366       String lineContent;
367
368       while ((lineContent = br.readLine()) != null)
369       {
370         responseStrBuilder.append(lineContent).append("\n");
371       }
372     } catch (OutOfMemoryError er)
373     {
374       er.printStackTrace();
375     } catch (Exception ex)
376     {
377       ex.printStackTrace();
378     } finally
379     {
380       if (is != null)
381       {
382         try
383         {
384           is.close();
385         } catch (IOException e)
386         {
387           e.printStackTrace();
388         }
389       }
390     }
391     return responseStrBuilder == null ? null : responseStrBuilder
392             .toString();
393   }
394
395   public static File getCurrentBJSTemplateFile()
396   {
397     return currentBJSTemplateFile;
398   }
399
400   public static void setCurrentBJSTemplateFile(File currentBJSTemplateFile)
401   {
402     BioJsHTMLOutput.currentBJSTemplateFile = currentBJSTemplateFile;
403   }
404
405   public static TreeMap<String, File> getBioJsMSAVersions()
406   {
407     return bioJsMSAVersions;
408   }
409
410   public static void setBioJsMSAVersions(
411           TreeMap<String, File> bioJsMSAVersions)
412   {
413     BioJsHTMLOutput.bioJsMSAVersions = bioJsMSAVersions;
414   }
415
416 }