1 package org.simantics.document;
3 import java.io.BufferedReader;
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;
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.graphfile.ontology.GraphFileResource;
23 import org.simantics.graphfile.util.GraphFileUtil;
24 import org.simantics.layer0.Layer0;
25 import org.simantics.utils.ui.ExceptionUtils;
29 * @author Marko Luukkainen <marko.luukkainen@vtt.fi>
32 public class FileDocumentUtil {
35 * Imports file, sets its L0.hasName, and and adds it to a library
37 * Note: if library relation is L0.ConsistsOf, L0.HasName is set to next available unique name.
42 * @throws DatabaseException
44 public static Resource importFile(final String fileName, final Resource lib, final Resource rel) throws DatabaseException {
45 return Simantics.getSession().syncRequest(new WriteResultRequest<Resource>() {
47 public Resource perform(WriteGraph graph) throws DatabaseException {
48 return importFile(graph, fileName,lib,rel);
55 public static void importFileAsync(final String fileName, final Resource lib, final Resource rel) {
56 Simantics.getSession().asyncRequest(new WriteRequest() {
59 public void perform(WriteGraph graph) throws DatabaseException {
60 importFile(graph, fileName,lib,rel);
65 ExceptionUtils.logAndShowError("Cannot import file " + fileName, e);
72 * Imports file, sets its L0.HasName, and and adds it to a library
74 * Note: if library relation is L0.ConsistsOf, L0.HasName is set to next available unique name.
80 * @throws DatabaseException
82 public static Resource importFile(WriteGraph graph, String fileName, Resource lib, Resource rel) throws DatabaseException{
83 Layer0 l0 = Layer0.getInstance(graph);
84 Resource fileResource = importFile(graph, fileName);
85 graph.claim(lib, rel, fileResource);
86 File file = new File(fileName);
87 String name = file.getName();
88 graph.claimLiteral(fileResource, l0.HasName, name);
89 setUniqueName(graph, fileResource, lib, rel);
93 public static Resource importFileWithName(WriteGraph graph, String fileName) throws DatabaseException{
94 Layer0 l0 = Layer0.getInstance(graph);
95 Resource fileResource = importFile(graph, fileName);
96 File file = new File(fileName);
97 String name = file.getName();
98 graph.claimLiteral(fileResource, l0.HasName, name);
103 * Imports folder of documents recursively (including all sub folders).
105 * @param folderName Name of imported folder
106 * @param lib Library, where imported folder is attached.
107 * @param folderType Type of folders
108 * @param relation Relation used to create file/folder hierarchy
109 * @return the imported folder
110 * @throws DatabaseException
112 public static Resource importFolderWithName(WriteGraph graph, String folderName, Resource lib, Resource folderType, Resource relation, IProgressMonitor monitor) throws Exception{
113 Resource folderRes = importFolderWithName(graph, folderName, folderType, relation,monitor);
114 graph.claim(lib, relation, folderRes);
115 FileDocumentUtil.createUniqueName(graph, folderRes);
120 * Imports folder of documents recursively (including all sub folders).
122 * @param folderName Name of imported folder
123 * @param folderType Type of folders
124 * @param relation Relation used to create file/folder hierarchy
125 * @param monitor ProgessMonitor or null
126 * @return the imported folder
127 * @throws DatabaseException
129 public static Resource importFolderWithName(WriteGraph graph, String folderName, Resource folderType, Resource relation, IProgressMonitor monitor) throws Exception{
130 Layer0 l0 = Layer0.getInstance(graph);
131 File folder = new File(folderName);
132 Resource rootFolderRes = graph.newResource();
133 graph.claim(rootFolderRes, l0.InstanceOf, folderType);
134 graph.claimLiteral(rootFolderRes, l0.HasName, folder.getName());
135 importFolder(graph, folder, rootFolderRes, relation, monitor);
136 return rootFolderRes;
140 * Imports folder of documents recursively (including all sub folders).
142 * @param folder Imported folder
143 * @param folderResource Resource folder matching file system folder
144 * @param relation Relation used to create file/folder hierarchy
145 * @throws DatabaseException
147 public static void importFolder(WriteGraph graph, File folder, Resource folderResource, Resource relation, IProgressMonitor monitor) throws Exception{
148 if (monitor != null) {
149 int count = _countFiles(folder);
150 monitor.beginTask("Import files", count);
152 _importFolder(graph, folder, folderResource, relation, monitor);
157 private static void _importFolder(WriteGraph graph, File folder, Resource folderResource, Resource relation, IProgressMonitor monitor) throws Exception{
158 Layer0 l0 = Layer0.getInstance(graph);
159 File files[] = folder.listFiles();
160 for (File f : files) {
161 if (f.isDirectory()) {
162 Resource newFolderRes = graph.newResource();
163 graph.claim(newFolderRes, l0.InstanceOf, graph.getSingleType(folderResource));
164 graph.claim(folderResource, relation, newFolderRes);
165 graph.claimLiteral(newFolderRes, l0.HasName, f.getName());
166 _importFolder(graph, f, newFolderRes, relation,monitor);
168 Resource fileRes = null;
171 fileRes = importURL(graph, f);
172 fileRes = importFileWithName(graph, f.getAbsolutePath());
174 graph.claim(folderResource, relation, fileRes);
181 private static int _countFiles(File folder) {
184 File files[] = folder.listFiles();
185 for (File f : files) {
186 if (f.isDirectory()) {
187 count += _countFiles(f);
196 public static void createUniqueName(WriteGraph graph, Resource document) throws DatabaseException {
197 Layer0 l0 = Layer0.getInstance(graph);
198 Resource lib = graph.getPossibleObject(document, l0.PartOf);
201 setUniqueName(graph, document, lib, l0.ConsistsOf);
204 public static void setUniqueName(WriteGraph graph, Resource res, Resource lib, Resource rel) throws DatabaseException{
205 Layer0 l0 = Layer0.getInstance(graph);
206 Set<String> names = new HashSet<String>();
207 for (Resource r : graph.getObjects(lib, rel)) {
210 names.add((String)graph.getRelatedValue(r, l0.HasName));
212 String name = graph.getRelatedValue(res, l0.HasName);
213 if (!names.contains(name))
217 String proposal = name +" (" + i +")";
218 if (!names.contains(proposal)) {
219 graph.claimLiteral(res, l0.HasName, proposal);
233 * @throws DatabaseException
235 public static Resource importFile(WriteGraph graph, String fileName) throws DatabaseException{
236 Layer0 l0 = Layer0.getInstance(graph);
237 DocumentResource doc = DocumentResource.getInstance(graph);
239 Resource fileResource = graph.newResource();
240 graph.claim(fileResource, l0.InstanceOf, doc.FileDocument);
242 GraphFileUtil.toGraph(graph,fileName, fileResource);
244 } catch (IOException e) {
245 throw new DatabaseException(e);
252 * Exports graph folder recursively to file system.
254 * @param folderResource
257 * @throws DatabaseException
259 public static void exportDocumentFolder(final Resource folderResource, final File folder, final Resource relation, boolean useResourceNames, final IProgressMonitor monitor) throws Exception{
260 Simantics.getSession().syncRequest(new ReadRequest() {
263 public void run(ReadGraph graph) throws DatabaseException {
265 exportDocumentFolder(graph, folderResource, folder, relation, useResourceNames, monitor);
266 } catch (Exception e) {
267 throw new DatabaseException(e);
276 * Exports graph folder recursively to file system.
278 * @param folderResource
281 * @throws DatabaseException
283 public static void exportDocumentFolder(ReadGraph graph, Resource folderResource, File folder, Resource relation, boolean useResourceNames, IProgressMonitor monitor) throws Exception{
284 Layer0 l0 = Layer0.getInstance(graph);
285 DocumentResource doc = DocumentResource.getInstance(graph);
286 GraphFileResource gf = GraphFileResource.getInstance(graph);
287 Set<String> names = new HashSet<String>();
288 Collection<Resource> folderType = graph.getPrincipalTypes(folderResource);
289 for (Resource r : graph.getObjects(folderResource, relation)) {
290 if (graph.isInstanceOf(r, doc.Document)) {
292 boolean canExport = false;
293 if (graph.isInstanceOf(r, doc.FileDocument)) {
294 name = graph.getRelatedValue(r, useResourceNames ? gf.HasResourceName : l0.HasName);
296 } else if (graph.isInstanceOf(r, doc.UrlDocument)) {
297 name = graph.getRelatedValue(r, l0.HasName) +".url";
301 name = resolveName(folder, name, names, true);
302 File file = new File(folder.getAbsolutePath()+"/"+name);
303 if (graph.isInstanceOf(r, doc.FileDocument)) {
304 GraphFileUtil.writeDataToFile(graph,r, file);
305 } else if (graph.isInstanceOf(r, doc.UrlDocument)) {
306 String url = graph.getRelatedValue(r, doc.HasUrl);
307 String n = graph.getRelatedValue(r, l0.HasName);
308 exportUrl(file, n, url);
315 Collection<Resource> type = graph.getPrincipalTypes(r);
316 if (type.size() == folderType.size() && folderType.containsAll(type)) {
317 String name = graph.getRelatedValue(r, l0.HasName);
318 name = resolveName(folder, name, names, false);
319 File subFolder = new File(folder.getAbsolutePath()+"/"+name);
320 if (!subFolder.exists()) {
321 if (!subFolder.mkdir()) {
326 exportDocumentFolder(graph, r, subFolder, relation, useResourceNames, monitor);
333 * Print URL to a file (Windows specific format?)
336 * @throws DatabaseException
338 private static void exportUrl(File toFile, String name, String url) throws Exception{
339 PrintStream os = new PrintStream(toFile,"UTF-8");
340 os.println("[InternetShortcut]");
341 os.println("URL="+url);
342 os.println("name="+name);
347 public static Resource importURL(WriteGraph graph, File file) throws Exception{
351 BufferedReader is = null;
353 is = new BufferedReader(new InputStreamReader(new FileInputStream(file), "UTF-8"));
354 while ((s = is.readLine()) != null) {
355 if (s.startsWith("URL=")) {
356 url = s.substring(4);
357 } else if (s.startsWith("name=")) {
358 name = s.substring(5);
369 Layer0 l0 = Layer0.getInstance(graph);
370 DocumentResource doc = DocumentResource.getInstance(graph);
372 Resource fileResource = graph.newResource();
373 graph.claim(fileResource, l0.InstanceOf, doc.UrlDocument);
375 name = file.getName();
376 name = unescape(name);
377 name = name.substring(0,name.length()-4);
379 graph.claimLiteral(fileResource, l0.HasName, name);
380 graph.claimLiteral(fileResource, doc.HasUrl, url);
384 private static boolean isUrl(File file) throws Exception{
385 return (file.getAbsolutePath().endsWith(".url"));
388 private static final char ESCAPE = '%';
390 private static String escape(String s) {
392 int len = s.length();
393 StringBuilder sb = new StringBuilder(len);
394 for (int i = 0; i < len; i++) {
395 char ch = s.charAt(i);
396 if (ch < ' ' || ch >= 0x7F || ch == '/' || ch == '\\' || ch == ':' || ch == ESCAPE) {
401 sb.append(Integer.toHexString(ch));
406 return sb.toString();
409 private static String unescape(String s) {
410 int len = s.length();
411 StringBuilder sb = new StringBuilder(len);
412 for (int i = 0; i < len; i++) {
413 char ch = s.charAt(i);
416 num += s.charAt(++i);
417 num += s.charAt(++i);
418 ch = (char)Integer.decode(num).intValue();
422 return sb.toString();
426 private static String resolveName(File parentFolder, String proposal, Set<String> used, boolean file) {
427 String current = escape(proposal);
432 if (used.contains(current)) {
433 current = createFileName(proposal, i);
435 File subFile = new File(parentFolder.getAbsolutePath()+"/"+current);
436 if (!subFile.exists())
438 if (subFile.exists() && subFile.isFile() && subFile.canWrite()) {
446 if (used.contains(current)) {
447 current = proposal+i;
449 File subFolder = new File(parentFolder.getAbsolutePath()+"/"+current);
450 if (!subFolder.exists())
452 if (subFolder.exists() && subFolder.isDirectory()) {
462 private static String createFileName(String original, int i) {
463 int extIndex = original.lastIndexOf(".");
466 return original.substring(0,extIndex) + i + original.substring(extIndex);