1 package org.simantics.fileimport;
\r
3 import java.io.IOException;
\r
4 import java.io.InputStream;
\r
5 import java.io.OutputStream;
\r
6 import java.nio.file.Files;
\r
7 import java.nio.file.Path;
\r
8 import java.nio.file.Paths;
\r
9 import java.util.ArrayList;
\r
10 import java.util.Collections;
\r
11 import java.util.HashMap;
\r
12 import java.util.List;
\r
13 import java.util.Map;
\r
14 import java.util.Optional;
\r
15 import java.util.Properties;
\r
16 import java.util.function.Consumer;
\r
18 import org.osgi.framework.InvalidSyntaxException;
\r
19 import org.osgi.framework.ServiceReference;
\r
20 import org.simantics.fileimport.dropins.FileImportDropins;
\r
23 * Utility class for Simantics File import functions
\r
25 * @author Jani Simomaa
\r
28 public class FileImportService {
\r
30 private FileImportService() {}
\r
32 public static final String DB_FILE = ".simanticsdb";
\r
34 private static List<IGenericFileImport> getFileImportServices() {
\r
35 ServiceReference<?>[] serviceReferences = new ServiceReference<?>[0];
\r
37 serviceReferences = Activator.getContext().getAllServiceReferences(IGenericFileImport.class.getName(),
\r
39 } catch (InvalidSyntaxException e) {
\r
40 e.printStackTrace();
\r
42 if (serviceReferences.length == 0)
\r
43 return Collections.emptyList();
\r
45 List<IGenericFileImport> services = new ArrayList<>(serviceReferences.length);
\r
46 for (ServiceReference<?> reference : serviceReferences) {
\r
47 IGenericFileImport service = (IGenericFileImport) Activator.getContext().getService(reference);
\r
48 services.add(service);
\r
54 * Lists all supported file extensions which have a registered service for handling the import
\r
56 * @return Map containing the extension and the description of the extension in that order
\r
58 public static Map<String, String> supportedExtensionsWithFilters() {
\r
59 List<IGenericFileImport> services = getFileImportServices();
\r
60 Map<String, String> extensionsWithFilters = new HashMap<>();
\r
61 for (IGenericFileImport service : services)
\r
62 extensionsWithFilters.putAll(service.allowedExtensionsWithFilters());
\r
64 return extensionsWithFilters;
\r
68 * Method that performs the import of the given file. This method is called when e.g. {@link FileImportDropins} watcher detects {@link java.nio.file.StandardWatchEventKinds.ENTRY_CREATE} operation
\r
70 * @param file Path file to be imported
\r
71 * @param callback Optional callback which can be used to catch Throwables thrown in the import process
\r
73 public static void performFileImport(Path file, Optional<Consumer<Throwable>> callback) {
\r
74 if (file.getFileName().toString().equals(DB_FILE))
\r
76 Optional<IGenericFileImport> serviceOp = findServiceForFileExtension(file);
\r
77 serviceOp.ifPresent(service -> {
\r
79 Optional<String> resource = service.perform(file);
\r
80 saveResourceForPath(file, resource);
\r
81 } catch (Throwable t) {
\r
82 if (callback.isPresent()) {
\r
83 callback.get().accept(t);
\r
85 t.printStackTrace();
\r
93 * Remove the entity that matches the file. This method is called when e.g. the {@link FileImportDropins} watcher detects {@link java.nio.file.StandardWatchEventKinds.ENTRY_DELETE} operation
\r
95 * @param file Path file that was deleted
\r
96 * @param callback Optional callback to catch Throwables thrown during the deletion process
\r
98 public static void removeResourceForFile(Path file, Optional<Consumer<Throwable>> callback) {
\r
99 Optional<IGenericFileImport> serviceOp = findServiceForFileExtension(file);
\r
100 serviceOp.ifPresent(service -> {
\r
102 Optional<String> resource = getResourceForPath(file);
\r
103 if (!resource.isPresent())
\r
105 service.remove(resource.get());
\r
106 removeResourceForPath(file);
\r
107 } catch (Throwable t) {
\r
108 if (callback.isPresent()) {
\r
109 callback.get().accept(t);
\r
111 t.printStackTrace();
\r
117 public static void removeFileForResource(long id, Optional<Consumer<Throwable>> callback) {
\r
118 Optional<Path> fileOp;
\r
120 fileOp = findPathForId(id);
\r
121 } catch (IOException e) {
\r
122 e.printStackTrace();
\r
125 if (!fileOp.isPresent())
\r
127 Path file = fileOp.get();
\r
128 Optional<IGenericFileImport> serviceOp = findServiceForFileExtension(file);
\r
129 serviceOp.ifPresent(service -> {
\r
131 Optional<String> resource = getResourceForPath(file);
\r
132 if (!resource.isPresent())
\r
134 service.remove(resource.get());
\r
135 removeResourceForPath(file);
\r
137 Files.delete(file);
\r
138 } catch (IOException e) {
\r
139 Files.delete(file);
\r
141 } catch (Throwable t) {
\r
142 if (callback.isPresent()) {
\r
143 callback.get().accept(t);
\r
145 t.printStackTrace();
\r
151 private static Optional<Path> findPathForId(long id) throws IOException {
\r
152 Path db = Activator.getDropinsFolder().resolve(DB_FILE);
\r
153 if (!Files.exists(db))
\r
154 Files.createFile(db);
\r
155 Properties props = new Properties();
\r
156 try (InputStream stream = Files.newInputStream(db)) {
\r
157 props.load(stream);
\r
159 for (Map.Entry<Object, Object> entry : props.entrySet()) {
\r
160 Long value = Long.valueOf(entry.getValue().toString());
\r
161 if (value.longValue() == id) {
\r
162 String key = (String) entry.getKey();
\r
163 return Optional.of(Paths.get(key));
\r
166 return Optional.empty();
\r
169 static final String FOLDER = "_folder_";
\r
172 * Method for finding a File Import service for the given file based on the file extension
\r
174 * @param file Path file for which the import service is looked for
\r
175 * @return Optiona IGenerigFileImport service which is able to handle the import of this type of file
\r
177 public static Optional<IGenericFileImport> findServiceForFileExtension(Path file) {
\r
178 String extension = "";
\r
180 int i = file.getFileName().toString().lastIndexOf('.');
\r
182 extension = file.getFileName().toString().substring(i);
\r
184 // Handle case that file is actually a directory
\r
185 if (Files.isDirectory(file) || !Files.isRegularFile(file)) {
\r
186 extension = FOLDER;
\r
190 List<IGenericFileImport> services = getFileImportServices();
\r
191 for (IGenericFileImport service : services) {
\r
192 for (Map.Entry<String, String> entry : service.allowedExtensionsWithFilters().entrySet()) {
\r
193 String possibleExtensions = entry.getKey();
\r
194 if (possibleExtensions.startsWith("*"))
\r
195 possibleExtensions = possibleExtensions.substring(1);
\r
196 if (possibleExtensions.equals(extension) || possibleExtensions.isEmpty()) {
\r
197 if (extension.equals(FOLDER) && possibleExtensions.equals(FOLDER)) {
\r
198 return Optional.of(service);
\r
199 } else if (!extension.isEmpty() && !extension.equals(FOLDER)){
\r
200 return Optional.of(service);
\r
205 return Optional.empty();
\r
209 * Method for listing all current paths and their corresponding identifiers in Simantics database
\r
211 * @return Map containing
\r
213 public static Map<String, String> getPathsAndResources() {
\r
215 Path db = Activator.getDropinsFolder().resolve(DB_FILE);
\r
216 if (!Files.exists(db))
\r
217 Files.createFile(db);
\r
218 Properties props = new Properties();
\r
219 try (InputStream stream = Files.newInputStream(db)) {
\r
220 props.load(stream);
\r
222 Map<String, String> map = new HashMap<>();
\r
223 for (Map.Entry<Object, Object> entry : props.entrySet()) {
\r
224 String value = (String) entry.getValue();
\r
225 String key = (String) entry.getKey();
\r
226 map.put(key, value);
\r
229 } catch (IOException e) {
\r
230 e.printStackTrace();
\r
231 return Collections.emptyMap();
\r
235 private static void saveResourceForPath(Path file, Optional<String> resource) {
\r
236 resource.ifPresent(res -> {
\r
238 Path db = Activator.getDropinsFolder().resolve(DB_FILE);
\r
239 if (!Files.exists(db))
\r
240 Files.createFile(db);
\r
241 Properties props = new Properties();
\r
242 try (InputStream stream = Files.newInputStream(db)) {
\r
243 props.load(stream);
\r
245 props.put(file.getFileName().toString(), resource.get());
\r
246 try (OutputStream stream = Files.newOutputStream(db)) {
\r
247 props.store(stream, null);
\r
249 } catch (IOException e) {
\r
250 e.printStackTrace();
\r
255 private static void removeResourceForPath(Path file) throws IOException {
\r
256 Path db = Activator.getDropinsFolder().resolve(DB_FILE);
\r
257 if (!Files.exists(db))
\r
258 Files.createFile(db);
\r
259 Properties props = new Properties();
\r
260 try (InputStream stream = Files.newInputStream(db)) {
\r
261 props.load(stream);
\r
263 props.remove(file.getFileName().toString());
\r
264 try (OutputStream stream = Files.newOutputStream(db)) {
\r
265 props.store(stream, null);
\r
269 private static Optional<String> getResourceForPath(Path file) throws IOException {
\r
270 Path db = Activator.getDropinsFolder().resolve(DB_FILE);
\r
271 if (!Files.exists(db))
\r
272 Files.createFile(db);
\r
273 Properties props = new Properties();
\r
274 try (InputStream stream = Files.newInputStream(db)) {
\r
275 props.load(stream);
\r
277 String value = props.getProperty(file.getFileName().toString());
\r
279 return Optional.empty();
\r
280 return Optional.of(value);
\r