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