]> gerrit.simantics Code Review - simantics/python.git/blob - org.simantics.pythonlink/src/org/simantics/pythonlink/variable/PythonNodeManager.java
Report and log failure of Python DLL loading
[simantics/python.git] / org.simantics.pythonlink / src / org / simantics / pythonlink / variable / PythonNodeManager.java
1 package org.simantics.pythonlink.variable;\r
2 \r
3 import java.util.ArrayList;\r
4 import java.util.Arrays;\r
5 import java.util.Collection;\r
6 import java.util.Collections;\r
7 import java.util.HashMap;\r
8 import java.util.HashSet;\r
9 import java.util.List;\r
10 import java.util.Map;\r
11 import java.util.Set;\r
12 import java.util.regex.Matcher;\r
13 import java.util.regex.Pattern;\r
14 \r
15 import org.simantics.databoard.Bindings;\r
16 import org.simantics.databoard.Datatypes;\r
17 import org.simantics.databoard.adapter.AdaptException;\r
18 import org.simantics.databoard.binding.Binding;\r
19 import org.simantics.databoard.binding.error.BindingException;\r
20 import org.simantics.databoard.binding.mutable.Variant;\r
21 import org.simantics.databoard.type.Datatype;\r
22 import org.simantics.databoard.type.MapType;\r
23 import org.simantics.databoard.type.RecordType;\r
24 import org.simantics.pythonlink.NDArray;\r
25 import org.simantics.pythonlink.PythonContext;\r
26 import org.simantics.pythonlink.PythonContext.Listener;\r
27 import org.simantics.pythonlink.PythonContext.VariableType;\r
28 import org.simantics.simulator.variable.Realm;\r
29 import org.simantics.simulator.variable.exceptions.NodeManagerException;\r
30 import org.simantics.simulator.variable.impl.AbstractNodeManager;\r
31 \r
32 public class PythonNodeManager extends AbstractNodeManager<PythonNode> {\r
33     PythonContext context;\r
34     \r
35     static Realm realm = new Realm() {\r
36         public void asyncExec(Runnable runnable) {\r
37             runnable.run();\r
38         };\r
39         \r
40         public void syncExec(Runnable runnable) {\r
41             runnable.run();\r
42         };\r
43     };\r
44     \r
45     Map<String, Set<Runnable>> listeners = new HashMap<>();\r
46     Map<String, PythonNode> nodes = new HashMap<>();\r
47     \r
48     PythonNode root = new PythonNode("/");\r
49     \r
50     static Pattern namePattern = Pattern.compile("/?([a-zA-Z_][a-zA-Z_0-9]*)");\r
51     \r
52     static MapType dictionaryType = new MapType(Datatypes.VARIANT, Datatypes.VARIANT);\r
53     static RecordType ndarrayType = (RecordType)Bindings.getBindingUnchecked(NDArray.class).type();\r
54     \r
55     public PythonNodeManager(PythonContext context) {\r
56         super();\r
57         this.context = context;\r
58         \r
59         context.addListener(new Listener() {\r
60             @Override\r
61             public void updated(String variableName) {\r
62                 if (variableName != null) {\r
63                     Set<Runnable> lis = listeners.get(variableName);\r
64                     if (lis != null) {\r
65                         for (Runnable r : lis)\r
66                             r.run();\r
67                     }\r
68                     lis = listeners.get("/");\r
69                     if (lis != null) {\r
70                         for (Runnable r : lis)\r
71                             r.run();\r
72                     }\r
73                 }\r
74                 else {\r
75                     Set<Runnable> allRunnables = new HashSet<>();\r
76                     for (Collection<Runnable> s : listeners.values())\r
77                         allRunnables.addAll(s);\r
78                     for (Runnable r : allRunnables)\r
79                         r.run();\r
80                 }\r
81             }\r
82             \r
83             @Override\r
84             public void closed() {\r
85                 nodes.clear();\r
86                 Set<Runnable> allRunnables = new HashSet<>();\r
87                 for (Collection<Runnable> s : listeners.values())\r
88                     allRunnables.addAll(s);\r
89                 for (Runnable r : allRunnables)\r
90                     r.run();\r
91             }\r
92         });\r
93     }\r
94     \r
95     @Override\r
96     public Realm getRealm() {\r
97         return realm;\r
98     }\r
99 \r
100     @Override\r
101     public String getName(PythonNode node) {\r
102         return node.getName();\r
103     }\r
104 \r
105     @Override\r
106     public void addNodeListener(PythonNode node, Runnable listener) {\r
107         synchronized(listeners) {\r
108             if (!listeners.containsKey(node.getName())) listeners.put(node.getName(), new HashSet<>());\r
109             listeners.get(node.getName()).add(listener);\r
110         }        \r
111     }\r
112 \r
113     @Override\r
114     public void removeNodeListener(PythonNode node, Runnable listener) {\r
115         synchronized(listeners) {\r
116             if (!listeners.containsKey(node.getName()))\r
117                 listeners.get(node.getName()).remove(listener);\r
118         }        \r
119     }\r
120 \r
121     @Override\r
122     public PythonNode getNode(String path) throws NodeManagerException {\r
123         if (!context.isOpen())\r
124             return null;\r
125         \r
126         if ("/".equals(path))\r
127             return root;        \r
128         \r
129         Matcher match = namePattern.matcher(path);\r
130         if (!match.matches())\r
131             return null;\r
132         \r
133         String name = match.group(1);\r
134         \r
135         if (nodes.containsKey(name))\r
136             return nodes.get(name);\r
137         \r
138         VariableType type = context.getPythonVariableType(name);\r
139         if (type == VariableType.NO_VARIABLE)\r
140             return null;\r
141         \r
142         PythonNode node = new PythonNode(name);\r
143         nodes.put(path, node);\r
144         \r
145         return node;\r
146     }\r
147 \r
148     @Override\r
149     public PythonNode getChild(PythonNode node, String name) throws NodeManagerException {\r
150         return null;\r
151     }\r
152 \r
153     @Override\r
154     public PythonNode getProperty(PythonNode node, String name) throws NodeManagerException {\r
155         if (node != root || !context.isOpen()) return null;\r
156         \r
157         return getNode(name);\r
158     }\r
159     \r
160     @Override\r
161     public List<String> getChildNames(PythonNode node) throws NodeManagerException {\r
162         return Collections.emptyList();\r
163     }\r
164 \r
165     @Override\r
166     public List<PythonNode> getChildren(PythonNode node) throws NodeManagerException {\r
167         return Collections.emptyList();\r
168     }\r
169     \r
170     @Override\r
171     public List<String> getPropertyNames(PythonNode node) throws NodeManagerException {\r
172         if (node != root || !context.isOpen()) return Collections.emptyList();        \r
173         return Arrays.asList(context.getPythonVariableNames());\r
174     }\r
175 \r
176     @Override\r
177     public List<PythonNode> getProperties(PythonNode node) throws NodeManagerException {\r
178         if (node != root || !context.isOpen()) return Collections.emptyList();\r
179         \r
180         String[] names = context.getPythonVariableNames();\r
181         List<PythonNode> result = new ArrayList<>(names.length);\r
182         \r
183         for (String name : names) {\r
184             result.add(getNode(name));\r
185         }\r
186         \r
187         return result;\r
188     }\r
189 \r
190     @Override\r
191     public Datatype getDatatype(PythonNode node) throws NodeManagerException {\r
192         String name = node.getName();\r
193         VariableType type;\r
194         try {\r
195             type = context.getPythonVariableType(name);\r
196         } catch (RuntimeException e) {\r
197             throw new NodeManagerException("Failed to get type of variable " + name, e);            \r
198         }\r
199         \r
200         switch (type) {\r
201         case NO_VARIABLE: return Datatypes.VOID;\r
202         case BOOLEAN: return Datatypes.BOOLEAN;\r
203         case LONG: return Datatypes.LONG;\r
204         case FLOAT: return Datatypes.DOUBLE;\r
205         case STRING: return Datatypes.STRING;\r
206         case BYTEARRAY: return Datatypes.BYTE_ARRAY;\r
207         case DICTIONARY: return dictionaryType;\r
208         case NDARRAY: return ndarrayType;\r
209         case SEQUENCE: return Datatypes.VARIANT_ARRAY;\r
210         case UNKNOWN: return Datatypes.VOID;\r
211         default: throw new RuntimeException("Unknown python variable type");\r
212         }\r
213     }\r
214 \r
215     @Override\r
216     public Variant getValue(PythonNode node, String propertyName) throws NodeManagerException {\r
217         if (node == root && context.isOpen())\r
218             return context.getPythonVariantVariable(propertyName);\r
219         \r
220         throw new NodeManagerException("No value available for " + node.getName() + "#" + propertyName);\r
221     }\r
222 \r
223     @Override\r
224     public Object getValue(PythonNode node, String propertyName, Binding binding)\r
225             throws NodeManagerException, BindingException {\r
226         Variant value = getValue(node, propertyName);\r
227         \r
228         try {\r
229             return value.getValue(binding);\r
230         } catch (AdaptException e) {\r
231             throw new BindingException(e);\r
232         }\r
233     }\r
234         \r
235     @Override\r
236     public Variant getValue(PythonNode node) throws NodeManagerException {\r
237         if (node == root || !context.isOpen())\r
238             throw new NodeManagerException("No value available for " + node.getName());\r
239         \r
240         String name = node.getName();\r
241         \r
242         try {\r
243             return context.getPythonVariantVariable(name);\r
244         } catch (RuntimeException e) {\r
245             throw new NodeManagerException("Failed to get value of variable " + name, e);\r
246         }\r
247     }\r
248     \r
249     @Override\r
250     public Object getValue(PythonNode node, Binding binding) throws NodeManagerException, BindingException {\r
251         Variant value = getValue(node);\r
252         \r
253         try {\r
254             return value.getValue(binding);\r
255         } catch (AdaptException e) {\r
256             throw new BindingException(e);\r
257         }\r
258     }\r
259 \r
260     @Override\r
261     public void setValue(PythonNode node, String propertyName, Object value, Binding binding)\r
262             throws NodeManagerException, BindingException {\r
263         if (node != root || !context.isOpen()) throw new NodeManagerException("No property " + node.getName() + "#" + propertyName);\r
264         \r
265         context.setPythonVariantVariable(propertyName, value, binding);        \r
266     }\r
267     \r
268     @Override\r
269     public void setValue(PythonNode node, Object value, Binding binding) throws NodeManagerException, BindingException {        \r
270         if (node == root || !context.isOpen()) throw new NodeManagerException("No property " + node.getName());\r
271         String name = node.getName();\r
272         \r
273         context.setPythonVariantVariable(name, value, binding);\r
274     }\r
275     \r
276     @Override\r
277     public Set<String> getClassifications(PythonNode node) throws NodeManagerException {\r
278         return Collections.emptySet();\r
279     }\r
280     \r
281 }\r