1 package org.simantics.document.ui.graphfile;
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.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;
31 * @author Marko Luukkainen <marko.luukkainen@vtt.fi>
34 public class FileDocumentUtil {
37 * Imports file, sets its L0.hasName, and and adds it to a library
39 * Note: if library relation is L0.ConsistsOf, L0.HasName is set to next available unique name.
44 * @throws DatabaseException
46 public static Resource importFile(final String fileName, final Resource lib, final Resource rel) throws DatabaseException {
47 return Simantics.getSession().syncRequest(new WriteResultRequest<Resource>() {
49 public Resource perform(WriteGraph graph) throws DatabaseException {
50 return importFile(graph, fileName,lib,rel);
57 public static void importFileAsync(final String fileName, final Resource lib, final Resource rel) {
58 Simantics.getSession().asyncRequest(new WriteRequest() {
61 public void perform(WriteGraph graph) throws DatabaseException {
62 importFile(graph, fileName,lib,rel);
67 ExceptionUtils.logAndShowError(NLS.bind(Messages.FileDocumentUtil_CannotImportFile, fileName), e);
74 * Imports file, sets its L0.HasName, and and adds it to a library
76 * Note: if library relation is L0.ConsistsOf, L0.HasName is set to next available unique name.
82 * @throws DatabaseException
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);
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);
105 * Imports folder of documents recursively (including all sub folders).
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
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);
122 * Imports folder of documents recursively (including all sub folders).
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
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;
142 * Imports folder of documents recursively (including all sub folders).
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
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);
154 _importFolder(graph, folder, folderResource, relation, monitor);
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);
170 Resource fileRes = null;
173 fileRes = importURL(graph, f);
174 fileRes = importFileWithName(graph, f.getAbsolutePath());
176 graph.claim(folderResource, relation, fileRes);
183 private static int _countFiles(File folder) {
186 File files[] = folder.listFiles();
187 for (File f : files) {
188 if (f.isDirectory()) {
189 count += _countFiles(f);
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);
203 setUniqueName(graph, document, lib, l0.ConsistsOf);
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)) {
212 names.add((String)graph.getRelatedValue(r, l0.HasName));
214 String name = graph.getRelatedValue(res, l0.HasName);
215 if (!names.contains(name))
219 String proposal = name +" (" + i +")"; //$NON-NLS-1$ //$NON-NLS-2$
220 if (!names.contains(proposal)) {
221 graph.claimLiteral(res, l0.HasName, proposal);
235 * @throws DatabaseException
237 public static Resource importFile(WriteGraph graph, String fileName) throws DatabaseException{
238 Layer0 l0 = Layer0.getInstance(graph);
239 DocumentResource doc = DocumentResource.getInstance(graph);
241 Resource fileResource = graph.newResource();
242 graph.claim(fileResource, l0.InstanceOf, doc.FileDocument);
244 GraphFileUtil.toGraph(graph,fileName, fileResource);
246 } catch (IOException e) {
247 throw new DatabaseException(e);
254 * Exports graph folder recursively to file system.
256 * @param folderResource
259 * @throws DatabaseException
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() {
265 public void run(ReadGraph graph) throws DatabaseException {
267 exportDocumentFolder(graph, folderResource, folder, relation, useResourceNames, monitor);
268 } catch (Exception e) {
269 throw new DatabaseException(e);
278 * Exports graph folder recursively to file system.
280 * @param folderResource
283 * @throws DatabaseException
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)) {
294 boolean canExport = false;
295 if (graph.isInstanceOf(r, doc.FileDocument)) {
296 name = graph.getRelatedValue(r, useResourceNames ? gf.HasResourceName : l0.HasName);
298 } else if (graph.isInstanceOf(r, doc.UrlDocument)) {
299 name = graph.getRelatedValue(r, l0.HasName) +".url"; //$NON-NLS-1$
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);
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()) {
328 exportDocumentFolder(graph, r, subFolder, relation, useResourceNames, monitor);
335 * Print URL to a file (Windows specific format?)
338 * @throws DatabaseException
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$
349 public static Resource importURL(WriteGraph graph, File file) throws Exception{
353 BufferedReader is = null;
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);
371 Layer0 l0 = Layer0.getInstance(graph);
372 DocumentResource doc = DocumentResource.getInstance(graph);
374 Resource fileResource = graph.newResource();
375 graph.claim(fileResource, l0.InstanceOf, doc.UrlDocument);
377 name = file.getName();
378 name = unescape(name);
379 name = name.substring(0,name.length()-4);
381 graph.claimLiteral(fileResource, l0.HasName, name);
382 graph.claimLiteral(fileResource, doc.HasUrl, url);
386 private static boolean isUrl(File file) throws Exception{
387 return (file.getAbsolutePath().endsWith(".url")); //$NON-NLS-1$
390 private static final char ESCAPE = '%';
392 private static String escape(String s) {
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) {
403 sb.append(Integer.toHexString(ch));
408 return sb.toString();
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);
417 String num = "0x"; //$NON-NLS-1$
418 num += s.charAt(++i);
419 num += s.charAt(++i);
420 ch = (char)Integer.decode(num).intValue();
424 return sb.toString();
428 private static String resolveName(File parentFolder, String proposal, Set<String> used, boolean file) {
429 String current = escape(proposal);
434 if (used.contains(current)) {
435 current = createFileName(proposal, i);
437 File subFile = new File(parentFolder.getAbsolutePath()+"/"+current); //$NON-NLS-1$
438 if (!subFile.exists())
440 if (subFile.exists() && subFile.isFile() && subFile.canWrite()) {
448 if (used.contains(current)) {
449 current = proposal+i;
451 File subFolder = new File(parentFolder.getAbsolutePath()+"/"+current); //$NON-NLS-1$
452 if (!subFolder.exists())
454 if (subFolder.exists() && subFolder.isDirectory()) {
464 private static String createFileName(String original, int i) {
465 int extIndex = original.lastIndexOf("."); //$NON-NLS-1$
468 return original.substring(0,extIndex) + i + original.substring(extIndex);