X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=org.simantics.pythonlink%2Fsrc%2Forg%2Fsimantics%2Fpythonlink%2FPythonContext.java;h=ecf925d9bfc9c358a72e5b5303b6bbf315f1a7b4;hb=c09eb1d21fa19556b14301ca70b622b8a2e1d080;hp=d237c83eb5afd5ab0c112111adaadeb2120b729e;hpb=52bef206878a4384b43494243dd39813b2bdf5ad;p=simantics%2Fpython.git diff --git a/org.simantics.pythonlink/src/org/simantics/pythonlink/PythonContext.java b/org.simantics.pythonlink/src/org/simantics/pythonlink/PythonContext.java index d237c83..ecf925d 100644 --- a/org.simantics.pythonlink/src/org/simantics/pythonlink/PythonContext.java +++ b/org.simantics.pythonlink/src/org/simantics/pythonlink/PythonContext.java @@ -1,94 +1,294 @@ -package org.simantics.pythonlink; - -import java.io.Closeable; - -public class PythonContext implements Closeable { - private long contextID; - - PythonContext() { - contextID = openPythonContextImpl(); - } - - @Override - public void close() { - long id = contextID; - contextID = 0; - closePythonContextImpl(id); - } - - public void executePythonStatement(String statement) { - executePythonStatementImpl( contextID, statement ); - } - - public void setPythonIntegerVariable(String variableName, int value) { - setPythonIntegerVariableImpl(contextID, variableName, value); - } - public void setPythonDoubleVariable(String variableName, double value) { - setPythonDoubleVariableImpl(contextID, variableName, value); - } - public void setPythonStringVariable(String variableName, String value) { - setPythonStringVariableImpl(contextID, variableName, value); - } - - public void setPythonIntegerArrayVariable(String variableName, int[] value) { - setPythonIntegerArrayVariableImpl(contextID, variableName, value); - } - public void setPythonDoubleArrayVariable(String variableName, double[] value) { - setPythonDoubleArrayVariableImpl(contextID, variableName, value); - } - public void setPythonStringArrayVariable(String variableName, String[] value) { - setPythonStringArrayVariableImpl(contextID, variableName, value); - } - - public int getPythonIntegerVariable(String variableName) { - return getPythonIntegerVariableImpl(contextID, variableName); - } - public double getPythonDoubleVariable(String variableName) { - return getPythonDoubleVariableImpl(contextID, variableName); - } - public String getPythonStringVariable(String variableName) { - return getPythonStringVariableImpl(contextID, variableName); - } - - public int[] getPythonIntegerArrayVariable(String variableName) { - return getPythonIntegerArrayVariableImpl(contextID, variableName); - } - public double[] getPythonDoubleArrayVariable(String variableName) { - return getPythonDoubleArrayVariableImpl(contextID, variableName); - } - public String[] getPythonStringArrayVariable(String variableName) { - return getPythonStringArrayVariableImpl(contextID, variableName); - } - - public void setPythonNDArrayVariable(String variableName, NDArray value) { - setPythonNDArrayVariableImpl(contextID, variableName, value); - } - public NDArray getPythonNDArrayVariable(String variableName) { - return getPythonNDArrayVariableImpl(contextID, variableName); - } - - // Native function declarations - private static native long openPythonContextImpl(); - private static native void closePythonContextImpl(long contextID); - - private static native void executePythonStatementImpl(long contextID, String statement); - - private static native void setPythonIntegerVariableImpl(long contextID, String variableName, int value); - private static native void setPythonDoubleVariableImpl(long contextID, String variableName, double value); - private static native void setPythonStringVariableImpl(long contextID, String variableName, String value); - - private static native void setPythonIntegerArrayVariableImpl(long contextID, String variableName, int[] value); - private static native void setPythonDoubleArrayVariableImpl(long contextID, String variableName, double[] value); - private static native void setPythonStringArrayVariableImpl(long contextID, String variableName, String[] value); - - private static native int getPythonIntegerVariableImpl(long contextID, String variableName); - private static native double getPythonDoubleVariableImpl(long contextID, String variableName); - private static native String getPythonStringVariableImpl(long contextID, String variableName); - - private static native int[] getPythonIntegerArrayVariableImpl(long contextID, String variableName); - private static native double[] getPythonDoubleArrayVariableImpl(long contextID, String variableName); - private static native String[] getPythonStringArrayVariableImpl(long contextID, String variableName); - - private static native void setPythonNDArrayVariableImpl(long contextID, String variableName, NDArray value); - private static native NDArray getPythonNDArrayVariableImpl(long contextID, String variableName); -} +package org.simantics.pythonlink; + +import java.io.Closeable; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.regex.Pattern; + +import org.simantics.databoard.Bindings; +import org.simantics.databoard.binding.Binding; +import org.simantics.databoard.binding.error.BindingException; +import org.simantics.databoard.binding.mutable.Variant; + +public class PythonContext implements Closeable { + private long contextID; + + public interface Listener { + void updated(String variableName); + void closed(); + } + + static ExecutorService pythonExecutor = Executors.newSingleThreadExecutor(); + + Set listeners = new HashSet<>(); + + public enum VariableType { + NO_VARIABLE, + BOOLEAN, + LONG, + FLOAT, + STRING, + BYTEARRAY, + DICTIONARY, + NDARRAY, + SEQUENCE, + UNKNOWN + } + + static Pattern namePattern = Pattern.compile("([a-zA-Z_][a-zA-Z_0-9]*)"); + + PythonContext() { + contextID = execute(() -> createContextImpl()); + } + + public void addListener(Listener listener) { + listeners.add(listener); + } + + public void removeListener(Listener listener) { + listeners.remove(listener); + } + + @Override + public void close() { + long id = contextID; + contextID = 0; + if (id != 0) execute(() -> deleteContextImpl(id)); + + for (Listener l : listeners) { + l.closed(); + } + } + + public boolean isOpen() { + return contextID != 0; + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + close(); + } + + public void executePythonStatement(String statement) { + execute(() -> executePythonStatementImpl( contextID, statement )); + for (Listener l : listeners) { l.updated(null); } + } + + // Setters + + public void setPythonBooleanVariable(String variableName, boolean value) { + checkValidName(variableName); + execute(() -> setPythonBooleanVariableImpl(contextID, variableName, value)); + for (Listener l : listeners) { l.updated(variableName); } + } + + public void setPythonIntegerVariable(String variableName, int value) { + checkValidName(variableName); + execute(() -> setPythonLongVariableImpl(contextID, variableName, value)); + for (Listener l : listeners) { l.updated(variableName); } + } + public void setPythonLongVariable(String variableName, long value) { + checkValidName(variableName); + execute(() -> setPythonLongVariableImpl(contextID, variableName, value)); + for (Listener l : listeners) { l.updated(variableName); } + } + public void setPythonDoubleVariable(String variableName, double value) { + checkValidName(variableName); + execute(() -> setPythonDoubleVariableImpl(contextID, variableName, value)); + for (Listener l : listeners) { l.updated(variableName); } + } + public void setPythonStringVariable(String variableName, String value) { + checkValidName(variableName); + execute(() -> setPythonStringVariableImpl(contextID, variableName, value)); + for (Listener l : listeners) { l.updated(variableName); } + } + + public void setPythonBooleanArrayVariable(String variableName, boolean[] value) { + checkValidName(variableName); + execute(() -> setPythonBooleanArrayVariableImpl(contextID, variableName, value)); + for (Listener l : listeners) { l.updated(variableName); } + } + public void setPythonIntegerArrayVariable(String variableName, int[] value) { + checkValidName(variableName); + execute(() -> setPythonIntegerArrayVariableImpl(contextID, variableName, value)); + for (Listener l : listeners) { l.updated(variableName); } + } + public void setPythonLongArrayVariable(String variableName, long[] value) { + checkValidName(variableName); + execute(() -> setPythonLongArrayVariableImpl(contextID, variableName, value)); + for (Listener l : listeners) { l.updated(variableName); } + } + public void setPythonDoubleArrayVariable(String variableName, double[] value) { + checkValidName(variableName); + execute(() -> setPythonDoubleArrayVariableImpl(contextID, variableName, value)); + for (Listener l : listeners) { l.updated(variableName); } + } + public void setPythonStringArrayVariable(String variableName, String[] value) { + checkValidName(variableName); + execute(() -> setPythonStringArrayVariableImpl(contextID, variableName, value)); + for (Listener l : listeners) { l.updated(variableName); } + } + + // Getters + + public boolean getPythonBooleanVariable(String variableName) { + checkValidName(variableName); + return getPythonBooleanVariableImpl(contextID, variableName); + } + public int getPythonIntegerVariable(String variableName) { + checkValidName(variableName); + long value = execute(() -> getPythonLongVariableImpl(contextID, variableName)); + if (value > Integer.MAX_VALUE || value < Integer.MIN_VALUE) + throw new RuntimeException("Python value not in integer range"); + return (int) value; + } + public long getPythonLongVariable(String variableName) { + checkValidName(variableName); + return execute(() -> getPythonLongVariableImpl(contextID, variableName)); + } + public double getPythonDoubleVariable(String variableName) { + checkValidName(variableName); + return execute(() -> getPythonDoubleVariableImpl(contextID, variableName)); + } + public String getPythonStringVariable(String variableName) { + checkValidName(variableName); + return execute(() -> getPythonStringVariableImpl(contextID, variableName)); + } + + public boolean[] getPythonBooleanArrayVariable(String variableName) { + checkValidName(variableName); + return execute(() -> getPythonBooleanArrayVariableImpl(contextID, variableName)); + } + public int[] getPythonIntegerArrayVariable(String variableName) { + checkValidName(variableName); + return execute(() -> getPythonIntegerArrayVariableImpl(contextID, variableName)); + } + public long[] getPythonLongArrayVariable(String variableName) { + checkValidName(variableName); + return execute(() -> getPythonLongArrayVariableImpl(contextID, variableName)); + } + public double[] getPythonDoubleArrayVariable(String variableName) { + checkValidName(variableName); + return execute(() -> getPythonDoubleArrayVariableImpl(contextID, variableName)); + } + public String[] getPythonStringArrayVariable(String variableName) { + checkValidName(variableName); + return execute(() -> getPythonStringArrayVariableImpl(contextID, variableName)); + } + + public void setPythonNDArrayVariable(String variableName, NDArray value) { + checkValidName(variableName); + execute(() -> setPythonNDArrayVariableImpl(contextID, variableName, value)); + } + public NDArray getPythonNDArrayVariable(String variableName) { + checkValidName(variableName); + return execute(() -> getPythonNDArrayVariableImpl(contextID, variableName)); + } + + public Object getPythonVariantVariable(String variableName, Binding binding) { + checkValidName(variableName); + Object result = execute(() -> getPythonVariantVariableImpl(contextID, variableName)); + try { + return Bindings.OBJECT.getContent(result, binding); + } catch (BindingException e) { + throw new RuntimeException(e); + } + } + + public Variant getPythonVariantVariable(String variableName) { + checkValidName(variableName); + return Variant.ofInstance(execute(() -> getPythonVariantVariableImpl(contextID, variableName))); + } + + public void setPythonVariantVariable(String variableName, Variant value) { + setPythonVariantVariable(variableName, value.getValue(), value.getBinding()); + } + + public void setPythonVariantVariable(String variableName, Object value, Binding binding) { + checkValidName(variableName); + if (!binding.isInstance(value)) throw new IllegalArgumentException("Invalid object binding"); + + execute(() -> setPythonVariantVariableImpl(contextID, variableName, value, binding)); + + for (Listener l : listeners) { l.updated(variableName); } + } + + public VariableType getPythonVariableType(String variableName) { + checkValidName(variableName); + int code = execute(() -> getPythonVariableTypeImpl(contextID, variableName)); + + VariableType[] values = VariableType.values(); + if (code < 0 || code >= values.length) + return VariableType.UNKNOWN; + + return values[code]; + } + + public String[] getPythonVariableNames() { + return execute(() -> getPythonVariableNamesImpl(contextID)); + } + + private static void checkValidName(String variableName) { + if (!namePattern.matcher(variableName).matches()) + throw new IllegalArgumentException("Invalid Python variable name " + variableName); + } + + static void execute(Runnable job) { + try { + pythonExecutor.submit(job).get(); + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + } + + static V execute(Callable job) { + try { + return pythonExecutor.submit(job).get(); + } catch (InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + } + + // Native function declarations + private static native long createContextImpl(); + private static native void deleteContextImpl(long contextID); + + private static native int executePythonStatementImpl(long contextID, String statement); + + private static native void setPythonBooleanVariableImpl(long contextID, String variableName, boolean value); + private static native void setPythonLongVariableImpl(long contextID, String variableName, long value); + private static native void setPythonDoubleVariableImpl(long contextID, String variableName, double value); + private static native void setPythonStringVariableImpl(long contextID, String variableName, String value); + + private static native void setPythonBooleanArrayVariableImpl(long contextID, String variableName, boolean[] value); + private static native void setPythonIntegerArrayVariableImpl(long contextID, String variableName, int[] value); + private static native void setPythonLongArrayVariableImpl(long contextID, String variableName, long[] value); + private static native void setPythonDoubleArrayVariableImpl(long contextID, String variableName, double[] value); + private static native void setPythonStringArrayVariableImpl(long contextID, String variableName, String[] value); + + private static native boolean getPythonBooleanVariableImpl(long contextID, String variableName); + private static native long getPythonLongVariableImpl(long contextID, String variableName); + private static native double getPythonDoubleVariableImpl(long contextID, String variableName); + private static native String getPythonStringVariableImpl(long contextID, String variableName); + + private static native boolean[] getPythonBooleanArrayVariableImpl(long contextID, String variableName); + private static native long[] getPythonLongArrayVariableImpl(long contextID, String variableName); + private static native int[] getPythonIntegerArrayVariableImpl(long contextID, String variableName); + private static native double[] getPythonDoubleArrayVariableImpl(long contextID, String variableName); + private static native String[] getPythonStringArrayVariableImpl(long contextID, String variableName); + + private static native void setPythonNDArrayVariableImpl(long contextID, String variableName, NDArray value); + private static native NDArray getPythonNDArrayVariableImpl(long contextID, String variableName); + + private static native void setPythonVariantVariableImpl(long contextID, String variableName, Object value, Binding binding); + private static native Object getPythonVariantVariableImpl(long contextID, String variableName); + + private static native int getPythonVariableTypeImpl(long contextID, String variableName); + + private static native String[] getPythonVariableNamesImpl(long contextID); +}