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 public static final String DB_FILE = ".simanticsdb";
\r
32 private static List<IGenericFileImport> getFileImportServices() {
\r
33 ServiceReference<?>[] serviceReferences = new ServiceReference<?>[0];
\r
35 serviceReferences = Activator.getContext().getAllServiceReferences(IGenericFileImport.class.getName(),
\r
37 } catch (InvalidSyntaxException e) {
\r
38 e.printStackTrace();
\r
40 if (serviceReferences.length == 0)
\r
41 return Collections.emptyList();
\r
43 List<IGenericFileImport> services = new ArrayList<>(serviceReferences.length);
\r
44 for (ServiceReference<?> reference : serviceReferences) {
\r
45 IGenericFileImport service = (IGenericFileImport) Activator.getContext().getService(reference);
\r
46 services.add(service);
\r
52 * Lists all supported file extensions which have a registered service for handling the import
\r
54 * @return Map containing the extension and the description of the extension in that order
\r
56 public static Map<String, String> supportedExtensionsWithFilters() {
\r
57 List<IGenericFileImport> services = getFileImportServices();
\r
58 Map<String, String> extensionsWithFilters = new HashMap<>();
\r
59 for (IGenericFileImport service : services)
\r
60 extensionsWithFilters.putAll(service.allowedExtensionsWithFilters());
\r
62 return extensionsWithFilters;
\r
66 * 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
68 * @param file Path file to be imported
\r
69 * @param callback Optional callback which can be used to catch Throwables thrown in the import process
\r
71 public static void performFileImport(Path file, Optional<Consumer<Throwable>> callback) {
\r
72 if (file.getFileName().toString().equals(DB_FILE))
\r
74 Optional<IGenericFileImport> serviceOp = findServiceForFileExtension(file);
\r
75 serviceOp.ifPresent(service -> {
\r
77 Optional<String> resource = service.perform(file);
\r
78 saveResourceForPath(file, resource);
\r
79 } catch (Throwable t) {
\r
80 if (callback.isPresent()) {
\r
81 callback.get().accept(t);
\r
83 t.printStackTrace();
\r
91 * 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
93 * @param file Path file that was deleted
\r
94 * @param callback Optional callback to catch Throwables thrown during the deletion process
\r
96 public static void removeResourceForFile(Path file, Optional<Consumer<Throwable>> callback) {
\r
97 Optional<IGenericFileImport> serviceOp = findServiceForFileExtension(file);
\r
98 serviceOp.ifPresent(service -> {
\r
100 Optional<String> resource = getResourceForPath(file);
\r
101 if (!resource.isPresent())
\r
103 service.remove(resource.get());
\r
104 removeResourceForPath(file);
\r
105 } catch (Throwable t) {
\r
106 if (callback.isPresent()) {
\r
107 callback.get().accept(t);
\r
109 t.printStackTrace();
\r
115 public static void removeFileForResource(long id, Optional<Consumer<Throwable>> callback) {
\r
116 Optional<Path> fileOp;
\r
118 fileOp = findPathForId(id);
\r
119 } catch (IOException e) {
\r
120 e.printStackTrace();
\r
123 if (!fileOp.isPresent())
\r
125 Path file = fileOp.get();
\r
126 Optional<IGenericFileImport> serviceOp = findServiceForFileExtension(file);
\r
127 serviceOp.ifPresent(service -> {
\r
129 Optional<String> resource = getResourceForPath(file);
\r
130 if (!resource.isPresent())
\r
132 service.remove(resource.get());
\r
133 removeResourceForPath(file);
\r
134 } catch (Throwable t) {
\r
135 if (callback.isPresent()) {
\r
136 callback.get().accept(t);
\r
138 t.printStackTrace();
\r
144 private static Optional<Path> findPathForId(long id) throws IOException {
\r
145 Path db = Activator.getDropinsFolder().resolve(DB_FILE);
\r
146 if (!Files.exists(db))
\r
147 Files.createFile(db);
\r
148 Properties props = new Properties();
\r
149 try (InputStream stream = Files.newInputStream(db)) {
\r
150 props.load(stream);
\r
152 for (Map.Entry<Object, Object> entry : props.entrySet()) {
\r
153 Long value = Long.valueOf(entry.getValue().toString());
\r
154 if (value.longValue() == id) {
\r
155 String key = (String) entry.getKey();
\r
156 return Optional.of(Paths.get(key));
\r
159 return Optional.empty();
\r
162 static final String FOLDER = "_folder_";
\r
165 * Method for finding a File Import service for the given file based on the file extension
\r
167 * @param file Path file for which the import service is looked for
\r
168 * @return Optiona IGenerigFileImport service which is able to handle the import of this type of file
\r
170 public static Optional<IGenericFileImport> findServiceForFileExtension(Path file) {
\r
171 String extension = "";
\r
173 int i = file.getFileName().toString().lastIndexOf('.');
\r
175 extension = file.getFileName().toString().substring(i);
\r
177 // Handle case that file is actually a directory
\r
178 if (Files.isDirectory(file) || !Files.isRegularFile(file)) {
\r
179 extension = FOLDER;
\r
183 List<IGenericFileImport> services = getFileImportServices();
\r
184 for (IGenericFileImport service : services) {
\r
185 for (Map.Entry<String, String> entry : service.allowedExtensionsWithFilters().entrySet()) {
\r
186 String possibleExtensions = entry.getKey();
\r
187 if (possibleExtensions.startsWith("*"))
\r
188 possibleExtensions = possibleExtensions.substring(1);
\r
189 if (possibleExtensions.equals(extension) || possibleExtensions.isEmpty()) {
\r
190 if (extension.equals(FOLDER) && possibleExtensions.equals(FOLDER)) {
\r
191 return Optional.of(service);
\r
192 } else if (!extension.isEmpty() && !extension.equals(FOLDER)){
\r
193 return Optional.of(service);
\r
198 return Optional.empty();
\r
202 * Method for listing all current paths and their corresponding identifiers in Simantics database
\r
204 * @return Map containing
\r
206 public static Map<String, String> getPathsAndResources() {
\r
208 Path db = Activator.getDropinsFolder().resolve(DB_FILE);
\r
209 if (!Files.exists(db))
\r
210 Files.createFile(db);
\r
211 Properties props = new Properties();
\r
212 try (InputStream stream = Files.newInputStream(db)) {
\r
213 props.load(stream);
\r
215 Map<String, String> map = new HashMap<>();
\r
216 for (Map.Entry<Object, Object> entry : props.entrySet()) {
\r
217 String value = (String) entry.getValue();
\r
218 String key = (String) entry.getKey();
\r
219 map.put(key, value);
\r
222 } catch (IOException e) {
\r
223 e.printStackTrace();
\r
224 return Collections.emptyMap();
\r
228 private static void saveResourceForPath(Path file, Optional<String> resource) {
\r
229 resource.ifPresent(res -> {
\r
231 Path db = Activator.getDropinsFolder().resolve(DB_FILE);
\r
232 if (!Files.exists(db))
\r
233 Files.createFile(db);
\r
234 Properties props = new Properties();
\r
235 try (InputStream stream = Files.newInputStream(db)) {
\r
236 props.load(stream);
\r
238 props.put(file.getFileName().toString(), resource.get());
\r
239 try (OutputStream stream = Files.newOutputStream(db)) {
\r
240 props.store(stream, null);
\r
242 } catch (IOException e) {
\r
243 e.printStackTrace();
\r
248 private static void removeResourceForPath(Path file) throws IOException {
\r
249 Path db = Activator.getDropinsFolder().resolve(DB_FILE);
\r
250 if (!Files.exists(db))
\r
251 Files.createFile(db);
\r
252 Properties props = new Properties();
\r
253 try (InputStream stream = Files.newInputStream(db)) {
\r
254 props.load(stream);
\r
256 props.remove(file.getFileName().toString());
\r
257 try (OutputStream stream = Files.newOutputStream(db)) {
\r
258 props.store(stream, null);
\r
262 private static Optional<String> getResourceForPath(Path file) throws IOException {
\r
263 Path db = Activator.getDropinsFolder().resolve(DB_FILE);
\r
264 if (!Files.exists(db))
\r
265 Files.createFile(db);
\r
266 Properties props = new Properties();
\r
267 try (InputStream stream = Files.newInputStream(db)) {
\r
268 props.load(stream);
\r
270 String value = props.getProperty(file.getFileName().toString());
\r
272 return Optional.empty();
\r
273 return Optional.of(value);
\r