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