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
136 } catch (Throwable t) {
\r
137 if (callback.isPresent()) {
\r
138 callback.get().accept(t);
\r
140 t.printStackTrace();
\r
146 private static Optional<Path> findPathForId(long id) throws IOException {
\r
147 Path db = Activator.getDropinsFolder().resolve(DB_FILE);
\r
148 if (!Files.exists(db))
\r
149 Files.createFile(db);
\r
150 Properties props = new Properties();
\r
151 try (InputStream stream = Files.newInputStream(db)) {
\r
152 props.load(stream);
\r
154 for (Map.Entry<Object, Object> entry : props.entrySet()) {
\r
155 Long value = Long.valueOf(entry.getValue().toString());
\r
156 if (value.longValue() == id) {
\r
157 String key = (String) entry.getKey();
\r
158 return Optional.of(Paths.get(key));
\r
161 return Optional.empty();
\r
164 static final String FOLDER = "_folder_";
\r
167 * Method for finding a File Import service for the given file based on the file extension
\r
169 * @param file Path file for which the import service is looked for
\r
170 * @return Optiona IGenerigFileImport service which is able to handle the import of this type of file
\r
172 public static Optional<IGenericFileImport> findServiceForFileExtension(Path file) {
\r
173 String extension = "";
\r
175 int i = file.getFileName().toString().lastIndexOf('.');
\r
177 extension = file.getFileName().toString().substring(i);
\r
179 // Handle case that file is actually a directory
\r
180 if (Files.isDirectory(file) || !Files.isRegularFile(file)) {
\r
181 extension = FOLDER;
\r
185 List<IGenericFileImport> services = getFileImportServices();
\r
186 for (IGenericFileImport service : services) {
\r
187 for (Map.Entry<String, String> entry : service.allowedExtensionsWithFilters().entrySet()) {
\r
188 String possibleExtensions = entry.getKey();
\r
189 if (possibleExtensions.startsWith("*"))
\r
190 possibleExtensions = possibleExtensions.substring(1);
\r
191 if (possibleExtensions.equals(extension) || possibleExtensions.isEmpty()) {
\r
192 if (extension.equals(FOLDER) && possibleExtensions.equals(FOLDER)) {
\r
193 return Optional.of(service);
\r
194 } else if (!extension.isEmpty() && !extension.equals(FOLDER)){
\r
195 return Optional.of(service);
\r
200 return Optional.empty();
\r
204 * Method for listing all current paths and their corresponding identifiers in Simantics database
\r
206 * @return Map containing
\r
208 public static Map<String, String> getPathsAndResources() {
\r
210 Path db = Activator.getDropinsFolder().resolve(DB_FILE);
\r
211 if (!Files.exists(db))
\r
212 Files.createFile(db);
\r
213 Properties props = new Properties();
\r
214 try (InputStream stream = Files.newInputStream(db)) {
\r
215 props.load(stream);
\r
217 Map<String, String> map = new HashMap<>();
\r
218 for (Map.Entry<Object, Object> entry : props.entrySet()) {
\r
219 String value = (String) entry.getValue();
\r
220 String key = (String) entry.getKey();
\r
221 map.put(key, value);
\r
224 } catch (IOException e) {
\r
225 e.printStackTrace();
\r
226 return Collections.emptyMap();
\r
230 private static void saveResourceForPath(Path file, Optional<String> resource) {
\r
231 resource.ifPresent(res -> {
\r
233 Path db = Activator.getDropinsFolder().resolve(DB_FILE);
\r
234 if (!Files.exists(db))
\r
235 Files.createFile(db);
\r
236 Properties props = new Properties();
\r
237 try (InputStream stream = Files.newInputStream(db)) {
\r
238 props.load(stream);
\r
240 props.put(file.getFileName().toString(), resource.get());
\r
241 try (OutputStream stream = Files.newOutputStream(db)) {
\r
242 props.store(stream, null);
\r
244 } catch (IOException e) {
\r
245 e.printStackTrace();
\r
250 private static void removeResourceForPath(Path file) throws IOException {
\r
251 Path db = Activator.getDropinsFolder().resolve(DB_FILE);
\r
252 if (!Files.exists(db))
\r
253 Files.createFile(db);
\r
254 Properties props = new Properties();
\r
255 try (InputStream stream = Files.newInputStream(db)) {
\r
256 props.load(stream);
\r
258 props.remove(file.getFileName().toString());
\r
259 try (OutputStream stream = Files.newOutputStream(db)) {
\r
260 props.store(stream, null);
\r
264 private static Optional<String> getResourceForPath(Path file) throws IOException {
\r
265 Path db = Activator.getDropinsFolder().resolve(DB_FILE);
\r
266 if (!Files.exists(db))
\r
267 Files.createFile(db);
\r
268 Properties props = new Properties();
\r
269 try (InputStream stream = Files.newInputStream(db)) {
\r
270 props.load(stream);
\r
272 String value = props.getProperty(file.getFileName().toString());
\r
274 return Optional.empty();
\r
275 return Optional.of(value);
\r