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