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