X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=org.simantics.pythonlink%2Fsrc%2Forg%2Fsimantics%2Fpythonlink%2FPythonContext.java;h=6c96dd3bde8a877e1e2115c4f1686f4101a44200;hb=15304b7c3168ef89c47dcfcfb4cf34c72000a75f;hp=5341cc233c16c02076e00bbfa8684aa09d14c001;hpb=7a0336fbf77a80fb8ca53dc9df3e76985c7b2860;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 5341cc2..6c96dd3 100644 --- a/org.simantics.pythonlink/src/org/simantics/pythonlink/PythonContext.java +++ b/org.simantics.pythonlink/src/org/simantics/pythonlink/PythonContext.java @@ -1,21 +1,73 @@ 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 = 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) deleteContextImpl(id); + + for (Listener l : listeners) { + l.closed(); + } } + public boolean isOpen() { + return contextID != 0; + } + @Override protected void finalize() throws Throwable { super.finalize(); @@ -23,82 +75,220 @@ public class PythonContext implements Closeable { } public void executePythonStatement(String statement) { - executePythonStatementImpl( contextID, 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) { - setPythonIntegerVariableImpl(contextID, variableName, 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) { - setPythonDoubleVariableImpl(contextID, variableName, value); + checkValidName(variableName); + execute(() -> setPythonDoubleVariableImpl(contextID, variableName, value)); + for (Listener l : listeners) { l.updated(variableName); } } public void setPythonStringVariable(String variableName, String value) { - setPythonStringVariableImpl(contextID, variableName, 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) { - setPythonIntegerArrayVariableImpl(contextID, variableName, 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) { - setPythonDoubleArrayVariableImpl(contextID, variableName, value); + checkValidName(variableName); + execute(() -> setPythonDoubleArrayVariableImpl(contextID, variableName, value)); + for (Listener l : listeners) { l.updated(variableName); } } public void setPythonStringArrayVariable(String variableName, String[] value) { - setPythonStringArrayVariableImpl(contextID, variableName, 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) { - return getPythonIntegerVariableImpl(contextID, 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) { - return getPythonDoubleVariableImpl(contextID, variableName); + checkValidName(variableName); + return execute(() -> getPythonDoubleVariableImpl(contextID, variableName)); } public String getPythonStringVariable(String variableName) { - return getPythonStringVariableImpl(contextID, 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) { - return getPythonIntegerArrayVariableImpl(contextID, 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) { - return getPythonDoubleArrayVariableImpl(contextID, variableName); + checkValidName(variableName); + return execute(() -> getPythonDoubleArrayVariableImpl(contextID, variableName)); } public String[] getPythonStringArrayVariable(String variableName) { - return getPythonStringArrayVariableImpl(contextID, variableName); + checkValidName(variableName); + return execute(() -> getPythonStringArrayVariableImpl(contextID, variableName)); } public void setPythonNDArrayVariable(String variableName, NDArray value) { - setPythonNDArrayVariableImpl(contextID, variableName, value); + checkValidName(variableName); + execute(() -> setPythonNDArrayVariableImpl(contextID, variableName, value)); } public NDArray getPythonNDArrayVariable(String variableName) { - return getPythonNDArrayVariableImpl(contextID, 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 setPythonIntegerVariableImpl(long contextID, String variableName, int value); + 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 int getPythonIntegerVariableImpl(long contextID, String variableName); + 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); }