]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.help.core/src/org/simantics/help/core/HelpUtils.java
merged svn revision 33114 and added desktop and help plugins
[simantics/platform.git] / bundles / org.simantics.help.core / src / org / simantics / help / core / HelpUtils.java
1 package org.simantics.help.core;\r
2 \r
3 import java.io.IOException;\r
4 import java.io.StringWriter;\r
5 import java.net.URL;\r
6 import java.net.URLDecoder;\r
7 import java.nio.charset.StandardCharsets;\r
8 import java.nio.file.Files;\r
9 import java.nio.file.Path;\r
10 import java.nio.file.StandardOpenOption;\r
11 import java.util.ArrayList;\r
12 import java.util.Arrays;\r
13 import java.util.Collection;\r
14 import java.util.Collections;\r
15 import java.util.HashMap;\r
16 import java.util.List;\r
17 import java.util.Map;\r
18 import java.util.Map.Entry;\r
19 import java.util.TreeMap;\r
20 \r
21 import org.eclipse.mylyn.wikitext.core.parser.MarkupParser;\r
22 import org.eclipse.mylyn.wikitext.core.parser.builder.HtmlDocumentBuilder;\r
23 import org.eclipse.mylyn.wikitext.mediawiki.core.MediaWikiLanguage;\r
24 import org.eclipse.ui.PlatformUI;\r
25 import org.eclipse.ui.help.IWorkbenchHelpSystem;\r
26 import org.simantics.databoard.Bindings;\r
27 import org.simantics.db.ReadGraph;\r
28 import org.simantics.db.Resource;\r
29 import org.simantics.db.WriteGraph;\r
30 import org.simantics.db.common.request.ObjectsWithType;\r
31 import org.simantics.db.common.utils.NameUtils;\r
32 import org.simantics.db.exception.BindingException;\r
33 import org.simantics.db.exception.DatabaseException;\r
34 import org.simantics.db.exception.ManyObjectsForFunctionalRelationException;\r
35 import org.simantics.db.exception.ServiceException;\r
36 import org.simantics.document.base.ontology.DocumentationResource;\r
37 import org.simantics.help.HelpResources;\r
38 import org.simantics.layer0.Layer0;\r
39 import org.simantics.modeling.ModelingUtils;\r
40 import org.simantics.structural.stubs.StructuralResource2;\r
41 \r
42 import winterwell.markdown.pagemodel.MarkdownPage;\r
43 \r
44 public class HelpUtils {\r
45 \r
46     public static Resource createHelpLibrary(WriteGraph graph, Resource parent) throws DatabaseException {\r
47         Layer0 L0 = Layer0.getInstance(graph);\r
48         HelpResources HELP = HelpResources.getInstance(graph);\r
49         Resource library = graph.newResource();\r
50         graph.claim(library, L0.InstanceOf, null, HELP.HelpLibrary);\r
51         graph.addLiteral(library, L0.HasName, L0.NameOf, "Help Library", Bindings.STRING);\r
52         graph.claim(parent, L0.ConsistsOf, L0.PartOf, library);\r
53         return library;\r
54     }\r
55     \r
56     public static Resource createHelpTutorial(WriteGraph graph, Resource parent, String name) throws DatabaseException {\r
57         Layer0 L0 = Layer0.getInstance(graph);\r
58         HelpResources HELP = HelpResources.getInstance(graph);\r
59         Resource tutorialFile = graph.newResource();\r
60         graph.claim(tutorialFile, L0.InstanceOf, null, HELP.TutorialFile);\r
61         graph.addLiteral(tutorialFile, L0.HasName, L0.NameOf, name, Bindings.STRING);\r
62         graph.claim(parent, L0.ConsistsOf, L0.PartOf, tutorialFile);\r
63         return tutorialFile;\r
64     }\r
65 \r
66     public static List<Path> collectHelps(ReadGraph graph, Resource indexRoot) throws DatabaseException {\r
67         Layer0 L0 = Layer0.getInstance(graph);\r
68         HelpResources HELP = HelpResources.getInstance(graph);\r
69         List<Resource> tutorialFiles = ModelingUtils.searchByType(graph, indexRoot, HELP.TutorialFile);\r
70         if (tutorialFiles.isEmpty())\r
71             return Collections.emptyList();\r
72         List<Path> result = new ArrayList<>(tutorialFiles.size());\r
73         for (Resource tutorialFile : tutorialFiles) {\r
74             StringBuilder sb = new StringBuilder();\r
75             \r
76             htmlHead(sb, graph.getRelatedValue2(tutorialFile, L0.HasName, Bindings.STRING));\r
77             sb.append(HelpUtils.markdownToHtml(graph, tutorialFile));\r
78             htmlHeadClose(sb);\r
79             \r
80             String indexRootURI = graph.getURI(indexRoot);\r
81             String indexRootName = graph.getRelatedValue2(indexRoot, L0.HasName, Bindings.STRING);\r
82             String tutorialFileURI = graph.getURI(tutorialFile);\r
83             String suffix = tutorialFileURI.substring(indexRootURI.length());\r
84             try {\r
85                 if (suffix.startsWith("/"))\r
86                     suffix = suffix.substring(1);\r
87                 suffix = URLDecoder.decode(suffix, StandardCharsets.UTF_8.name());\r
88                 Path outputPath = Activator.getHtmlDirectory().resolve(indexRootName).resolve(suffix + ".html");\r
89                 createDirsRec(outputPath.getParent());\r
90                 if (!Files.exists(outputPath))\r
91                     Files.createFile(outputPath);\r
92                 Files.write(outputPath, sb.toString().getBytes(StandardCharsets.UTF_8), StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);\r
93                 result.add(outputPath);\r
94             } catch (IOException e) {\r
95                 e.printStackTrace();\r
96             }\r
97         }\r
98         return result;\r
99     }\r
100 \r
101     private static void createDirsRec(Path path) throws IOException {\r
102         Path parent = path.getParent();\r
103         if (!Files.exists(parent)) {\r
104             createDirsRec(parent);\r
105         }\r
106         if (!Files.exists(path))\r
107             Files.createDirectory(path);\r
108     }\r
109 \r
110     public static Map<String, List<Path>> collectHelpsFromSharedLibraries(ReadGraph graph) throws DatabaseException {\r
111         Layer0 L0 = Layer0.getInstance(graph);\r
112         Collection<Resource> sharedLibraries = graph.syncRequest(new ObjectsWithType(graph.getRootLibrary(), L0.ConsistsOf, L0.SharedOntology));\r
113         if (sharedLibraries.isEmpty())\r
114             return Collections.emptyMap();\r
115         Map<String, List<Path>> result = new HashMap<>(sharedLibraries.size());\r
116         for (Resource library : sharedLibraries) {\r
117             String libraryName = graph.getRelatedValue2(library, L0.HasName, Bindings.STRING);\r
118             List<Path> paths = collectHelps(graph, library);\r
119             result.put(libraryName, paths);\r
120         }\r
121         return result;\r
122     }\r
123     \r
124     public static Map<String, Path> collectWidgetReferencesFromSharedLibraries(ReadGraph graph) throws DatabaseException {\r
125         Layer0 L0 = Layer0.getInstance(graph);\r
126         Collection<Resource> sharedLibraries = graph.syncRequest(new ObjectsWithType(graph.getRootLibrary(), L0.ConsistsOf, L0.SharedOntology));\r
127         if (sharedLibraries.isEmpty())\r
128             return Collections.emptyMap();\r
129         Map<String, Path> result = new HashMap<>(sharedLibraries.size());\r
130         for (Resource library : sharedLibraries) {\r
131             String html = createWidgetReference(graph, library, "Widget Reference");\r
132             String indexRootName = graph.getRelatedValue2(library, L0.HasName, Bindings.STRING);\r
133             try {\r
134                 Path outputPath = Activator.getHtmlDirectory().resolve(indexRootName).resolve("widgetReference.html");\r
135                 createDirsRec(outputPath.getParent());\r
136                 if (!Files.exists(outputPath))\r
137                     Files.createFile(outputPath);\r
138                 Files.write(outputPath, html.getBytes(StandardCharsets.UTF_8), StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);\r
139                 result.put(indexRootName, outputPath);\r
140             } catch (IOException e) {\r
141                 e.printStackTrace();\r
142             }\r
143         }\r
144         return result;\r
145     }\r
146     \r
147     private static void htmlHead(StringBuilder sb, String title) {\r
148         sb.append("<!DOCTYPE html PUBLIC \"-//IETF//DTD HTML//EN\">\n");\r
149         sb.append("<html><head><title>" + title + " Tutorial</title>\n");\r
150         sb.append("<link rel=\"Stylesheet\" type=\"text/css\" media=\"all\" href=\"../style.css\">\n");\r
151         sb.append("</head>\n");\r
152         sb.append("<body style=\"background-color: white;\">\n");\r
153         sb.append("<h1 align=\"center\">" + title + "</h1>\n");\r
154         sb.append("<hr>\n");\r
155     }\r
156     \r
157     private static void htmlHeadClose(StringBuilder sb) {\r
158         sb.append("</body></html>\n");\r
159     }\r
160 \r
161     public static String createWidgetReference(ReadGraph graph, Resource indexRoot, String title) throws DatabaseException {\r
162 \r
163         String ontologyDesc = NameUtils.getSafeLabel(graph, indexRoot);\r
164         \r
165         StringBuilder sb = new StringBuilder();\r
166         \r
167         sb.append("<!DOCTYPE html PUBLIC \"-//IETF//DTD HTML//EN\">\n");\r
168         sb.append("<html><head><title>" + ontologyDesc+ " Widget Reference</title>\n");\r
169         sb.append("<link rel=\"Stylesheet\" type=\"text/css\" media=\"all\" href=\"../style.css\">\n");\r
170         sb.append("</head>\n");\r
171         sb.append("<body style=\"background-color: white;\">\n");\r
172         sb.append("<h1 align=\"center\">" + ontologyDesc+ "</h1>\n");\r
173         sb.append("<h2 align=\"center\">Widget Reference</h2>\n");\r
174         sb.append("<hr>\n");\r
175         sb.append("<h1 align=\"center\">" + title + "</h1>\n");\r
176         \r
177         Layer0 L0 = Layer0.getInstance(graph);\r
178         StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
179         DocumentationResource DOC = DocumentationResource.getInstance(graph);\r
180         \r
181         List<Resource> types = ModelingUtils.searchByType(graph, indexRoot, DOC.DocumentComponentType);\r
182         for(Resource type : types) {\r
183 \r
184             \r
185             String label = NameUtils.getSafeLabel(graph, type);\r
186 \r
187             sb.append("<h2><a name=\"" + label + "\"></a>" + label + "</h2>\n");\r
188             sb.append("<h3>Description</h3>\n");\r
189 \r
190             String desc = graph.getPossibleRelatedValue(type, L0.HasDescription);\r
191             if(desc == null) desc = "";\r
192             \r
193             sb.append("<p>" + WikiParser.parseToHtml(desc, false) + "</p>\n");\r
194             \r
195             sb.append("<h3>Base Types</h3>\n");\r
196             \r
197             Map<String,String> names = new HashMap<String,String>();\r
198 \r
199             for(Resource r : graph.getSupertypes(type)) {\r
200 \r
201                 if(graph.isInheritedFrom(r, STR.Component)) {\r
202                     \r
203                     String label2 = NameUtils.getSafeLabel(graph, r);\r
204                     String name = graph.getRelatedValue(r, L0.HasName);\r
205                     //if("Component".equals(name)) continue;\r
206                     if("Element".equals(name)) continue;\r
207                     if("DefinedElement".equals(name)) continue;\r
208                     if("PrimitiveComponent".equals(name)) continue;\r
209                     if("DocumentComponent".equals(name)) continue;\r
210                     \r
211                     names.put(name, label2);\r
212 \r
213                 }\r
214                 \r
215             }\r
216 \r
217             for(Map.Entry<String, String> entry : names.entrySet()) {\r
218                 String stuff = "predefined/baseWidgets.html#";\r
219                 sb.append("<a href=\"" + stuff + entry.getKey() + "\">" + entry.getValue() + "</a>\n");\r
220                 //sb.append("<a href=\"baseWidgets.html#" + entry.getKey() + "\">" + entry.getValue() + "</a>\n");\r
221             }\r
222 \r
223             sb.append("<h3>Properties</h3>\n");\r
224             sb.append("<table style=\"width: 100%;\" border=\"1\" cellpadding=\"0\" cellspacing=\"0\">\n");\r
225             sb.append("<tbody>\n");\r
226             sb.append("  <tr style=\"background-color: silver;\">\n");\r
227             sb.append("  <td valign=\"top\"><br><strong>Property Name</strong></td>\n");\r
228             sb.append("  <td valign=\"top\"><br><strong>Type</strong></td>\n");\r
229             sb.append("  <td valign=\"top\"><br><strong>Default Value</strong></td>\n");\r
230             sb.append("  <td valign=\"top\"><br><strong>Description</strong></td>\n");\r
231             sb.append("  </tr>\n");\r
232             \r
233             Map<String, Resource> propertyMap = new TreeMap<String, Resource>();\r
234             \r
235             for(Resource ass : graph.getObjects(type, L0.Asserts)) {\r
236                 \r
237                 Resource object = graph.getSingleObject(ass, L0.HasObject);\r
238                 \r
239                 if(graph.isInstanceOf(object, L0.SCLValue)) continue;\r
240                 if(graph.isInstanceOf(object, L0.Function)) continue;\r
241                 if(graph.isInstanceOf(object, L0.ExternalValue)) continue;\r
242 \r
243                 Resource pred = graph.getSingleObject(ass, L0.HasPredicate);\r
244                 String pName = NameUtils.getSafeLabel(graph, pred);\r
245                 propertyMap.put(pName, ass);\r
246             }\r
247             \r
248             for (Entry<String, Resource> entry : propertyMap.entrySet()) {\r
249                 Resource ass = entry.getValue();\r
250                 Resource object = graph.getSingleObject(ass, L0.HasObject);\r
251                 \r
252                 Resource pred = graph.getSingleObject(ass, L0.HasPredicate);\r
253                 String pName = NameUtils.getSafeLabel(graph, pred);\r
254                 String valueType = graph.getPossibleRelatedValue(pred, L0.RequiresValueType);\r
255 \r
256                 Object jObject = graph.getValue(object);\r
257                 String objectName = jObject.toString();\r
258                 if(jObject.getClass().isArray()) {\r
259                     Class<?> c1 = jObject.getClass().getComponentType();\r
260                     boolean p1 = c1.isPrimitive();\r
261                     if (!p1)\r
262                         objectName = Arrays.toString((Object[])jObject);\r
263                     if (boolean.class.equals(c1))\r
264                         objectName = Arrays.toString((boolean[])jObject);\r
265                     else if (byte.class.equals(c1))\r
266                         objectName = Arrays.toString((byte[])jObject);\r
267                     else if (int.class.equals(c1))\r
268                         objectName = Arrays.toString((int[])jObject);\r
269                     else if (long.class.equals(c1))\r
270                         objectName = Arrays.toString((long[])jObject);\r
271                     else if (float.class.equals(c1))\r
272                         objectName = Arrays.toString((float[])jObject);\r
273                     else if (double.class.equals(c1))\r
274                         objectName = Arrays.toString((double[])jObject);\r
275                 }\r
276 \r
277                 String pDesc = graph.getPossibleRelatedValue(pred, L0.HasDescription);\r
278                 if(pDesc == null) pDesc = "";\r
279                 \r
280                 sb.append("  <tr>\n");\r
281                 sb.append("  <td valign=\"top\">" + pName + "</td>\n");\r
282                 sb.append("  <td valign=\"top\">" + valueType + "</td>\n");\r
283                 sb.append("  <td valign=\"top\">" + objectName + "</td>\n");\r
284                 sb.append("  <td valign=\"top\">" + WikiParser.parseToHtml(pDesc, false) + "</td>\n");\r
285                 sb.append("  </tr>\n");\r
286             }\r
287 \r
288             sb.append("  </tbody></table><br>\n");\r
289         }\r
290 \r
291         sb.append("</body></html>\n");\r
292         return sb.toString();\r
293     }\r
294     \r
295     public static void clearHelpTocCache() {\r
296         SimanticsTocProvider.clearTocCache();\r
297     }\r
298     \r
299     public static void saveHelpFileContents(WriteGraph graph, Resource helpFile, String currentText) throws BindingException, ManyObjectsForFunctionalRelationException, ServiceException {\r
300         HelpResources HELP = HelpResources.getInstance(graph);\r
301         graph.claimLiteral(helpFile, HELP.HelpFile_contents, currentText, Bindings.STRING);\r
302     }\r
303     \r
304     public static String readHelpFileContents(ReadGraph graph, Resource helpFile) throws DatabaseException {\r
305         HelpResources HELP = HelpResources.getInstance(graph);\r
306         String content = graph.getPossibleRelatedValue2(helpFile, HELP.HelpFile_contents, Bindings.STRING);\r
307         return content != null ? content : "";\r
308     }\r
309     \r
310     public static String markdownToHtml(ReadGraph graph, Resource tutorialFile) throws DatabaseException {\r
311         HelpResources HELP = HelpResources.getInstance(graph);\r
312         String markdown = graph.getRelatedValue2(tutorialFile, HELP.HelpFile_contents, Bindings.STRING);\r
313         MarkdownPage page = new MarkdownPage(markdown);\r
314         return page.html();\r
315     }\r
316     \r
317     public static URL getHelpBrowserUrl() {\r
318         IWorkbenchHelpSystem helpSystem = PlatformUI.getWorkbench().getHelpSystem();\r
319         URL url = helpSystem.resolve("", false);\r
320         return url;\r
321     }\r
322 \r
323     private static class WikiParser {\r
324         \r
325         private static MarkupParser markupParser = new MarkupParser(new MediaWikiLanguage());\r
326         \r
327         private WikiParser() {}\r
328         \r
329         public static String parseToHtml(String wiki, boolean asDocument) {\r
330             StringWriter writer = new StringWriter();\r
331             HtmlDocumentBuilder builder = new HtmlDocumentBuilder(writer);\r
332             markupParser.setBuilder(builder);\r
333             markupParser.parse(wiki, asDocument);\r
334             return writer.toString();\r
335         }\r
336     }\r
337 }\r