]> gerrit.simantics Code Review - simantics/python.git/blob - org.simantics.pythonlink/src/org/simantics/pythonlink/PythonContext.java
Merge "Macro for Python installation directory."
[simantics/python.git] / org.simantics.pythonlink / src / org / simantics / pythonlink / PythonContext.java
1 package org.simantics.pythonlink;\r
2 \r
3 import java.io.Closeable;\r
4 import java.util.HashSet;\r
5 import java.util.Set;\r
6 import java.util.concurrent.Callable;\r
7 import java.util.concurrent.ExecutionException;\r
8 import java.util.concurrent.ExecutorService;\r
9 import java.util.concurrent.Executors;\r
10 import java.util.regex.Pattern;\r
11 \r
12 import org.simantics.databoard.Bindings;\r
13 import org.simantics.databoard.binding.Binding;\r
14 import org.simantics.databoard.binding.error.BindingException;\r
15 import org.simantics.databoard.binding.mutable.Variant;\r
16 import org.simantics.scl.runtime.SCLContext;\r
17 import org.simantics.scl.runtime.reporting.SCLReportingHandler;\r
18 \r
19 public class PythonContext implements Closeable {\r
20     private long contextID;\r
21     \r
22     public interface Listener {\r
23         void updated(String variableName);\r
24         void closed();\r
25     }\r
26     \r
27     static ExecutorService pythonExecutor = Executors.newSingleThreadExecutor();\r
28     \r
29     Set<Listener> listeners = new HashSet<>();\r
30     \r
31     public enum VariableType {\r
32         NO_VARIABLE,\r
33         BOOLEAN,\r
34         LONG,\r
35         FLOAT,\r
36         STRING,\r
37         BYTEARRAY,\r
38         DICTIONARY,\r
39         NDARRAY,\r
40         SEQUENCE,\r
41         UNKNOWN\r
42     }\r
43     \r
44     static Pattern namePattern = Pattern.compile("([a-zA-Z_][a-zA-Z_0-9]*)");\r
45     \r
46     PythonContext() {\r
47         contextID = createContextImpl();\r
48     }\r
49     \r
50     public void addListener(Listener listener) {\r
51         listeners.add(listener);\r
52     }\r
53     \r
54     public void removeListener(Listener listener) {\r
55                 listeners.remove(listener);\r
56     }\r
57     \r
58     @Override\r
59     public void close() {\r
60         long id = contextID;\r
61         contextID = 0;\r
62         if (id != 0) deleteContextImpl(id);\r
63         \r
64         for (Listener l : listeners) {\r
65                 l.closed();\r
66         }\r
67     }\r
68 \r
69         public boolean isOpen() {\r
70                 return contextID != 0;\r
71         }\r
72         \r
73     @Override\r
74     protected void finalize() throws Throwable {\r
75         super.finalize();\r
76         close();\r
77     }\r
78     \r
79     public void executePythonStatement(String statement) {\r
80         SCLContext sclContext = SCLContext.getCurrent();\r
81         \r
82         execute(() -> {\r
83                 SCLContext.push(sclContext);\r
84                 executePythonStatementImpl( contextID, statement );\r
85                 SCLContext.pop();\r
86         });\r
87         \r
88         for (Listener l : listeners) { l.updated(null); }\r
89     }\r
90 \r
91     // Setters\r
92     \r
93     public void setPythonBooleanVariable(String variableName, boolean value) {\r
94         checkValidName(variableName);\r
95         execute(() -> setPythonBooleanVariableImpl(contextID, variableName, value));\r
96         for (Listener l : listeners) { l.updated(variableName); }\r
97     }\r
98 \r
99     public void setPythonIntegerVariable(String variableName, int value) {\r
100         checkValidName(variableName);\r
101         execute(() -> setPythonLongVariableImpl(contextID, variableName, value));\r
102         for (Listener l : listeners) { l.updated(variableName); }\r
103     }\r
104     public void setPythonLongVariable(String variableName, long value) {\r
105         checkValidName(variableName);\r
106         execute(() -> setPythonLongVariableImpl(contextID, variableName, value));\r
107         for (Listener l : listeners) { l.updated(variableName); }\r
108     }\r
109     public void setPythonDoubleVariable(String variableName, double value) {\r
110         checkValidName(variableName);\r
111         execute(() -> setPythonDoubleVariableImpl(contextID, variableName, value));\r
112         for (Listener l : listeners) { l.updated(variableName); }\r
113     }\r
114     public void setPythonStringVariable(String variableName, String value) {\r
115         checkValidName(variableName);\r
116         execute(() -> setPythonStringVariableImpl(contextID, variableName, value));\r
117         for (Listener l : listeners) { l.updated(variableName); }\r
118     }\r
119     \r
120     public void setPythonBooleanArrayVariable(String variableName, boolean[] value) {\r
121         checkValidName(variableName);\r
122         execute(() -> setPythonBooleanArrayVariableImpl(contextID, variableName, value));\r
123         for (Listener l : listeners) { l.updated(variableName); }\r
124     }\r
125     public void setPythonIntegerArrayVariable(String variableName, int[] value) {\r
126         checkValidName(variableName);\r
127         execute(() -> setPythonIntegerArrayVariableImpl(contextID, variableName, value));\r
128         for (Listener l : listeners) { l.updated(variableName); }\r
129     }\r
130     public void setPythonLongArrayVariable(String variableName, long[] value) {\r
131         checkValidName(variableName);\r
132         execute(() -> setPythonLongArrayVariableImpl(contextID, variableName, value));\r
133         for (Listener l : listeners) { l.updated(variableName); }\r
134     }\r
135     public void setPythonDoubleArrayVariable(String variableName, double[] value) {\r
136         checkValidName(variableName);\r
137         execute(() -> setPythonDoubleArrayVariableImpl(contextID, variableName, value));\r
138         for (Listener l : listeners) { l.updated(variableName); }\r
139     }\r
140     public void setPythonStringArrayVariable(String variableName, String[] value) {\r
141         checkValidName(variableName);\r
142         execute(() -> setPythonStringArrayVariableImpl(contextID, variableName, value));\r
143         for (Listener l : listeners) { l.updated(variableName); }\r
144     }\r
145 \r
146     // Getters\r
147     \r
148     public boolean getPythonBooleanVariable(String variableName) {\r
149         checkValidName(variableName);\r
150         return getPythonBooleanVariableImpl(contextID, variableName);\r
151     }\r
152     public int getPythonIntegerVariable(String variableName) {\r
153         checkValidName(variableName);\r
154         long value = execute(() -> getPythonLongVariableImpl(contextID, variableName));\r
155         if (value > Integer.MAX_VALUE || value < Integer.MIN_VALUE)\r
156                 throw new RuntimeException("Python value not in integer range");\r
157         return (int) value;\r
158     }\r
159     public long getPythonLongVariable(String variableName) {\r
160         checkValidName(variableName);\r
161         return execute(() -> getPythonLongVariableImpl(contextID, variableName));\r
162     }\r
163     public double getPythonDoubleVariable(String variableName) {\r
164         checkValidName(variableName);\r
165         return execute(() -> getPythonDoubleVariableImpl(contextID, variableName));\r
166     }\r
167     public String getPythonStringVariable(String variableName) {\r
168         checkValidName(variableName);\r
169         return execute(() -> getPythonStringVariableImpl(contextID, variableName));\r
170     }\r
171     \r
172     public boolean[] getPythonBooleanArrayVariable(String variableName) {\r
173         checkValidName(variableName);\r
174         return execute(() -> getPythonBooleanArrayVariableImpl(contextID, variableName));\r
175     }\r
176     public int[] getPythonIntegerArrayVariable(String variableName) {\r
177         checkValidName(variableName);\r
178         return execute(() -> getPythonIntegerArrayVariableImpl(contextID, variableName));\r
179     }\r
180     public long[] getPythonLongArrayVariable(String variableName) {\r
181         checkValidName(variableName);\r
182         return execute(() -> getPythonLongArrayVariableImpl(contextID, variableName));\r
183     }\r
184     public double[] getPythonDoubleArrayVariable(String variableName) {\r
185         checkValidName(variableName);\r
186         return execute(() -> getPythonDoubleArrayVariableImpl(contextID, variableName));\r
187     }\r
188     public String[] getPythonStringArrayVariable(String variableName) {\r
189         checkValidName(variableName);\r
190         return execute(() -> getPythonStringArrayVariableImpl(contextID, variableName));\r
191     }\r
192     \r
193     public void setPythonNDArrayVariable(String variableName, NDArray value) {\r
194         checkValidName(variableName);\r
195         execute(() -> setPythonNDArrayVariableImpl(contextID, variableName, value));\r
196     }\r
197     public NDArray getPythonNDArrayVariable(String variableName) {\r
198         checkValidName(variableName);\r
199         return execute(() -> getPythonNDArrayVariableImpl(contextID, variableName));\r
200     }\r
201 \r
202     public Object getPythonVariantVariable(String variableName, Binding binding) {\r
203         checkValidName(variableName);\r
204         Object result = execute(() -> getPythonVariantVariableImpl(contextID, variableName));\r
205         try {\r
206                         return Bindings.OBJECT.getContent(result, binding);\r
207                 } catch (BindingException e) {\r
208                         throw new RuntimeException(e);\r
209                 }\r
210     }\r
211     \r
212     public Variant getPythonVariantVariable(String variableName) {\r
213         checkValidName(variableName);\r
214         return Variant.ofInstance(execute(() -> getPythonVariantVariableImpl(contextID, variableName)));\r
215     }\r
216 \r
217     public void setPythonVariantVariable(String variableName, Variant value) {\r
218         setPythonVariantVariable(variableName, value.getValue(), value.getBinding());\r
219     }\r
220     \r
221     public void setPythonVariantVariable(String variableName, Object value, Binding binding) {\r
222         checkValidName(variableName);\r
223         if (!binding.isInstance(value)) throw new IllegalArgumentException("Invalid object binding");\r
224         \r
225         execute(() -> setPythonVariantVariableImpl(contextID, variableName, value, binding));\r
226         \r
227         for (Listener l : listeners) { l.updated(variableName); }\r
228     }\r
229     \r
230     public VariableType getPythonVariableType(String variableName) {\r
231         checkValidName(variableName);\r
232         int code = execute(() -> getPythonVariableTypeImpl(contextID, variableName));\r
233         \r
234         VariableType[] values = VariableType.values();\r
235         if (code < 0 || code >= values.length)\r
236                 return VariableType.UNKNOWN;\r
237         \r
238         return values[code];\r
239     }\r
240     \r
241     public String[] getPythonVariableNames() {\r
242         return execute(() -> getPythonVariableNamesImpl(contextID));\r
243     }\r
244      \r
245     private static void checkValidName(String variableName) {\r
246         if (!namePattern.matcher(variableName).matches())\r
247             throw new IllegalArgumentException("Invalid Python variable name " + variableName);\r
248     }\r
249     \r
250     static void execute(Runnable job) {\r
251         try {\r
252             pythonExecutor.submit(job).get();\r
253         } catch (InterruptedException | ExecutionException e) {\r
254             throw new RuntimeException(e);\r
255         }\r
256     }\r
257     \r
258     static <V> V execute(Callable<V> job) {\r
259         try {\r
260             return pythonExecutor.submit(job).get();\r
261         } catch (InterruptedException | ExecutionException e) {\r
262             throw new RuntimeException(e);\r
263         }\r
264     }\r
265     \r
266     // Native function declarations\r
267     private static native long createContextImpl();\r
268     private static native void deleteContextImpl(long contextID);\r
269     \r
270     private static native int executePythonStatementImpl(long contextID, String statement);\r
271     \r
272     private static native void setPythonBooleanVariableImpl(long contextID, String variableName, boolean value);\r
273     private static native void setPythonLongVariableImpl(long contextID, String variableName, long value);\r
274     private static native void setPythonDoubleVariableImpl(long contextID, String variableName, double value);\r
275     private static native void setPythonStringVariableImpl(long contextID, String variableName, String value);\r
276     \r
277     private static native void setPythonBooleanArrayVariableImpl(long contextID, String variableName, boolean[] value);\r
278     private static native void setPythonIntegerArrayVariableImpl(long contextID, String variableName, int[] value);\r
279     private static native void setPythonLongArrayVariableImpl(long contextID, String variableName, long[] value);\r
280     private static native void setPythonDoubleArrayVariableImpl(long contextID, String variableName, double[] value);\r
281     private static native void setPythonStringArrayVariableImpl(long contextID, String variableName, String[] value);\r
282     \r
283     private static native boolean getPythonBooleanVariableImpl(long contextID, String variableName);\r
284     private static native long getPythonLongVariableImpl(long contextID, String variableName);\r
285     private static native double getPythonDoubleVariableImpl(long contextID, String variableName);\r
286     private static native String getPythonStringVariableImpl(long contextID, String variableName);\r
287     \r
288     private static native boolean[] getPythonBooleanArrayVariableImpl(long contextID, String variableName);\r
289     private static native long[] getPythonLongArrayVariableImpl(long contextID, String variableName);\r
290     private static native int[] getPythonIntegerArrayVariableImpl(long contextID, String variableName);\r
291     private static native double[] getPythonDoubleArrayVariableImpl(long contextID, String variableName);\r
292     private static native String[] getPythonStringArrayVariableImpl(long contextID, String variableName);\r
293     \r
294     private static native void setPythonNDArrayVariableImpl(long contextID, String variableName, NDArray value);\r
295     private static native NDArray getPythonNDArrayVariableImpl(long contextID, String variableName);\r
296     \r
297     private static native void setPythonVariantVariableImpl(long contextID, String variableName, Object value, Binding binding);\r
298     private static native Object getPythonVariantVariableImpl(long contextID, String variableName);\r
299     \r
300     private static native int getPythonVariableTypeImpl(long contextID, String variableName);\r
301     \r
302     private static native String[] getPythonVariableNamesImpl(long contextID);\r
303 }\r