]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.document.ui/src/org/simantics/document/ui/graphfile/FileDocumentUtil.java
Use Consumer interface instead of deprecated Callback interface
[simantics/platform.git] / bundles / org.simantics.document.ui / src / org / simantics / document / ui / graphfile / FileDocumentUtil.java
1 package org.simantics.document.ui.graphfile;
2
3 import java.io.BufferedReader;
4 import java.io.File;
5 import java.io.FileInputStream;
6 import java.io.IOException;
7 import java.io.InputStreamReader;
8 import java.io.PrintStream;
9 import java.util.Collection;
10 import java.util.HashSet;
11 import java.util.Set;
12
13 import org.eclipse.core.runtime.IProgressMonitor;
14 import org.simantics.Simantics;
15 import org.simantics.db.ReadGraph;
16 import org.simantics.db.Resource;
17 import org.simantics.db.WriteGraph;
18 import org.simantics.db.common.request.ReadRequest;
19 import org.simantics.db.common.request.WriteRequest;
20 import org.simantics.db.common.request.WriteResultRequest;
21 import org.simantics.db.exception.DatabaseException;
22 import org.simantics.document.DocumentResource;
23 import org.simantics.graphfile.ontology.GraphFileResource;
24 import org.simantics.graphfile.util.GraphFileUtil;
25 import org.simantics.layer0.Layer0;
26 import org.simantics.utils.ui.ExceptionUtils;
27
28 /**
29  * 
30  * @author Marko Luukkainen <marko.luukkainen@vtt.fi>
31  *
32  */
33 public class FileDocumentUtil {
34         
35         /**
36          * Imports file, sets its L0.hasName, and and adds it to a library
37          * 
38          * Note: if library relation is L0.ConsistsOf, L0.HasName is set to next available unique name.
39          * 
40          * @param fileName
41          * @param lib
42          * @param rel
43          * @throws DatabaseException 
44          */
45         public static Resource importFile(final String fileName, final Resource lib, final Resource rel) throws DatabaseException {
46                 return Simantics.getSession().syncRequest(new WriteResultRequest<Resource>() {
47                         @Override
48                         public Resource perform(WriteGraph graph) throws DatabaseException {
49                                 return importFile(graph, fileName,lib,rel);
50                         }
51                 });
52                         
53                 
54         }
55         
56         public static void importFileAsync(final String fileName, final Resource lib, final Resource rel)  {
57                 Simantics.getSession().asyncRequest(new WriteRequest() {
58                         
59                         @Override
60                         public void perform(WriteGraph graph) throws DatabaseException {
61                                  importFile(graph, fileName,lib,rel);
62                                 
63                         }
64                 }, e -> {
65                         if (e != null)
66                                 ExceptionUtils.logAndShowError("Cannot import file " + fileName, e);
67                 });
68                         
69                 
70         }
71         
72         /**
73          * Imports file, sets its L0.HasName, and and adds it to a library
74          * 
75          * Note: if library relation is L0.ConsistsOf, L0.HasName is set to next available unique name.
76          * 
77          * @param graph
78          * @param fileName
79          * @param lib
80          * @param rel
81          * @throws DatabaseException
82          */
83         public static Resource importFile(WriteGraph graph, String fileName, Resource lib, Resource rel) throws DatabaseException{
84                 Layer0 l0 = Layer0.getInstance(graph);
85                 Resource fileResource = importFile(graph, fileName);
86                 graph.claim(lib, rel, fileResource);
87                 File file = new File(fileName);
88                 String name = file.getName();
89                 graph.claimLiteral(fileResource, l0.HasName, name);
90                 setUniqueName(graph, fileResource, lib, rel);
91                 return fileResource;
92         }
93         
94         public static Resource importFileWithName(WriteGraph graph, String fileName) throws DatabaseException{
95                 Layer0 l0 = Layer0.getInstance(graph);
96                 Resource fileResource = importFile(graph, fileName);
97                 File file = new File(fileName);
98                 String name = file.getName();
99                 graph.claimLiteral(fileResource, l0.HasName, name);
100                 return fileResource;
101         }
102         
103         /**
104          * Imports folder of documents recursively (including all sub folders). 
105          * @param graph
106          * @param folderName  Name of imported folder
107          * @param lib         Library, where imported folder is attached.
108          * @param folderType  Type of folders
109          * @param relation    Relation used to create file/folder hierarchy
110          * @return            the imported folder
111          * @throws DatabaseException
112          */
113         public static Resource importFolderWithName(WriteGraph graph, String folderName, Resource lib, Resource folderType, Resource relation, IProgressMonitor monitor) throws Exception{
114                 Resource folderRes = importFolderWithName(graph, folderName, folderType, relation,monitor);
115                 graph.claim(lib, relation, folderRes);
116                 FileDocumentUtil.createUniqueName(graph, folderRes);
117                 return folderRes;
118         }
119         
120         /**
121          * Imports folder of documents recursively (including all sub folders). 
122          * @param graph
123          * @param folderName  Name of imported folder
124          * @param folderType  Type of folders
125          * @param relation    Relation used to create file/folder hierarchy
126          * @param monitor     ProgessMonitor or null
127          * @return            the imported folder
128          * @throws DatabaseException
129          */
130         public static Resource importFolderWithName(WriteGraph graph, String folderName, Resource folderType, Resource relation, IProgressMonitor monitor) throws Exception{
131                 Layer0 l0 = Layer0.getInstance(graph);
132                 File folder = new File(folderName);
133                 Resource rootFolderRes = graph.newResource();
134                 graph.claim(rootFolderRes, l0.InstanceOf, folderType);
135                 graph.claimLiteral(rootFolderRes, l0.HasName, folder.getName());
136                 importFolder(graph, folder, rootFolderRes, relation, monitor);
137                 return rootFolderRes;
138         }
139         
140         /**
141          * Imports folder of documents recursively (including all sub folders).
142          * @param graph
143          * @param folder            Imported folder
144          * @param folderResource    Resource folder matching file system folder
145          * @param relation          Relation used to create file/folder hierarchy
146          * @throws DatabaseException
147          */
148         public static void importFolder(WriteGraph graph, File folder, Resource folderResource, Resource relation, IProgressMonitor monitor) throws Exception{
149                 if (monitor != null) {
150                         int count = _countFiles(folder);
151                         monitor.beginTask("Import files", count);
152                 }
153                 _importFolder(graph, folder, folderResource, relation, monitor);
154                 if (monitor != null)
155                         monitor.done();
156         }
157         
158         private static void _importFolder(WriteGraph graph, File folder, Resource folderResource, Resource relation, IProgressMonitor monitor) throws Exception{
159                 Layer0 l0 = Layer0.getInstance(graph);
160                 File files[] = folder.listFiles();
161                 for (File f : files) {
162                         if (f.isDirectory()) {
163                                 Resource newFolderRes = graph.newResource();
164                                 graph.claim(newFolderRes, l0.InstanceOf, graph.getSingleType(folderResource));
165                                 graph.claim(folderResource, relation, newFolderRes);
166                                 graph.claimLiteral(newFolderRes, l0.HasName, f.getName());
167                                 _importFolder(graph, f, newFolderRes, relation,monitor);
168                         } else {
169                                 Resource fileRes = null;
170                                 if (isUrl(f)) {
171                                 } else {
172                                     fileRes = importURL(graph, f);
173                                         fileRes = importFileWithName(graph, f.getAbsolutePath());
174                                 }
175                                 graph.claim(folderResource, relation, fileRes);
176                                 if (monitor != null)
177                                         monitor.worked(1);
178                         }
179                 }
180         }
181         
182         private static int _countFiles(File folder) {
183                 
184                 int count = 0;
185                 File files[] = folder.listFiles();
186                 for (File f : files) {
187                         if (f.isDirectory()) {
188                                 count += _countFiles(f);
189                         } else {
190                                 count++;
191                         }
192                 }
193                 return count;
194         }
195         
196         
197         public static void createUniqueName(WriteGraph graph, Resource document) throws DatabaseException {
198                 Layer0 l0 = Layer0.getInstance(graph);
199                 Resource lib = graph.getPossibleObject(document, l0.PartOf);
200                 if (lib == null)
201                         return;
202                 setUniqueName(graph, document, lib, l0.ConsistsOf);
203         }
204         
205         public static void setUniqueName(WriteGraph graph, Resource res, Resource lib, Resource rel) throws DatabaseException{
206                 Layer0 l0 = Layer0.getInstance(graph);
207                 Set<String> names = new HashSet<String>();
208                 for (Resource r : graph.getObjects(lib, rel)) {
209                         if (r.equals(res))
210                                 continue;
211                         names.add((String)graph.getRelatedValue(r, l0.HasName));
212                 }
213                 String name = graph.getRelatedValue(res, l0.HasName);
214                 if (!names.contains(name))
215                         return;
216                 int i = 1;
217                 while (true) {
218                         String proposal = name +" (" + i +")";
219                         if (!names.contains(proposal)) {
220                                 graph.claimLiteral(res, l0.HasName, proposal);
221                                 return;
222                         }
223                         i++;
224                 }
225                 
226         }
227         
228         /**
229          * Imports a file
230          * 
231          * @param graph
232          * @param fileName
233          * @return
234          * @throws DatabaseException
235          */
236         public static Resource importFile(WriteGraph graph, String fileName) throws DatabaseException{
237                 Layer0 l0 = Layer0.getInstance(graph);
238                 DocumentResource doc = DocumentResource.getInstance(graph);
239                 
240                 Resource fileResource = graph.newResource();
241                 graph.claim(fileResource, l0.InstanceOf, doc.FileDocument);
242                 try {
243                         GraphFileUtil.toGraph(graph,fileName, fileResource);
244                         
245                 } catch (IOException e) {
246                         throw new DatabaseException(e);
247                 }
248                 return fileResource;
249                 
250         }
251         
252         /**
253          * Exports graph folder recursively to file system. 
254          * @param graph
255          * @param folderResource
256          * @param folder
257          * @param relation
258          * @throws DatabaseException
259          */
260         public static void exportDocumentFolder(final Resource folderResource, final File folder, final Resource relation, boolean useResourceNames, final IProgressMonitor monitor) throws Exception{
261                 Simantics.getSession().syncRequest(new ReadRequest() {
262                         
263                         @Override
264                         public void run(ReadGraph graph) throws DatabaseException {
265                                 try {
266                                         exportDocumentFolder(graph, folderResource, folder, relation, useResourceNames, monitor);
267                                 } catch (Exception e) {
268                                         throw new DatabaseException(e);
269                                 }
270                                 
271                         }
272                 });
273         }
274         
275         
276         /**
277          * Exports graph folder recursively to file system. 
278          * @param graph
279          * @param folderResource
280          * @param folder
281          * @param relation
282          * @throws DatabaseException
283          */
284         public static void exportDocumentFolder(ReadGraph graph, Resource folderResource, File folder, Resource relation, boolean useResourceNames, IProgressMonitor monitor) throws Exception{
285                 Layer0 l0 = Layer0.getInstance(graph);
286                 DocumentResource doc = DocumentResource.getInstance(graph);
287                 GraphFileResource gf = GraphFileResource.getInstance(graph);
288                 Set<String> names = new HashSet<String>();
289                 Collection<Resource> folderType = graph.getPrincipalTypes(folderResource);
290                 for (Resource r : graph.getObjects(folderResource, relation)) {
291                         if (graph.isInstanceOf(r, doc.Document)) {
292                                 String name = null;
293                                 boolean canExport = false;
294                                 if (graph.isInstanceOf(r, doc.FileDocument)) {
295                                         name = graph.getRelatedValue(r, useResourceNames ? gf.HasResourceName : l0.HasName);
296                                         canExport = true;
297                                 } else if (graph.isInstanceOf(r, doc.UrlDocument)) {
298                                         name = graph.getRelatedValue(r, l0.HasName) +".url";
299                                         canExport = true;
300                                 }
301                                 if (canExport) {
302                                         name = resolveName(folder, name, names, true);
303                                         File file = new File(folder.getAbsolutePath()+"/"+name);
304                                         if (graph.isInstanceOf(r, doc.FileDocument)) {
305                                                 GraphFileUtil.writeDataToFile(graph,r, file);
306                                         } else if (graph.isInstanceOf(r, doc.UrlDocument)) {
307                                                 String url = graph.getRelatedValue(r, doc.HasUrl);
308                                                 String n = graph.getRelatedValue(r, l0.HasName);
309                                                 exportUrl(file, n, url);
310                                         }
311                                         if (monitor != null)
312                                                 monitor.worked(1);
313                                 }
314                                 
315                         } else {
316                                 Collection<Resource> type = graph.getPrincipalTypes(r);
317                                 if (type.size() == folderType.size() && folderType.containsAll(type)) {
318                                         String name = graph.getRelatedValue(r, l0.HasName);
319                                         name = resolveName(folder, name, names, false);
320                                         File subFolder = new File(folder.getAbsolutePath()+"/"+name);
321                                         if (!subFolder.exists()) {
322                                                 if (!subFolder.mkdir()) {
323                                                         // TODO : error.
324                                                         continue;
325                                                 }
326                                         }
327                                         exportDocumentFolder(graph, r, subFolder, relation, useResourceNames, monitor);
328                                 }
329                         }
330                 }
331         }
332         
333         /**
334          * Print URL to a file (Windows specific format?)
335          * @param toFile
336          * @param url
337          * @throws DatabaseException
338          */
339         private static void exportUrl(File toFile, String name, String url) throws Exception{
340                 PrintStream os = new PrintStream(toFile,"UTF-8");
341                 os.println("[InternetShortcut]");
342                 os.println("URL="+url);
343                 os.println("name="+name);
344                 os.flush();
345                 os.close();
346         }
347         
348         public static Resource importURL(WriteGraph graph, File file) throws Exception{
349                 String s = null;
350                 String url = null;
351                 String name = null;
352                 BufferedReader is = null;
353                 try {
354                 is = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
355                 while ((s = is.readLine()) != null) {
356                         if (s.startsWith("URL=")) {
357                                 url = s.substring(4);
358                         } else if (s.startsWith("name=")) {
359                                 name = s.substring(5);
360                         }
361                 }
362                 } finally {
363                     if (is != null)
364                         is.close();
365                 }
366                 
367                 if (url == null)
368                         return null;
369                 
370                 Layer0 l0 = Layer0.getInstance(graph);
371                 DocumentResource doc = DocumentResource.getInstance(graph);
372                 
373                 Resource fileResource = graph.newResource();
374                 graph.claim(fileResource, l0.InstanceOf, doc.UrlDocument);
375                 if (name == null) {
376                         name = file.getName();
377                         name = unescape(name);
378                         name = name.substring(0,name.length()-4);
379                 }
380                 graph.claimLiteral(fileResource, l0.HasName, name);
381                 graph.claimLiteral(fileResource, doc.HasUrl, url);
382                 return fileResource;
383         }
384         
385         private static boolean isUrl(File file) throws Exception{
386                 return (file.getAbsolutePath().endsWith(".url"));
387         }
388         
389         private static final char ESCAPE = '%';
390         
391         private static String escape(String s) {
392                 
393                 int len = s.length();
394                 StringBuilder sb = new StringBuilder(len);
395                 for (int i = 0; i < len; i++) {
396                     char ch = s.charAt(i);
397                     if (ch < ' ' || ch >= 0x7F || ch == '/'  || ch == '\\' || ch == ':' || ch == ESCAPE) {
398                         sb.append(ESCAPE);
399                         if (ch < 0x10) {
400                             sb.append('0');
401                         }
402                         sb.append(Integer.toHexString(ch));
403                     } else {
404                         sb.append(ch);
405                     }
406                 }
407                 return sb.toString();
408         }
409         
410         private static String unescape(String s) {
411                 int len = s.length();
412                 StringBuilder sb = new StringBuilder(len);
413                 for (int i = 0; i < len; i++) {
414                     char ch = s.charAt(i);
415                     if (ch == ESCAPE) {
416                         String num = "0x";
417                         num += s.charAt(++i);
418                         num += s.charAt(++i);
419                         ch = (char)Integer.decode(num).intValue();
420                     }
421                     sb.append(ch);
422                 }
423                 return sb.toString();
424                 
425         }
426         
427         private static String resolveName(File parentFolder, String proposal, Set<String> used, boolean file) {
428                 String current = escape(proposal);
429                 int i = 0;
430                 if (file) {
431                         while (true) {
432                                 i++;
433                                 if (used.contains(current)) {
434                                         current = createFileName(proposal, i);
435                                 } else {
436                                         File subFile = new File(parentFolder.getAbsolutePath()+"/"+current);
437                                         if (!subFile.exists())
438                                                 break;
439                                         if (subFile.exists() && subFile.isFile() && subFile.canWrite()) {
440                                                 break;
441                                         }
442                                 }
443                         }
444                 } else {
445                         while (true) {
446                                 i++;
447                                 if (used.contains(current)) {
448                                         current = proposal+i;
449                                 } else {
450                                         File subFolder = new File(parentFolder.getAbsolutePath()+"/"+current);
451                                         if (!subFolder.exists())
452                                                 break;
453                                         if (subFolder.exists() && subFolder.isDirectory()) {
454                                                 break;
455                                         }
456                                 }
457                         }
458                 }
459                 used.add(current);
460                 return current;
461         }
462         
463         private static String createFileName(String original, int i) {
464                 int extIndex = original.lastIndexOf(".");
465                 if (extIndex == -1)
466                         return original+i;
467                 return original.substring(0,extIndex) + i + original.substring(extIndex);
468         }
469
470 }