get(x,y).setVerticalAlignment(verticalAlignment);\r
}\r
\r
+ public void setForceEventListening(int x, int y, boolean force) {\r
+ get(x,y).setForceEventListening(force);\r
+ }\r
+ \r
public void setEditable(int x, int y, boolean editable) {\r
get(x,y).setEditable(editable);\r
}\r
*/\r
protected String text = null;\r
\r
- /**\r
- * Tells if this node is still pending for real results or not.\r
- */\r
- protected boolean pending = false;\r
-\r
/**\r
* The font used to render the {@link #text}.\r
*/\r
*/\r
protected byte verticalAlignment = 3;\r
\r
- protected boolean hover = false;\r
- boolean editable = false;\r
- boolean showSelection = true;\r
- \r
- \r
- boolean wrapText = true;\r
+ /**\r
+ * Tells if this node is still pending for real results or not.\r
+ */\r
+ protected static final int STATE_PENDING = (1 << 0);\r
+ protected static final int STATE_HOVER = (1 << 1);\r
+ protected static final int STATE_EDITABLE = (1 << 2);\r
+ protected static final int STATE_SHOW_SELECTION = (1 << 3);\r
+ protected static final int STATE_WRAP_TEXT = (1 << 4);\r
+ protected transient static final int STATE_EDITING = (1 << 5);\r
+ protected transient static final int STATE_VALID = (1 << 6);\r
+ protected transient static final int STATE_X_OFFSET_IS_DIRTY = (1 << 7);\r
+ protected static final int STATE_ALWAYS_ADD_LISTENERS = (1 << 8);\r
+ protected static final int STATE_LISTENERS_ADDED = (1 << 9);\r
+\r
+ /**\r
+ * A combination of all the STATE_ constants defined in this class,\r
+ * e.g. {@link #STATE_PENDING}.\r
+ */\r
+ protected int state = STATE_SHOW_SELECTION | STATE_WRAP_TEXT | STATE_VALID | STATE_X_OFFSET_IS_DIRTY;\r
\r
protected RVI dataRVI = null;\r
\r
ITextListener textListener;\r
ITextContentFilter editContentFilter;\r
\r
- transient boolean editing = false;\r
- transient boolean valid = true;\r
-\r
- private transient boolean xOffsetIsDirty = true;\r
-\r
/**\r
* The renderable line structures parsed from {@link #text} by\r
* {@link #parseLines(String)}, laid out by\r
super.cleanup();\r
}\r
\r
+ protected boolean hasState(int flags) {\r
+ return (state & flags) == flags;\r
+ }\r
+\r
+ protected void setState(int flags) {\r
+ this.state |= flags;\r
+ }\r
+\r
+ protected void setState(int flags, boolean set) {\r
+ if (set)\r
+ this.state |= flags;\r
+ else\r
+ this.state &= ~flags;\r
+ }\r
+\r
+ protected void clearState(int flags) {\r
+ this.state &= ~flags;\r
+ }\r
+\r
+ protected void setListeners(boolean add) {\r
+ if (add)\r
+ addListeners();\r
+ else\r
+ removeListeners();\r
+ }\r
+\r
protected void addListeners() {\r
- addEventHandler(this);\r
+ if (!hasState(STATE_LISTENERS_ADDED)) {\r
+ addEventHandler(this);\r
+ setState(STATE_LISTENERS_ADDED);\r
+ }\r
}\r
\r
protected void removeListeners() {\r
- removeEventHandler(this);\r
+ if (hasState(STATE_LISTENERS_ADDED)) {\r
+ removeEventHandler(this);\r
+ clearState(STATE_LISTENERS_ADDED);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Set to true to always enable event listening in this TextNode to allow the text node to keep track of hovering, etc. and to allow DnD even when \r
+ * @param force\r
+ */\r
+ public void setForceEventListening(boolean force) {\r
+ setState(STATE_ALWAYS_ADD_LISTENERS, force);\r
+ if (force && !hasState(STATE_EDITABLE)) {\r
+ setListeners(force);\r
+ }\r
}\r
\r
/**\r
* @return null if no change to edit state was made\r
*/\r
protected Boolean setEditMode(boolean edit, boolean notify) {\r
- if (edit && !editable)\r
+ if (edit && !hasState(STATE_EDITABLE))\r
return null;\r
- if (editing == edit)\r
+ if (hasState(STATE_EDITING) == edit)\r
return null;\r
- this.editing = edit;\r
+ setState(STATE_EDITING);\r
if (edit) {\r
caret = text != null ? text.length() : 0;\r
selectionTail = 0;\r
\r
@SyncField({"editable"})\r
public void setEditable(boolean editable) {\r
- boolean changed = this.editable != editable;\r
- this.editable = editable;\r
- if (editing && !editable)\r
+ boolean changed = hasState(STATE_EDITABLE) != editable;\r
+ setState(STATE_EDITABLE, editable);\r
+ if (hasState(STATE_EDITING) && !editable)\r
setEditMode(false);\r
- if (changed) {\r
- if (editable)\r
- addListeners();\r
- else\r
- removeListeners();\r
+ if (changed && !hasState(STATE_ALWAYS_ADD_LISTENERS)) {\r
+ setListeners(editable);\r
}\r
}\r
\r
public boolean isEditable() {\r
- return editable;\r
+ return hasState(STATE_EDITABLE);\r
}\r
\r
public boolean isEditMode() {\r
- return editing;\r
+ return hasState(STATE_EDITING);\r
}\r
\r
@SyncField({"wrapText"})\r
public void setWrapText(boolean wrapText) {\r
- this.wrapText = wrapText;\r
+ setState(STATE_WRAP_TEXT, wrapText);\r
}\r
\r
/**\r
* the width of the box is fixed\r
*/\r
public boolean isWrapText() {\r
- return this.wrapText;\r
+ return hasState(STATE_WRAP_TEXT);\r
}\r
\r
@SyncField({"showSelection"})\r
public void setShowSelection(boolean showSelection) {\r
- this.showSelection = showSelection;\r
+ setState(STATE_SHOW_SELECTION, showSelection);\r
}\r
\r
public boolean showsSelection() {\r
- return showSelection;\r
+ return hasState(STATE_SHOW_SELECTION);\r
}\r
\r
/**\r
// no value => value\r
if(this.text == null && text != null) NodeUtil.decreasePending(this);\r
\r
- if (editing)\r
+ if (hasState(STATE_EDITING))\r
return;\r
\r
this.text = new String(text != null ? text : "");\r
@SyncField({"text","caret","selectionTail"})\r
public void setText(String text) {\r
//System.out.println("TextNode.setText('" + text + "', " + editing + ")");\r
- if (editing)\r
+ if (hasState(STATE_EDITING))\r
return;\r
\r
// value => no value\r
\r
@SyncField({"pending"})\r
public void setPending(boolean pending) {\r
- if(!this.pending && pending) NodeUtil.increasePending(this);\r
- if(this.pending && !pending) NodeUtil.decreasePending(this);\r
- this.pending = pending;\r
+ boolean p = hasState(STATE_PENDING);\r
+ if(!p && pending) NodeUtil.increasePending(this);\r
+ if(p && !pending) NodeUtil.decreasePending(this);\r
+ if(p != pending)\r
+ setState(STATE_PENDING, pending);\r
}\r
\r
@SyncField({"fixedWidth"})\r
}\r
\r
public final void synchronizeWrapText(boolean wrap) {\r
- wrapText = wrap;\r
+ setState(STATE_WRAP_TEXT, wrap);\r
}\r
\r
public boolean isHovering() {\r
- return hover;\r
+ return hasState(STATE_HOVER);\r
}\r
\r
@SyncField({"hover"})\r
public void setHover(boolean hover) {\r
- this.hover = hover;\r
+ setState(STATE_HOVER, hover);\r
repaint();\r
}\r
\r
\r
Color color = this.color;\r
boolean isSelected = NodeUtil.isSelected(this, 1);\r
+ boolean hover = hasState(STATE_HOVER);\r
+ boolean editing = hasState(STATE_EDITING);\r
\r
if (!isSelected && hover) {\r
color = add(color, 120, 120, 120);\r
fieldName.equals("created_by") );\r
}\r
\r
- Color backgroundColor = valid ? this.backgroundColor : Color.red;\r
+ Color backgroundColor = hasState(STATE_VALID) ? this.backgroundColor : Color.red;\r
\r
// RENDER\r
if ( !isPdfField ) {\r
\r
if(validator != null) {\r
String error = validator.apply(text);\r
- valid = (error == null);\r
+ setState(STATE_VALID, (error == null));\r
}\r
\r
resetCaches();\r
\r
@ServerSide\r
protected void fireTextEditingCancelled() {\r
- valid = true;\r
+ setState(STATE_VALID);\r
\r
if (deactivateEdit()) {\r
if (textListener != null)\r
\r
@ServerSide\r
public void fireTextEditingEnded() {\r
- if (!valid) {\r
+ if (!hasState(STATE_VALID)) {\r
fireTextEditingCancelled();\r
- valid = true;\r
+ setState(STATE_VALID);\r
return;\r
}\r
\r
}\r
\r
private void invalidateXOffset() {\r
- xOffsetIsDirty = true;\r
+ setState(STATE_X_OFFSET_IS_DIRTY);\r
}\r
\r
private void computeEditingXOffset() {\r
\r
if(lines == null) return;\r
- if(!xOffsetIsDirty) return;\r
+ if(!hasState(STATE_X_OFFSET_IS_DIRTY)) return;\r
if(fixedWidth > 0f) {\r
\r
// TODO: implement\r
\r
}\r
\r
- xOffsetIsDirty = false;\r
+ clearState(STATE_X_OFFSET_IS_DIRTY);\r
\r
}\r
\r
// Parse & layout (unaligned)\r
Line[] lines = null;\r
\r
- if(wrapText) {\r
+ if(hasState(STATE_WRAP_TEXT)) {\r
float width = fixedWidth;\r
if(width <= 0 && targetBounds != null)\r
width = (float) (((targetBounds.getWidth() - 2*paddingX)) * scaleRecip);\r
\r
@Override\r
protected boolean handleCommand(CommandEvent e) {\r
- if (!editing)\r
+ if (!hasState(STATE_EDITING))\r
return false;\r
\r
if (Commands.SELECT_ALL.equals(e.command)) {\r
\r
@Override\r
protected boolean keyPressed(KeyPressedEvent event) {\r
- if (!editing)\r
+ if (!hasState(STATE_EDITING))\r
return false;\r
\r
char c = event.character;\r
case KeyEvent.VK_ESCAPE:\r
text = textBeforeEdit;\r
resetCaches();\r
- editing = false;\r
+ clearState(STATE_EDITING);\r
fireTextEditingCancelled();\r
return true;\r
\r
if (event.button != MouseClickEvent.LEFT_BUTTON)\r
return false;\r
\r
- if (hover) {\r
+ if (hasState(STATE_HOVER)) {\r
hoverClick++;\r
if (hoverClick < 2)\r
return false;\r
if (ctx == null)\r
return false;\r
IElement e = DiagramNodeUtil.getElement(ctx, this);\r
- if (!editing) {\r
+ if (!hasState(STATE_EDITING)) {\r
if (Boolean.TRUE.equals(setEditMode(true))) {\r
editActivation = activateEdit(0, e, ctx);\r
repaint();\r
} \r
} else {\r
hoverClick = 0;\r
- if (editing) {\r
+ if (hasState(STATE_EDITING)) {\r
fireTextEditingEnded();\r
}\r
}\r
\r
@Override\r
protected boolean mouseButtonPressed(MouseButtonPressedEvent event) {\r
- if (!editing)\r
+ if (!hasState(STATE_EDITING))\r
return false;\r
\r
Point2D local = controlToLocal( event.controlPosition );\r
// FIXME: once the event coordinate systems are cleared up, remove this workaround\r
local = parentToLocal(local);\r
- if (hover && this.containsLocal(local)) {\r
+ if (hasState(STATE_HOVER) && this.containsLocal(local)) {\r
setCaret(local, event.isShiftDown());\r
}\r
return false;\r
@Override\r
protected boolean mouseMoved(MouseMovedEvent event) {\r
boolean hit = hitTest(event, 3.0);\r
- if (hit != hover) {\r
- hover = hit;\r
+ if (hit != hasState(STATE_HOVER)) {\r
+ setState(STATE_HOVER, hit);\r
repaint();\r
}\r
return false;\r
setTextNodeData(node, 3, row, value3, FONT, awtColor, BACKGROUND_COLOR);\r
\r
node.setEditable(1, row, false);\r
+ node.setForceEventListening(2, row, true);\r
node.setEditable(2, row, modifier != null);\r
node.setEditable(3, row, false);\r
\r
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
-Bundle-Name: Simantics Fileimport Interface
+Bundle-Name: Simantics Fileimport Interface and base classes
Bundle-SymbolicName: org.simantics.fileimport
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: org.simantics.fileimport.Activator
Export-Package: org.simantics.fileimport
Service-Component: OSGI-INF/FileReferenceFileImport.xml,
OSGI-INF/LibraryFolderFileImport.xml
+Bundle-Vendor: Semantum Oy
import "MMap" as MMap\r
\r
importJava "org.simantics.fileimport.scl.DropinsSCL" where\r
+ watchDropinsFolder :: () -> <Proc> ()\r
+ unwatchDropinsFolder :: () -> <Proc> ()\r
uploadToDropinsBase64 :: String -> String -> <Proc> ()\r
getUploadedFiles :: () -> <Proc> MMap.T String Long\r
removeFileForId :: Long -> <Proc> ()\r
\r
import org.osgi.framework.InvalidSyntaxException;\r
import org.osgi.framework.ServiceReference;\r
-import org.simantics.Simantics;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.common.request.UniqueRead;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.service.SerialisationSupport;\r
-import org.simantics.layer0.Layer0;\r
+import org.simantics.fileimport.dropins.FileImportDropins;\r
\r
+/**\r
+ * Utility class for Simantics File import functions\r
+ * \r
+ * @author Jani Simomaa\r
+ *\r
+ */\r
public class FileImportService {\r
\r
public static final String DB_FILE = ".simanticsdb";\r
\r
- public static List<IGenericFileImport> getFileImportServices() {\r
+ private static List<IGenericFileImport> getFileImportServices() {\r
ServiceReference<?>[] serviceReferences = new ServiceReference<?>[0];\r
try {\r
serviceReferences = Activator.getContext().getAllServiceReferences(IGenericFileImport.class.getName(),\r
return services;\r
}\r
\r
+ /**\r
+ * Lists all supported file extensions which have a registered service for handling the import\r
+ * \r
+ * @return Map containing the extension and the description of the extension in that order\r
+ */\r
public static Map<String, String> supportedExtensionsWithFilters() {\r
List<IGenericFileImport> services = getFileImportServices();\r
Map<String, String> extensionsWithFilters = new HashMap<>();\r
return extensionsWithFilters;\r
}\r
\r
+ /**\r
+ * 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
+ * \r
+ * @param file Path file to be imported\r
+ * @param callback Optional callback which can be used to catch Throwables thrown in the import process\r
+ */\r
public static void performFileImport(Path file, Optional<Consumer<Throwable>> callback) {\r
if (file.getFileName().toString().equals(DB_FILE))\r
return;\r
});\r
}\r
\r
+ \r
+ /**\r
+ * 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
+ * \r
+ * @param file Path file that was deleted\r
+ * @param callback Optional callback to catch Throwables thrown during the deletion process\r
+ */\r
public static void removeResourceForFile(Path file, Optional<Consumer<Throwable>> callback) {\r
Optional<IGenericFileImport> serviceOp = findServiceForFileExtension(file);\r
serviceOp.ifPresent(service -> {\r
\r
static final String FOLDER = "_folder_";\r
\r
+ /**\r
+ * Method for finding a File Import service for the given file based on the file extension\r
+ * \r
+ * @param file Path file for which the import service is looked for\r
+ * @return Optiona IGenerigFileImport service which is able to handle the import of this type of file\r
+ */\r
public static Optional<IGenericFileImport> findServiceForFileExtension(Path file) {\r
String extension = "";\r
\r
return Optional.empty();\r
}\r
\r
- public static Map<String, Long> getPathsAndResources() {\r
+ /**\r
+ * Method for listing all current paths and their corresponding identifiers in Simantics database\r
+ * \r
+ * @return Map containing \r
+ */\r
+ public static Map<String, String> getPathsAndResources() {\r
try {\r
Path db = Activator.getDropinsFolder().resolve(DB_FILE);\r
if (!Files.exists(db))\r
try (InputStream stream = Files.newInputStream(db)) {\r
props.load(stream);\r
}\r
- Map<String, Long> result = Simantics.getSession().syncRequest(new UniqueRead<Map<String, Long>>() {\r
-\r
- @Override\r
- public Map<String, Long> perform(ReadGraph graph) throws DatabaseException {\r
- Map<String, Long> map = new HashMap<>();\r
- for (Map.Entry<Object, Object> entry : props.entrySet()) {\r
- String value = (String) entry.getValue();\r
- Long id = Long.valueOf(value);\r
- SerialisationSupport ss = graph.getService(SerialisationSupport.class);\r
- try {\r
- Resource r = ss.getResource(id);\r
- String name = graph.getRelatedValue(r, Layer0.getInstance(graph).HasName);\r
- map.put(name, id);\r
- } catch (DatabaseException e) {\r
- e.printStackTrace();\r
- }\r
- }\r
- return map;\r
- }\r
- });\r
-\r
- return result;\r
- } catch (IOException | DatabaseException e) {\r
+ Map<String, String> map = new HashMap<>();\r
+ for (Map.Entry<Object, Object> entry : props.entrySet()) {\r
+ String value = (String) entry.getValue();\r
+ String key = (String) entry.getKey();\r
+ map.put(key, value);\r
+ }\r
+ return map;\r
+ } catch (IOException e) {\r
e.printStackTrace();\r
return Collections.emptyMap();\r
}\r
import java.util.Optional;\r
\r
/**\r
+ * Base interface for performing file imports. \r
+ * \r
+ * Usually with Simantics products every file that will be imported will become \r
+ * a resource in the Simantics database. For these cases see {@link SimanticsResourceFileImport}\r
+ * \r
* @author Jani Simomaa\r
*\r
*/\r
public interface IGenericFileImport {\r
\r
/**\r
- * Performs the import procedure for the given file\r
+ * Performs the import for the given file\r
* \r
- * @param file\r
- * file to import\r
+ * @param file Path to file to import\r
+ * @return Optional string which will be the identifier of the imported file which can later be used for removing the imported entity\r
+ * @throws Exception\r
*/\r
Optional<String> perform(Path file) throws Exception;\r
\r
/**\r
- * @param resource\r
+ * Remove the entity\r
+ * \r
+ * @param identifier String identifier which can be used to remove the imported entity\r
*/\r
- void remove(String resource) throws Exception;\r
+ void remove(String identifier) throws Exception;\r
\r
/**\r
* Returns a key-value map for file extensions this importer can handle\r
* \r
- * @return\r
+ * @return Map<String, String> allowed extensions this service can handle. Key is the extension e.g. <code>.sharedLibrary</code> and the value is the description of the extension\r
*/\r
Map<String, String> allowedExtensionsWithFilters();\r
\r
import org.simantics.db.service.SerialisationSupport;\r
import org.simantics.layer0.Layer0;\r
\r
+/**\r
+ * Most of the implementations should extend this class which handles the storing of\r
+ * the identifier of the imported entity and the removing of the entity\r
+ * \r
+ * @author Jani Simomaa\r
+ *\r
+ */\r
public abstract class SimanticsResourceFileImport implements IGenericFileImport {\r
\r
@Override\r
final public Optional<String> perform(Path file) throws Exception {\r
\r
- Path dropins = Activator.getDropinsFolder(); \r
+ Path dropins = Activator.getDropinsFolder();\r
Path parts = dropins.relativize(file);\r
Resource parent = resolveParent(null, parts);\r
if (parent == null)\r
}\r
}\r
\r
- public abstract Optional<Resource> perform(Resource parent, Path file);\r
+ /**\r
+ * Performs the import for the given file\r
+ * \r
+ * @param parent Resource parent of the imported entity in Simantics database\r
+ * @param file Path file location of file\r
+ * @return Optional Resource of the imported entity in Simantics database\r
+ * @throws Exception\r
+ */\r
+ public abstract Optional<Resource> perform(Resource parent, Path file) throws Exception;\r
\r
@Override\r
public void remove(String resourceId) throws Exception {\r
package org.simantics.fileimport.dropins;\r
\r
-import static java.nio.file.StandardWatchEventKinds.OVERFLOW;\r
import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;\r
import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;\r
import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;\r
+import static java.nio.file.StandardWatchEventKinds.OVERFLOW;\r
\r
import java.io.IOException;\r
+import java.io.RandomAccessFile;\r
import java.nio.file.FileSystem;\r
+import java.nio.file.FileSystemException;\r
import java.nio.file.FileVisitResult;\r
import java.nio.file.Files;\r
import java.nio.file.Path;\r
import java.nio.file.SimpleFileVisitor;\r
import java.nio.file.WatchEvent;\r
import java.nio.file.WatchEvent.Kind;\r
+import java.nio.file.WatchKey;\r
+import java.nio.file.WatchService;\r
import java.nio.file.attribute.BasicFileAttributes;\r
import java.util.HashMap;\r
import java.util.Map;\r
import java.util.Optional;\r
import java.util.concurrent.atomic.AtomicBoolean;\r
-import java.nio.file.WatchKey;\r
-import java.nio.file.WatchService;\r
\r
import org.simantics.fileimport.Activator;\r
import org.simantics.fileimport.FileImportService;\r
\r
+/**\r
+ * Directory watcher based on {@link java.nio.file.WatchService} which will listen to file changes inside the dropins directory\r
+ * ~/workspace/.metadata/plugins/org.simantics.fileimport/dropins\r
+ * \r
+ * @author Jani Simomaa\r
+ *\r
+ */\r
public class FileImportDropins {\r
\r
private static Thread watcherThread = null;\r
private static DropinsFolderWatcher watcher = null;\r
\r
+ /**\r
+ * Start watching the dropins folder which are located in\r
+ * ~/workspace/.metadata/plugins/org.simantics.fileimport/dropins\r
+ */\r
public static void watchDropinsFolder() {\r
if (watcher == null && watcherThread == null) {\r
try {\r
}\r
}\r
\r
+ /**\r
+ * Stop watching the dropins folder\r
+ */\r
public static void unwatchDropinsFolder() {\r
watcher.stop();\r
try {\r
registerAll(this.dropinsFolder);\r
}\r
\r
+ private static void syncPath(Path f) throws IOException {\r
+ // Does not seem to need 's' according to unit test in Windows\r
+ boolean synced = false;\r
+ int count = 0;\r
+ while (!synced) {\r
+ try (RandomAccessFile raf = new RandomAccessFile(f.toFile(), "rw")) {\r
+ raf.getFD().sync();\r
+ synced = true;\r
+ } catch (IOException e) {\r
+ if (count == 3) {\r
+ throw e;\r
+ } else {\r
+ try {\r
+ Thread.sleep(50);\r
+ } catch (InterruptedException e1) {\r
+ e1.printStackTrace();\r
+ }\r
+ count++;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ \r
@Override\r
public void run() {\r
stopped.set(false);\r
continue;\r
if (ENTRY_CREATE == kind) {\r
System.out.println("New path created: " + newPath);\r
- FileImportService.performFileImport(newPath, Optional.empty());\r
+ int current = 0;\r
+ \r
+ while (!Files.isWritable(newPath) && current <= 10) {\r
+ System.out.println("Sleeping for file import (current=" + current +")");\r
+ Thread.sleep(200);\r
+ current++;\r
+ }\r
+ \r
+ FileImportService.performFileImport(newPath, Optional.of(t -> {\r
+ if (t instanceof FileSystemException) {\r
+ try {\r
+ syncPath(newPath);\r
+ } catch (IOException e) {\r
+ e.printStackTrace();\r
+ }\r
+ FileImportService.performFileImport(newPath, Optional.empty());\r
+ } else {\r
+ t.printStackTrace();\r
+ }\r
+ }));\r
register(newPath);\r
+ \r
} else if (ENTRY_MODIFY == kind) {\r
System.out.println("New path modified: " + newPath);\r
} else if (ENTRY_DELETE == kind) {\r
keys.remove(key);\r
// break; // loop\r
}\r
- } catch (IOException e) {\r
- e.printStackTrace();\r
} catch (InterruptedException e) {\r
if (!stopped.get())\r
e.printStackTrace();\r
\r
import java.io.IOException;\r
import java.nio.file.Path;\r
+import java.util.HashMap;\r
import java.util.Map;\r
import java.util.Optional;\r
\r
+import org.simantics.Simantics;\r
import org.simantics.databoard.util.Base64;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.request.UniqueRead;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.service.SerialisationSupport;\r
import org.simantics.fileimport.Activator;\r
import org.simantics.fileimport.FileImportService;\r
import org.simantics.fileimport.dropins.FileImportDropins;\r
+import org.simantics.layer0.Layer0;\r
import org.simantics.utils.FileUtils;\r
\r
+/**\r
+ * SCL interface for Simantics File Import Functionality\r
+ * See <code>"Dropins/Core"</code> SCL module for more\r
+ * \r
+ * @author Jani Simomaa\r
+ *\r
+ */\r
public class DropinsSCL {\r
\r
+ public static void watchDropinsFolder() {\r
+ FileImportDropins.watchDropinsFolder();\r
+ }\r
+ \r
+ public static void unwatchDropinsFolder() {\r
+ FileImportDropins.unwatchDropinsFolder();\r
+ }\r
+ \r
public static void uploadToDropinsBase64(String base64, String fileName) {\r
// ensure that watcher is awake\r
FileImportDropins.watchDropinsFolder();\r
}\r
}\r
\r
- public static Map<String, Long> getUploadedFiles() {\r
- return FileImportService.getPathsAndResources();\r
+ public static Map<String, Long> getUploadedFiles() throws DatabaseException {\r
+ Map<String, String> results = FileImportService.getPathsAndResources();\r
+ Map<String, Long> result = Simantics.getSession().syncRequest(new UniqueRead<Map<String, Long>>() {\r
+\r
+ @Override\r
+ public Map<String, Long> perform(ReadGraph graph) throws DatabaseException {\r
+ Map<String, Long> map = new HashMap<>();\r
+ for (Map.Entry<String, String> entry : results.entrySet()) {\r
+ String value = (String) entry.getValue();\r
+ Long id = Long.valueOf(value);\r
+ SerialisationSupport ss = graph.getService(SerialisationSupport.class);\r
+ try {\r
+ Resource r = ss.getResource(id);\r
+ String name = graph.getRelatedValue(r, Layer0.getInstance(graph).HasName);\r
+ map.put(name, id);\r
+ } catch (DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+ }\r
+ return map;\r
+ }\r
+ });\r
+ return result;\r
}\r
\r
public static void removeFileForId(long id) {\r