package org.simantics.fileimport; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; import java.util.Properties; import java.util.function.Consumer; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; import org.simantics.Simantics; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.request.UniqueRead; import org.simantics.db.exception.DatabaseException; import org.simantics.db.service.SerialisationSupport; import org.simantics.layer0.Layer0; public class FileImportService { public static final String DB_FILE = ".simanticsdb"; public static List getFileImportServices() { ServiceReference[] serviceReferences = new ServiceReference[0]; try { serviceReferences = Activator.getContext().getAllServiceReferences(IGenericFileImport.class.getName(), null); } catch (InvalidSyntaxException e) { e.printStackTrace(); } if (serviceReferences.length == 0) return Collections.emptyList(); List services = new ArrayList<>(serviceReferences.length); for (ServiceReference reference : serviceReferences) { IGenericFileImport service = (IGenericFileImport) Activator.getContext().getService(reference); services.add(service); } return services; } public static Map supportedExtensionsWithFilters() { List services = getFileImportServices(); Map extensionsWithFilters = new HashMap<>(); for (IGenericFileImport service : services) extensionsWithFilters.putAll(service.allowedExtensionsWithFilters()); return extensionsWithFilters; } public static void performFileImport(Path file, Optional> callback) { if (file.getFileName().toString().equals(DB_FILE)) return; Optional serviceOp = findServiceForFileExtension(file); serviceOp.ifPresent(service -> { try { Optional resource = service.perform(file); saveResourceForPath(file, resource); } catch (Throwable t) { if (callback.isPresent()) { callback.get().accept(t); } else { t.printStackTrace(); } } }); } public static void removeResourceForFile(Path file, Optional> callback) { Optional serviceOp = findServiceForFileExtension(file); serviceOp.ifPresent(service -> { try { Optional resource = getResourceForPath(file); if (!resource.isPresent()) return; service.remove(resource.get()); removeResourceForPath(file); } catch (Throwable t) { if (callback.isPresent()) { callback.get().accept(t); } else { t.printStackTrace(); } } }); } public static void removeFileForResource(long id, Optional> callback) { Optional fileOp; try { fileOp = findPathForId(id); } catch (IOException e) { e.printStackTrace(); return; } if (!fileOp.isPresent()) return; Path file = fileOp.get(); Optional serviceOp = findServiceForFileExtension(file); serviceOp.ifPresent(service -> { try { Optional resource = getResourceForPath(file); if (!resource.isPresent()) return; service.remove(resource.get()); removeResourceForPath(file); } catch (Throwable t) { if (callback.isPresent()) { callback.get().accept(t); } else { t.printStackTrace(); } } }); } private static Optional findPathForId(long id) throws IOException { Path db = Activator.getDropinsFolder().resolve(DB_FILE); if (!Files.exists(db)) Files.createFile(db); Properties props = new Properties(); try (InputStream stream = Files.newInputStream(db)) { props.load(stream); } for (Map.Entry entry : props.entrySet()) { Long value = Long.valueOf(entry.getValue().toString()); if (value.longValue() == id) { String key = (String) entry.getKey(); return Optional.of(Paths.get(key)); } } return Optional.empty(); } static final String FOLDER = "_folder_"; public static Optional findServiceForFileExtension(Path file) { String extension = ""; int i = file.getFileName().toString().lastIndexOf('.'); if (i > 0) { extension = file.getFileName().toString().substring(i); } else { // Handle case that file is actually a directory if (Files.isDirectory(file) || !Files.isRegularFile(file)) { extension = FOLDER; } } List services = getFileImportServices(); for (IGenericFileImport service : services) { for (Map.Entry entry : service.allowedExtensionsWithFilters().entrySet()) { String possibleExtensions = entry.getKey(); if (possibleExtensions.startsWith("*")) possibleExtensions = possibleExtensions.substring(1); if (possibleExtensions.equals(extension) || possibleExtensions.isEmpty()) { if (extension.equals(FOLDER) && possibleExtensions.equals(FOLDER)) { return Optional.of(service); } else if (!extension.isEmpty() && !extension.equals(FOLDER)){ return Optional.of(service); } } } } return Optional.empty(); } public static Map getPathsAndResources() { try { Path db = Activator.getDropinsFolder().resolve(DB_FILE); if (!Files.exists(db)) Files.createFile(db); Properties props = new Properties(); try (InputStream stream = Files.newInputStream(db)) { props.load(stream); } Map result = Simantics.getSession().syncRequest(new UniqueRead>() { @Override public Map perform(ReadGraph graph) throws DatabaseException { Map map = new HashMap<>(); for (Map.Entry entry : props.entrySet()) { String value = (String) entry.getValue(); Long id = Long.valueOf(value); SerialisationSupport ss = graph.getService(SerialisationSupport.class); try { Resource r = ss.getResource(id); String name = graph.getRelatedValue(r, Layer0.getInstance(graph).HasName); map.put(name, id); } catch (DatabaseException e) { e.printStackTrace(); } } return map; } }); return result; } catch (IOException | DatabaseException e) { e.printStackTrace(); return Collections.emptyMap(); } } private static void saveResourceForPath(Path file, Optional resource) { resource.ifPresent(res -> { try { Path db = Activator.getDropinsFolder().resolve(DB_FILE); if (!Files.exists(db)) Files.createFile(db); Properties props = new Properties(); try (InputStream stream = Files.newInputStream(db)) { props.load(stream); } props.put(file.getFileName().toString(), resource.get()); try (OutputStream stream = Files.newOutputStream(db)) { props.store(stream, null); } } catch (IOException e) { e.printStackTrace(); } }); } private static void removeResourceForPath(Path file) throws IOException { Path db = Activator.getDropinsFolder().resolve(DB_FILE); if (!Files.exists(db)) Files.createFile(db); Properties props = new Properties(); try (InputStream stream = Files.newInputStream(db)) { props.load(stream); } props.remove(file.getFileName().toString()); try (OutputStream stream = Files.newOutputStream(db)) { props.store(stream, null); } } private static Optional getResourceForPath(Path file) throws IOException { Path db = Activator.getDropinsFolder().resolve(DB_FILE); if (!Files.exists(db)) Files.createFile(db); Properties props = new Properties(); try (InputStream stream = Files.newInputStream(db)) { props.load(stream); } String value = props.getProperty(file.getFileName().toString()); if (value == null) return Optional.empty(); return Optional.of(value); } }