]> gerrit.simantics Code Review - simantics/fmil.git/blob - FMIL.java
b2928b9474c9bfc9974cb876dbdc56fca8e32ff8
[simantics/fmil.git] / FMIL.java
1 package org.simantics.fmil.core;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.io.RandomAccessFile;
6 import java.nio.channels.FileChannel;
7 import java.nio.channels.FileLock;
8 import java.util.ArrayList;
9 import java.util.HashSet;
10 import java.util.List;
11 import java.util.Set;
12 import java.util.UUID;
13
14 import org.eclipse.core.runtime.FileLocator;
15 import org.eclipse.core.runtime.Platform;
16 import org.osgi.framework.Bundle;
17 import org.simantics.Simantics;
18 import org.simantics.fmil.core.ExecEnvironment.ARCHType;
19 import org.simantics.fmil.core.ExecEnvironment.OSType;
20 import org.simantics.utils.FileUtils;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 import gnu.trove.list.array.TIntArrayList;
25 import gnu.trove.map.hash.TObjectIntHashMap;
26
27
28 public class FMIL {
29
30     private static final Logger LOGGER = LoggerFactory.getLogger(FMIL.class);
31
32     /**
33      * Static variables
34      */
35     private static int      OK                  = 0;
36     private static int      ERROR               = 1;
37     private static String   UNSATISFIED_LINK    = "Method not found. DLL might not be loaded properly.";    
38     private static String   TEMP_FMU_DIRECTORY_NAME = "fmil";    
39     public static String    TEMP_FMU_COMMON_DIRECTORY;  
40     public static String    LOCK_FILE_NAME      = "fmil.lock";
41
42     public static Object syncObject = new Object();
43
44     /**
45      * Static: load native libraries required for the FMU simulation to work.
46      */
47     static {
48         
49         File[] libraries = new File[2];
50
51         Bundle bundle = null;
52         
53         ExecEnvironment env = ExecEnvironment.calculate();
54         if (env.os == OSType.WINDOWS) {
55             if (env.arch == ARCHType.X86) {
56                 bundle = Platform.getBundle("org.simantics.fmil.win32");
57             } else if (env.arch == ARCHType.X86_64) {
58                 bundle = Platform.getBundle("org.simantics.fmil.win64");
59             }
60         }
61         
62         if (bundle != null) {
63             try{
64                 String root = FileLocator.getBundleFile(bundle).getAbsolutePath();
65 //                if (env.arch == ARCHType.X86_64) {
66 //                    File newFIle = new File(root, "libraries/libexpat.dll");
67 //                    System.load(newFIle.getAbsolutePath());
68 //                }
69 //                libraries[0] = new File(root, "libraries/zlibwapi.dll");
70 //                libraries[1] = new File(root, "libraries/miniunz.dll");
71                 libraries[0] = new File(root, "libraries/fmilib_shared.dll");
72                 libraries[1] = new File(root, "libraries/FMUSimulator.dll");
73             }
74             catch (Exception e) {
75                 e.printStackTrace();
76             }
77         }
78
79         for(File library : libraries) {
80             if(library == null) {
81                 System.err.println("FMU library not loaded. FMU simulation not working.");
82                 continue;
83             } else if(!library.isFile()) {
84                 System.err.println(library.getAbsolutePath() + " not found");
85             } else {
86                 try {
87                     System.load(library.getAbsolutePath());
88                 } catch (Throwable t) {
89                     System.err.println(t.getMessage());
90                 }
91             } 
92         }
93     }
94
95     /**
96      * Static: initialize fmu temp folder
97      */
98     static {
99         File dir = Simantics.getTemporaryDirectory(TEMP_FMU_DIRECTORY_NAME);
100         TEMP_FMU_COMMON_DIRECTORY = dir.getAbsolutePath(); 
101     }
102
103
104     private String fmuDir;
105     private int id;
106
107     public String TEMP_FOLDER_1;
108     public String TEMP_FOLDER_2;
109     public String TEMP_FMU_DIRECTORY;
110     private String dirName;
111
112         private String[] variableNames;
113         private String[] variableDescriptions;
114         private String[] variableDeclaredTypes;
115         private int[] variableReferences;
116         private int[] variableTypes;
117         private int[] variableCausalities;
118         private int[] variableVariabilities;
119         
120         private String[] declaredTypes;
121         private String[] declaredTypeDescriptions;
122         private String[] declaredTypeQuantities;
123         private String[] declaredTypeUnits;
124         
125         private TObjectIntHashMap<String> variableMap = new TObjectIntHashMap<String>();
126         
127         private Set<String> subscriptionSet = new HashSet<String>();
128         private TIntArrayList subscription = new TIntArrayList();
129         private ArrayList<String> subscribedNames = new ArrayList<String>();
130         
131         public List<String> getSubscribedNames() {
132                 return subscribedNames;
133         }
134         
135         public boolean subscribe(String name) throws FMILException {
136                 // Safety check
137                 int vr = variableMap.get(name);
138                 if(vr == 0) return false;
139                 if(!subscriptionSet.add(name)) return false;
140                 subscribedNames.add(name);
141                 System.err.println("subscribed : " + name + " => " + subscribedNames.size());
142                 subscription.add(vr);
143                 subscribe(new int[] { vr });
144                 return true;
145         }
146
147     public FMIL() {
148         // Create a directory for this control
149         File tempDir = new File(TEMP_FMU_COMMON_DIRECTORY, UUID.randomUUID().toString());
150         tempDir.mkdir();
151         TEMP_FMU_DIRECTORY = tempDir.getAbsolutePath();
152
153         // Create two directories inside the temp directory for this control
154         dirName = UUID.randomUUID().toString();
155         File fmuDir = new File(TEMP_FMU_DIRECTORY, dirName);
156         fmuDir.mkdir();
157
158         TEMP_FOLDER_1 = fmuDir.toString();
159         TEMP_FOLDER_2 = fmuDir.toString() + "_2";
160
161         // Lock fmu directory in temp directory
162         lockFMUDirectory();
163     }
164
165     public int getModelIDNew() {
166         return id;
167     }
168
169     public String getModelID() {
170         return dirName;
171     }
172
173     public String getFmuDir() {
174         return fmuDir;
175     }
176
177     /**
178      * Load fmu from a given file path. Releases the (possible) previously
179      * loaded fmu.
180      * 
181      * @param path absolute file path for fmu file
182      * @throws FMILException
183      */
184     private int fmuN = 0;
185     private boolean fmuLoaded = false;
186     public void loadFMUFile(String path) throws FMILException {
187
188         synchronized(syncObject) {
189
190             if(fmuN % 2 == 0) {
191                 fmuDir = TEMP_FOLDER_1;
192                 fmuN++;
193             } else {
194                 fmuDir = TEMP_FOLDER_2;
195                 fmuN = 0;
196             }
197
198             File tempDir = new File(fmuDir);
199             if(tempDir.isDirectory()) {
200                 try {
201                     FileUtils.deleteAll(tempDir);
202                 } catch (IOException e) {
203                     throw new FMILException("Could not create temp folder for fmu");
204                 }
205                 tempDir.mkdir();
206             } else {
207                 tempDir.mkdir();
208             }
209
210
211             try {
212                 String tmpPath = tempDir.getAbsolutePath();
213                 if(!tmpPath.endsWith("\\"))
214                     tmpPath = tmpPath + "\\";
215                 id = loadFMUFile_(path, tmpPath);
216                 
217                 getAllVariables();
218                 getAllVariableReferences();
219                 
220                 for(int i=0;i<variableNames.length;i++) {
221                         variableMap.put(variableNames[i], variableReferences[i]);
222                 }
223
224                 fmuLoaded = true;
225             } catch (UnsatisfiedLinkError err) {
226                 throw new FMILException(UNSATISFIED_LINK, err);
227             } catch (Exception e) {
228                 throw new FMILException(e.getMessage());
229             }
230         }
231     }
232
233     private native int loadFMUFile_(String path, String toDir);
234
235     /**
236      * Set a step length for simulation
237      * 
238      * @param step Step length for simulation
239      * @throws FMILException
240      */
241     public void setStepLength(double step) throws FMILException {
242         synchronized(syncObject) {
243
244             try {
245                 int ret = setStepLength_(getModelIDNew(), step);
246                 if(ret != OK)
247                     LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
248
249             } catch (UnsatisfiedLinkError err) {
250                 throw new FMILException(UNSATISFIED_LINK);
251             } catch (Exception e) {
252                 throw new FMILException(e.getMessage());
253             }
254         }
255     }
256
257     private native int setStepLength_(int id, double step);
258
259     /**
260      * Instantiates a simulation. 
261      * <p>
262      * Make sure that an FMU is loaded first.
263      * @throws FMILException
264      */
265     public void instantiateSimulation() throws FMILException {
266         synchronized(syncObject) {
267
268             try {
269
270                 int ret = instantiateSimulation_(getModelIDNew()); 
271                 if(ret != OK)
272                     LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
273
274             } catch (FMILException e) {
275                 throw e;
276             } catch (UnsatisfiedLinkError err) {
277                 throw new FMILException(UNSATISFIED_LINK);
278             } catch (Exception e) {
279                 throw new FMILException(e.getMessage());
280             }
281         }
282     }
283
284     private native int instantiateSimulation_(int id) throws FMILException;
285
286     
287     /**
288      * Initializes a simulation. 
289      * <p>
290      * Make sure that simulation is instantiated first!
291      * @throws FMILException
292      */
293     public void initializeSimulation() throws FMILException {
294         synchronized(syncObject) {
295
296             try {
297
298                 int ret = initializeSimulation_(getModelIDNew()); 
299                 if(ret != OK)
300                     LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
301
302             } catch (FMILException e) {
303                 throw e;
304             } catch (UnsatisfiedLinkError err) {
305                 throw new FMILException(UNSATISFIED_LINK);
306             } catch (Exception e) {
307                 throw new FMILException(e.getMessage());
308             }
309         }
310     }
311
312     private native int initializeSimulation_(int id) throws FMILException;
313
314     /**
315      * Subscribe a set of variables from a loaded simulation.
316      * <p>
317      * Make sure that an FMU is loaded first.
318      * @param variables Array of variables
319      * @throws FMILException
320      */
321     public void subscribe(int[] variables) throws FMILException {
322         synchronized(syncObject) {
323
324             try {
325
326                 int ret = subscribe_(getModelIDNew(), variables); 
327                 if(ret != OK)
328                     LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
329
330             } catch (UnsatisfiedLinkError err) {
331                 throw new FMILException(UNSATISFIED_LINK);
332             } catch (Exception e) {
333                 throw new FMILException(e.getMessage());
334             }
335         }
336     }
337
338     private native int subscribe_(int id, int[] variables);
339
340     /**
341      * Set a new (Real, double) value for a variable. If the variable is a 
342      * parameter, the change is effective immediately.
343      *  
344      * @param name Variable
345      * @param value New (Real, double) value
346      * @throws FMILException
347      */
348     public void setRealValue(String name, double value) throws FMILException {
349         
350         synchronized(syncObject) {
351
352             try {
353
354                 int ret = setRealValue_(getModelIDNew(), variableMap.get(name), value); 
355                 if(ret != OK)
356                     LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
357
358             } catch (FMILException e) {
359                 throw e;
360             } catch (UnsatisfiedLinkError err) {
361                 throw new FMILException(UNSATISFIED_LINK);
362             } catch (Exception e) {
363                 throw new FMILException(e.getMessage());
364             }
365             
366         }
367         
368     }
369
370     public void setRealValue(int variableReference, double value) throws FMILException {
371         
372         synchronized(syncObject) {
373
374             try {
375
376                 int ret = setRealValue_(getModelIDNew(), variableReference, value); 
377                 if(ret != OK)
378                     LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
379
380             } catch (FMILException e) {
381                 throw e;
382             } catch (UnsatisfiedLinkError err) {
383                 throw new FMILException(UNSATISFIED_LINK);
384             } catch (Exception e) {
385                 throw new FMILException(e.getMessage());
386             }
387             
388         }
389         
390     }
391
392     private native int setRealValue_(int id, int variableReference, double value) throws FMILException;
393
394 //    /**
395 //     * Set a new (integer) value for a variable. If the variable is a 
396 //     * parameter, the change is effective immediately.
397 //     *  
398 //     * @param name Variable
399 //     * @param value New (integer) value
400 //     * @throws FMILException
401 //     */
402 //    public void setIntegerValue(String name, int value) throws FMILException {
403 //        synchronized(syncObject) {
404 //
405 //            try {
406 //
407 //                int ret = setIntegerValue_(getModelID(), name, value); 
408 //                if(ret == ERROR)
409 //                    throw new FMILException(getLastErrorMessage());
410 //
411 //            } catch (UnsatisfiedLinkError err) {
412 //                throw new FMILException(UNSATISFIED_LINK);
413 //            } catch (Exception e) {
414 //                throw new FMILException(e.getMessage());
415 //            }
416 //        }
417 //    }
418 //    private native int setIntegerValue_(String id, String name, int value);
419 //
420 //    /**
421 //     * Set a new (boolean) value for a variable. If the variable is a 
422 //     * parameter, the change is effective immediately.
423 //     *  
424 //     * @param name Variable
425 //     * @param value New (boolean) value
426 //     * @throws FMILException
427 //     */
428 //    public void setBooleanValue(String name, boolean value) throws FMILException {
429 //        synchronized(syncObject) {
430 //
431 //            try {
432 //
433 //                int ret = setBooleanValue_(getModelID(), name, value); 
434 //                if(ret == ERROR)
435 //                    throw new FMILException(getLastErrorMessage());
436 //
437 //            } catch (UnsatisfiedLinkError err) {
438 //                throw new FMILException(UNSATISFIED_LINK);
439 //            } catch (Exception e) {
440 //                throw new FMILException(e.getMessage());
441 //            }
442 //        }
443 //    }
444 //    private native int setBooleanValue_(String id, String name, boolean value);
445 //
446 //    public void setTime(double time) throws FMILException {
447 //        synchronized(syncObject) {
448 //
449 //            try {
450 //
451 //                int ret = setTime_(getModelID(), time); 
452 //                if(ret == ERROR)
453 //                    throw new FMILException(getLastErrorMessage());
454 //
455 //            } catch (UnsatisfiedLinkError err) {
456 //                throw new FMILException(UNSATISFIED_LINK);
457 //            } catch (Exception e) {
458 //                throw new FMILException(e.getMessage());
459 //            }
460 //        }
461 //    }
462 //    private native int setTime_(String id, double time);
463
464     /**
465      * Simulate one step forward. The step length can be set with
466      * setStepLength()
467      * 
468      * @throws FMILException
469      */
470     public void simulateStep() throws FMILException {
471         synchronized(syncObject) {
472
473             try {
474
475                 int ret = simulateStep_(getModelIDNew()); 
476                 if(ret != OK)
477                     LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
478
479             } catch (FMILException e) {
480                 throw e;
481             } catch (UnsatisfiedLinkError err) {
482                 throw new FMILException(UNSATISFIED_LINK);
483             } catch (Exception e) {
484                 throw new FMILException(e.getMessage());
485             }
486         }
487     }
488     private native int simulateStep_(int id) throws FMILException;
489
490     /**
491      * Get an array containing the current values for subscribed variables. The
492      * values are in the same order as in the subscription.
493      * 
494      * @param results An array the size of subscribed results
495      * @return
496      */
497     public double[] getSubscribedResults() throws FMILException {
498         synchronized(syncObject) {
499
500             try {
501
502                 double[] results = new double[subscription.size()];
503                 return getSubscribedResults_(getModelIDNew(), results);
504
505             } catch (UnsatisfiedLinkError err) {
506                 throw new FMILException(UNSATISFIED_LINK);
507             } catch (Exception e) {
508                 throw new FMILException(e.getMessage());
509             }
510         }
511     }
512
513     private native double[] getSubscribedResults_(int id, double[] results);
514     
515
516     /**
517      * Unload FMU and the dll:s that it requires.
518      * <p>
519      * To be called after all FMU simulations are ended. 
520      * If the fmu is loaded again / changed, call to loadFMUFile is sufficient. loadFMUFile 
521      * releases the previous fmu.dll  
522      * 
523      * @throws FMILException
524      */
525     public void unloadFMU() throws FMILException {
526         synchronized(syncObject) {
527
528             try {
529
530                 unlockFMUDirectory();
531                 if(fmuLoaded) {
532                     int ret = unloadFMU_(getModelIDNew()); 
533                     if(ret != OK)
534                         LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
535                     fmuLoaded = false;
536                 }
537                 removeFMUDirectoryContents();
538
539             } catch (FMILException e) {
540                 throw e;
541             } catch (UnsatisfiedLinkError err) {
542                 throw new FMILException(UNSATISFIED_LINK);
543             } catch (Exception e) {
544                 throw new FMILException(e.getMessage());
545             }
546         }
547     }
548     private native int unloadFMU_(int id) throws FMILException;
549     
550 //    /**
551 //     * Checks if fmu has been initialized
552 //     * @return current simulation time
553 //     */
554 //    public boolean isInitialized() throws FMILException {
555 //        synchronized(syncObject) {
556 //            try {
557 //                return isInitialized_(getModelID());
558 //            } catch (UnsatisfiedLinkError err) {
559 //                throw new FMILException(UNSATISFIED_LINK);
560 //            } catch (Exception e) {
561 //                throw new FMILException(e.getMessage());
562 //            }
563 //        }
564 //    }
565 //
566 //    private native boolean isInitialized_(String id);
567 //
568     /**
569      * Get the current simulation time
570      * @return current simulation time
571      */
572     public double getTime() throws FMILException {
573         synchronized(syncObject) {
574
575             try {
576
577                 return getTime_(getModelIDNew());
578
579             } catch (UnsatisfiedLinkError err) {
580                 throw new FMILException(UNSATISFIED_LINK);
581             } catch (Exception e) {
582                 throw new FMILException(e.getMessage());
583             }
584         }
585     }
586
587     private native double getTime_(int id);
588
589     /**
590      * Get all variables in a loaded model
591      * @return all variables in a loaded model
592      */
593     public String[] getAllVariables() throws FMILException {
594         synchronized(syncObject) {
595
596             try {
597
598                 if(variableNames == null) {
599                         variableNames = getAllVariables_(getModelIDNew());
600                 }
601                 return variableNames;
602
603             } catch (UnsatisfiedLinkError err) {
604                 throw new FMILException(UNSATISFIED_LINK);
605             } catch (Exception e) {
606                 throw new FMILException(e.getMessage());
607             }
608         }
609     }
610
611     private native String[] getAllVariables_(int id);
612
613     public String[] getAllVariableDescriptions() throws FMILException {
614         synchronized(syncObject) {
615
616             try {
617
618                 if(variableDescriptions == null) {
619                         variableDescriptions = getAllVariableDescriptions_(getModelIDNew());
620                 }
621                 return variableDescriptions;
622
623             } catch (UnsatisfiedLinkError err) {
624                 throw new FMILException(UNSATISFIED_LINK);
625             } catch (Exception e) {
626                 throw new FMILException(e.getMessage());
627             }
628         }
629     }
630
631     private native String[] getAllVariableDescriptions_(int id);
632     
633     public String[] getAllVariableDeclaredTypes() throws FMILException {
634         synchronized(syncObject) {
635
636             try {
637
638                 if(variableDeclaredTypes == null) {
639                         variableDeclaredTypes = getAllVariableDeclaredTypes_(getModelIDNew());
640                 }
641                 return variableDeclaredTypes;
642
643             } catch (UnsatisfiedLinkError err) {
644                 throw new FMILException(UNSATISFIED_LINK);
645             } catch (Exception e) {
646                 throw new FMILException(e.getMessage());
647             }
648         }
649     }
650
651     private native String[] getAllVariableDeclaredTypes_(int id);
652
653     public int[] getAllVariableReferences() throws FMILException {
654         synchronized(syncObject) {
655
656             try {
657
658                 if(variableReferences == null) {
659                         variableReferences = getAllVariableReferences_(getModelIDNew(), new int[variableNames.length]); 
660                 }
661                 return variableReferences;
662
663             } catch (UnsatisfiedLinkError err) {
664                 throw new FMILException(UNSATISFIED_LINK);
665             } catch (Exception e) {
666                 throw new FMILException(e.getMessage());
667             }
668         }
669     }
670
671     private native int[] getAllVariableReferences_(int id, int[] array);
672
673     public int[] getAllVariableTypes() throws FMILException {
674         synchronized(syncObject) {
675
676             try {
677
678                 if(variableTypes == null) {
679                         variableTypes = getAllVariableTypes_(getModelIDNew(), new int[variableNames.length]); 
680                 }
681                 return variableTypes;
682
683             } catch (UnsatisfiedLinkError err) {
684                 throw new FMILException(UNSATISFIED_LINK);
685             } catch (Exception e) {
686                 throw new FMILException(e.getMessage());
687             }
688         }
689     }
690
691     private native int[] getAllVariableTypes_(int id, int[] array);
692
693     public int[] getAllVariableCausalities() throws FMILException {
694         synchronized(syncObject) {
695
696             try {
697
698                 if(variableCausalities == null) {
699                         variableCausalities = getAllVariableCausalities_(getModelIDNew(), new int[variableNames.length]); 
700                 }
701                 return variableCausalities;
702
703             } catch (UnsatisfiedLinkError err) {
704                 throw new FMILException(UNSATISFIED_LINK);
705             } catch (Exception e) {
706                 throw new FMILException(e.getMessage());
707             }
708         }
709     }
710
711     private native int[] getAllVariableCausalities_(int id, int[] array);
712
713     public int[] getAllVariableVariabilities() throws FMILException {
714         synchronized(syncObject) {
715
716             try {
717
718                 if(variableVariabilities == null) {
719                         variableVariabilities = getAllVariableVariabilities_(getModelIDNew(), new int[variableNames.length]); 
720                 }
721                 return variableVariabilities;
722
723             } catch (UnsatisfiedLinkError err) {
724                 throw new FMILException(UNSATISFIED_LINK);
725             } catch (Exception e) {
726                 throw new FMILException(e.getMessage());
727             }
728         }
729     }
730
731     private native int[] getAllVariableVariabilities_(int id, int[] array);
732
733     /**
734      * Get all variables in a loaded model
735      * @return all variables in a loaded model
736      */
737     public String[] getAllDeclaredTypes() throws FMILException {
738         synchronized(syncObject) {
739
740             try {
741
742                 if(declaredTypes == null) {
743                         declaredTypes = getAllDeclaredTypes_(getModelIDNew());
744                 }
745                 return declaredTypes;
746
747             } catch (UnsatisfiedLinkError err) {
748                 throw new FMILException(UNSATISFIED_LINK);
749             } catch (Exception e) {
750                 throw new FMILException(e.getMessage());
751             }
752         }
753     }
754
755     private native String[] getAllDeclaredTypes_(int id);
756     
757     public String[] getAllDeclaredTypeDescriptions() throws FMILException {
758         synchronized(syncObject) {
759
760             try {
761
762                 if(declaredTypeDescriptions == null) {
763                         declaredTypeDescriptions = getAllDeclaredTypeDescriptions_(getModelIDNew());
764                 }
765                 return declaredTypeDescriptions;
766
767             } catch (UnsatisfiedLinkError err) {
768                 throw new FMILException(UNSATISFIED_LINK);
769             } catch (Exception e) {
770                 throw new FMILException(e.getMessage());
771             }
772         }
773     }
774
775     private native String[] getAllDeclaredTypeDescriptions_(int id);
776     
777     public String[] getAllDeclaredTypeQuantities() throws FMILException {
778         synchronized(syncObject) {
779
780             try {
781
782                 if(declaredTypeQuantities == null) {
783                         declaredTypeQuantities = getAllDeclaredTypeQuantities_(getModelIDNew());
784                 }
785                 return declaredTypeQuantities;
786
787             } catch (UnsatisfiedLinkError err) {
788                 throw new FMILException(UNSATISFIED_LINK);
789             } catch (Exception e) {
790                 throw new FMILException(e.getMessage());
791             }
792         }
793     }
794
795     private native String[] getAllDeclaredTypeQuantities_(int id);
796
797     public String[] getAllDeclaredTypeUnits() throws FMILException {
798         synchronized(syncObject) {
799
800             try {
801
802                 if(declaredTypeUnits == null) {
803                         declaredTypeUnits = getAllDeclaredTypeUnits_(getModelIDNew());
804                 }
805                 return declaredTypeUnits;
806
807             } catch (UnsatisfiedLinkError err) {
808                 throw new FMILException(UNSATISFIED_LINK);
809             } catch (Exception e) {
810                 throw new FMILException(e.getMessage());
811             }
812         }
813     }
814
815     private native String[] getAllDeclaredTypeUnits_(int id);
816     
817     
818 //
819 //    /**
820 //     * Get all variables from model that match the filter (and time variable)
821 //     * 
822 //     * @param regexp Regular expression filter
823 //     * @return An array of variable names that match regexp filter (and time-variable)
824 //     * @throws FMILException
825 //     */
826 //    public String[] filterVariables(String regexp) throws FMILException {       
827 //        synchronized(syncObject) {
828 //            try {
829 //
830 //                return filterVariables_(getModelID(), regexp + "|time");
831 //
832 //            } catch (UnsatisfiedLinkError err) {
833 //                throw new FMILException(UNSATISFIED_LINK);
834 //            } catch (Exception e) {
835 //                throw new FMILException(e.getMessage());
836 //            }
837 //        }
838 //    }
839 //
840 //    private native String[] filterVariables_(String id, String regexp);
841 ////
842 //    /**
843 //     * Get the last error message
844 //     * @return Last error message
845 //     */
846 //    public String getLastErrorMessage() throws FMILException {
847 //        synchronized(syncObject) {
848 //
849 //            try {
850 //
851 //              return "err";
852 //                //return getLastErrorMessage_(getModelID());
853 //
854 //            } catch (UnsatisfiedLinkError err) {
855 //                throw new FMILException(UNSATISFIED_LINK);
856 //            } catch (Exception e) {
857 //                throw new FMILException(e.getMessage());
858 //            }
859 //        }
860 //    }
861 //
862 //    private native String getLastErrorMessage_(String id);
863
864     /**
865      * Get a real (double) value for variable
866      * @param name Name of the variable
867      * @return value
868      * @throws FMILException
869      */
870     public double getRealValue(String name) throws FMILException {
871         synchronized(syncObject) {
872
873             try {
874                 // TODO: printtaa id ja name, jotta saadaan virheessä kiinni
875                 double result = getRealValue_(getModelIDNew(), variableMap.get(name));
876                 System.err.println("getRealValue " + name + " = " + result);
877                 return  result;
878             } catch (UnsatisfiedLinkError err) {
879                 throw new FMILException(UNSATISFIED_LINK);
880             } catch (Exception e) {
881                 throw new FMILException(e.getMessage());
882             }
883         }
884     }
885
886     private native double getRealValue_(int id, int variableReference);
887
888 //    /**
889 //     * Get a string value for variable
890 //     * @param name Name of the variable
891 //     * @return value
892 //     * @throws FMILException
893 //     */
894 //    public String getStringValue(String name) throws FMILException {
895 //        synchronized(syncObject) {
896 //
897 //            try {
898 //                return getStringValue_(getModelID(), name); 
899 //            } catch (UnsatisfiedLinkError err) {
900 //                throw new FMILException(UNSATISFIED_LINK);
901 //            } catch (Exception e) {
902 //                throw new FMILException(e.getMessage());
903 //            }
904 //        }
905 //    }
906 //
907 //    private native String getStringValue_(String id, String name);
908 //
909 //    /**
910 //     * Get an integer value for variable
911 //     * @param name Name of the variable
912 //     * @return value
913 //     * @throws FMILException
914 //     */
915 //    public int getIntegerValue(String name) throws FMILException {
916 //        synchronized(syncObject) {
917 //
918 //            try {
919 //                return getIntegerValue_(getModelID(), name); 
920 //            } catch (UnsatisfiedLinkError err) {
921 //                throw new FMILException(UNSATISFIED_LINK);
922 //            } catch (Exception e) {
923 //                throw new FMILException(e.getMessage());
924 //            }
925 //        }
926 //    }
927 //
928 //    private native int getIntegerValue_(String id, String name);
929 //
930 //    /**
931 //     * Get a real (double) value for variable
932 //     * @param name Name of the variable
933 //     * @return value
934 //     * @throws FMILException
935 //     */
936 //    public boolean getBooleanValue(String name) throws FMILException {
937 //        synchronized(syncObject) {
938 //
939 //            try {
940 //                return getBooleanValue_(getModelID(), name); 
941 //            } catch (UnsatisfiedLinkError err) {
942 //                throw new FMILException(UNSATISFIED_LINK);
943 //            } catch (Exception e) {
944 //                throw new FMILException(e.getMessage());
945 //            }
946 //        }
947 //    }
948 //
949 //    private native boolean getBooleanValue_(String id, String name);
950
951     private FileChannel channel; 
952     private FileLock lock;
953
954     @SuppressWarnings("resource")
955     private boolean lockFMUDirectory() {
956
957         try {
958             // Get a file channel for the lock file
959             File lockFile = new File(TEMP_FMU_DIRECTORY, LOCK_FILE_NAME);
960             if(!lockFile.isFile())
961                 lockFile.createNewFile();
962
963             channel = new RandomAccessFile(lockFile, "rw").getChannel();
964
965             // Use the file channel to create a lock on the file.
966             // This method blocks until it can retrieve the lock.
967             lock = channel.lock();
968
969             //          // Try acquiring the lock without blocking. This method returns
970             //          // null or throws an exception if the file is already locked.
971             //          try {
972             //              lock = channel.tryLock();
973             //          } catch (OverlappingFileLockException e) {
974             //              // File is already locked in this thread or virtual machine
975             //          }
976         } catch (IOException e) {
977             return false;
978         }
979
980         return true;
981     }
982
983     private boolean unlockFMUDirectory() {
984         try {
985             // Release the lock
986             if(lock != null)
987                 lock.release();
988
989             // Close the file
990             if(channel != null)
991                 channel.close();
992         } catch (IOException e) {
993             return false;
994         }
995         return true;
996     }
997
998     private boolean removeFMUDirectoryContents() {
999         // Remove contents
1000         try {
1001             File tempDir = new File(TEMP_FMU_DIRECTORY);
1002             FileUtils.deleteAll(tempDir);
1003             tempDir.delete();
1004         } catch (IOException e) {
1005             return false;
1006         }
1007         return true;
1008     }
1009     
1010     @Override
1011     protected void finalize() throws Throwable {
1012         try {
1013             unloadFMU();
1014         } catch (Throwable t) {
1015             LOGGER.error("Could not unload native FMU!", t);
1016         } finally {
1017             super.finalize();
1018         }
1019     }
1020 }