]> gerrit.simantics Code Review - simantics/fmil.git/blob - org.simantics.fmil.core/src/org/simantics/fmil/core/FMIL.java
Default values for FMI values is NaN in FMIL.java
[simantics/fmil.git] / org.simantics.fmil.core / src / org / simantics / fmil / core / 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.net.URL;
7 import java.nio.channels.FileChannel;
8 import java.nio.channels.FileLock;
9 import java.nio.file.Paths;
10 import java.util.ArrayList;
11 import java.util.Arrays;
12 import java.util.HashSet;
13 import java.util.List;
14 import java.util.Set;
15 import java.util.UUID;
16
17 import org.eclipse.core.runtime.FileLocator;
18 import org.eclipse.core.runtime.Path;
19 import org.eclipse.core.runtime.Platform;
20 import org.osgi.framework.Bundle;
21 import org.simantics.fmil.core.ExecEnvironment.OSType;
22 import org.simantics.utils.FileUtils;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25
26 import gnu.trove.list.array.TIntArrayList;
27 import gnu.trove.map.hash.TObjectIntHashMap;
28
29
30 public class FMIL {
31
32     private static final Logger LOGGER = LoggerFactory.getLogger(FMIL.class);
33
34     /**
35      * Static variables
36      */
37     private static int      OK                  = 0;
38     private static int      ERROR               = 1;
39     private static String   UNSATISFIED_LINK    = "Method not found. DLL might not be loaded properly.";
40     public static final String TEMP_FMU_DIRECTORY_NAME = "fmil";
41     public static String    TEMP_FMU_COMMON_DIRECTORY;
42     public static String    LOCK_FILE_NAME      = "fmil.lock";
43
44     public static Object syncObject = new Object();
45
46     /**
47      * Static: load native libraries required for the FMU simulation to work.
48      */
49     static {
50
51         File[] libraries = new File[2];
52
53         ExecEnvironment env = ExecEnvironment.calculate();
54
55         try {
56             URL sharedFMILIBUrl = null;
57             URL simulatorFMIUrl = null;
58             Bundle b = Platform.getBundle("org.simantics.fmil.core");
59
60             if (env.os == OSType.WINDOWS) {
61                 sharedFMILIBUrl = FileLocator.find(b, new Path("libraries/fmilib_shared.dll"), null);
62                 simulatorFMIUrl = FileLocator.find(b, new Path("libraries/FMUSimulator.dll"), null);
63             } else if(env.os == OSType.LINUX) {
64                 sharedFMILIBUrl = FileLocator.find(b, new Path("libraries/libfmilib_shared.so"), null);
65                 simulatorFMIUrl = FileLocator.find(b, new Path("libraries/libFMUSimulator.so"), null);
66             }
67
68             libraries[0] = new File(FileLocator.toFileURL(sharedFMILIBUrl).getPath());
69             libraries[1] = new File(FileLocator.toFileURL(simulatorFMIUrl).getPath());
70         } catch (Exception e) {
71             LOGGER.error("Failed to resolve native FMU simulation library for execution environment {}.{}", env.os, env.arch, e);
72         }
73
74         for(File library : libraries) {
75             if(library == null) {
76                 System.err.println("FMU library not loaded. FMU simulation not working.");
77                 continue;
78             } else if(!library.isFile()) {
79                 System.err.println(library.getAbsolutePath() + " not found");
80             } else {
81                 try {
82                     System.load(library.getAbsolutePath());
83                 } catch (Throwable t) {
84                     System.err.println(t.getMessage());
85                 }
86             } 
87         }
88     }
89
90     /**
91      * Static: initialize fmu temp folder from current working directory
92      */
93     static {
94         TEMP_FMU_COMMON_DIRECTORY = Paths.get(".").toAbsolutePath().normalize().toString();
95     }
96     
97     public static void setTempFMUCommonDir(File dir) {
98         TEMP_FMU_COMMON_DIRECTORY = dir.getAbsolutePath(); 
99     }
100
101     private String fmuDir;
102     private int id;
103
104     public String TEMP_FOLDER_1;
105     public String TEMP_FOLDER_2;
106     public String TEMP_FMU_DIRECTORY;
107     private String dirName;
108
109         private String[] variableNames;
110         private String[] variableDescriptions;
111         private String[] variableDeclaredTypes;
112         private int[] variableReferences;
113         private int[] variableTypes;
114         private int[] variableCausalities;
115         private int[] variableVariabilities;
116         
117         private String[] declaredTypes;
118         private String[] declaredTypeDescriptions;
119         private String[] declaredTypeQuantities;
120         private String[] declaredTypeUnits;
121         
122         private TObjectIntHashMap<String> variableMap = new TObjectIntHashMap<String>();
123         
124         private Set<String> subscriptionSet = new HashSet<String>();
125         private TIntArrayList subscription = new TIntArrayList();
126         private ArrayList<String> subscribedNames = new ArrayList<String>();
127         
128         public List<String> getSubscribedNames() {
129                 return subscribedNames;
130         }
131         
132         public boolean subscribe(String name) throws FMILException {
133                 synchronized(syncObject) {
134                         // Safety check
135                         int vr = variableMap.get(name);
136                         if(vr == 0) return false;
137                         if(!subscriptionSet.add(name)) return false;
138                         subscribedNames.add(name);
139                         subscription.add(vr);
140                         subscribe(new int[] { vr });
141                         return true;
142                 }
143         }
144
145     public FMIL() {
146         // Create a directory for this control
147         File tempDir = new File(TEMP_FMU_COMMON_DIRECTORY, UUID.randomUUID().toString());
148         tempDir.mkdir();
149         TEMP_FMU_DIRECTORY = tempDir.getAbsolutePath();
150
151         // Create two directories inside the temp directory for this control
152         dirName = UUID.randomUUID().toString();
153         File fmuDir = new File(TEMP_FMU_DIRECTORY, dirName);
154         fmuDir.mkdir();
155
156         TEMP_FOLDER_1 = fmuDir.toString();
157         TEMP_FOLDER_2 = fmuDir.toString() + "_2";
158
159         // Lock fmu directory in temp directory
160         lockFMUDirectory();
161     }
162
163     public int getModelIDNew() {
164         return id;
165     }
166
167     public String getModelID() {
168         return dirName;
169     }
170
171     public String getFmuDir() {
172         return fmuDir;
173     }
174
175     /**
176      * Load fmu from a given file path. Releases the (possible) previously
177      * loaded fmu.
178      * 
179      * @param path absolute file path for fmu file
180      * @throws FMILException
181      */
182     private int fmuN = 0;
183     private boolean fmuLoaded = false;
184     public void loadFMUFile(String path) throws FMILException {
185
186         synchronized(syncObject) {
187
188             if(fmuN % 2 == 0) {
189                 fmuDir = TEMP_FOLDER_1;
190                 fmuN++;
191             } else {
192                 fmuDir = TEMP_FOLDER_2;
193                 fmuN = 0;
194             }
195
196             File tempDir = new File(fmuDir);
197             if(tempDir.isDirectory()) {
198                 try {
199                     FileUtils.deleteAll(tempDir);
200                 } catch (IOException e) {
201                     throw new FMILException("Could not create temp folder for fmu");
202                 }
203                 tempDir.mkdir();
204             } else {
205                 tempDir.mkdir();
206             }
207
208
209             try {
210                 String tmpPath = tempDir.getAbsolutePath();
211                 if(!tmpPath.endsWith("\\") && !tmpPath.endsWith("/"))
212                     tmpPath = tmpPath + "/";
213                 id = loadFMUFile_(path, tmpPath);
214                 
215                 getAllVariables();
216                 getAllVariableReferences();
217                 
218                 for(int i=0;i<variableNames.length;i++) {
219                         variableMap.put(variableNames[i], variableReferences[i]);
220                 }
221
222                 fmuLoaded = true;
223             } catch (UnsatisfiedLinkError err) {
224                 throw new FMILException(UNSATISFIED_LINK, err);
225             } catch (Exception e) {
226                 LOGGER.error(e.getMessage());
227                 throw new FMILException(e.getMessage());
228             }
229         }
230     }
231
232     private native int loadFMUFile_(String path, String toDir);
233
234     /**
235      * Set a step length for simulation
236      * 
237      * @param step Step length for simulation
238      * @throws FMILException
239      */
240     public void setStepLength(double step) throws FMILException {
241         synchronized(syncObject) {
242
243             try {
244                 int ret = setStepLength_(getModelIDNew(), step);
245                 if(ret != OK)
246                     LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
247
248             } catch (UnsatisfiedLinkError err) {
249                 throw new FMILException(UNSATISFIED_LINK);
250             } catch (Exception e) {
251                 throw new FMILException(e.getMessage());
252             }
253         }
254     }
255
256     private native int setStepLength_(int id, double step);
257
258     /**
259      * Instantiates a simulation. 
260      * <p>
261      * Make sure that an FMU is loaded first.
262      * @throws FMILException
263      */
264     public void instantiateSimulation() throws FMILException {
265         synchronized(syncObject) {
266
267             try {
268
269                 int ret = instantiateSimulation_(getModelIDNew()); 
270                 if(ret != OK)
271                     LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
272
273             } catch (FMILException e) {
274                 throw e;
275             } catch (UnsatisfiedLinkError err) {
276                 throw new FMILException(UNSATISFIED_LINK);
277             } catch (Exception e) {
278                 throw new FMILException(e.getMessage());
279             }
280         }
281     }
282
283     private native int instantiateSimulation_(int id) throws FMILException;
284
285     
286     /**
287      * Initializes a simulation. 
288      * <p>
289      * Make sure that simulation is instantiated first!
290      * @throws FMILException
291      */
292     public void initializeSimulation() throws FMILException {
293         synchronized(syncObject) {
294
295             try {
296
297                 int ret = initializeSimulation_(getModelIDNew()); 
298                 if(ret != OK)
299                     LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
300
301             } catch (FMILException e) {
302                 throw e;
303             } catch (UnsatisfiedLinkError err) {
304                 throw new FMILException(UNSATISFIED_LINK);
305             } catch (Exception e) {
306                 throw new FMILException(e.getMessage());
307             }
308         }
309     }
310
311     private native int initializeSimulation_(int id) throws FMILException;
312
313     /**
314      * Subscribe a set of variables from a loaded simulation.
315      * <p>
316      * Make sure that an FMU is loaded first.
317      * @param variables Array of variables
318      * @throws FMILException
319      */
320     public void subscribe(int[] variables) throws FMILException {
321         synchronized(syncObject) {
322
323             try {
324
325                 int ret = subscribe_(getModelIDNew(), variables); 
326                 if(ret != OK)
327                     LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
328
329             } catch (UnsatisfiedLinkError err) {
330                 throw new FMILException(UNSATISFIED_LINK);
331             } catch (Exception e) {
332                 throw new FMILException(e.getMessage());
333             }
334         }
335     }
336
337     private native int subscribe_(int id, int[] variables);
338
339     /**
340      * Set a new (Real, double) value for a variable. If the variable is a 
341      * parameter, the change is effective immediately.
342      *  
343      * @param name Variable
344      * @param value New (Real, double) value
345      * @throws FMILException
346      */
347     public void setRealValue(String name, double value) throws FMILException {
348         
349         synchronized(syncObject) {
350
351             try {
352
353                 int ret = setRealValue_(getModelIDNew(), variableMap.get(name), value); 
354                 if(ret != OK)
355                     LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
356
357             } catch (FMILException e) {
358                 throw e;
359             } catch (UnsatisfiedLinkError err) {
360                 throw new FMILException(UNSATISFIED_LINK);
361             } catch (Exception e) {
362                 throw new FMILException(e.getMessage());
363             }
364             
365         }
366         
367     }
368
369     public void setRealValue(int variableReference, double value) throws FMILException {
370         
371         synchronized(syncObject) {
372
373             try {
374
375                 int ret = setRealValue_(getModelIDNew(), variableReference, value); 
376                 if(ret != OK)
377                     LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
378
379             } catch (FMILException e) {
380                 throw e;
381             } catch (UnsatisfiedLinkError err) {
382                 throw new FMILException(UNSATISFIED_LINK);
383             } catch (Exception e) {
384                 throw new FMILException(e.getMessage());
385             }
386             
387         }
388         
389     }
390
391     private native int setRealValue_(int id, int variableReference, double value) throws FMILException;
392
393 //    /**
394 //     * Set a new (integer) value for a variable. If the variable is a 
395 //     * parameter, the change is effective immediately.
396 //     *  
397 //     * @param name Variable
398 //     * @param value New (integer) value
399 //     * @throws FMILException
400 //     */
401 //    public void setIntegerValue(String name, int value) throws FMILException {
402 //        synchronized(syncObject) {
403 //
404 //            try {
405 //
406 //                int ret = setIntegerValue_(getModelID(), name, value); 
407 //                if(ret == ERROR)
408 //                    throw new FMILException(getLastErrorMessage());
409 //
410 //            } catch (UnsatisfiedLinkError err) {
411 //                throw new FMILException(UNSATISFIED_LINK);
412 //            } catch (Exception e) {
413 //                throw new FMILException(e.getMessage());
414 //            }
415 //        }
416 //    }
417 //    private native int setIntegerValue_(String id, String name, int value);
418 //
419 //    /**
420 //     * Set a new (boolean) value for a variable. If the variable is a 
421 //     * parameter, the change is effective immediately.
422 //     *  
423 //     * @param name Variable
424 //     * @param value New (boolean) value
425 //     * @throws FMILException
426 //     */
427 //    public void setBooleanValue(String name, boolean value) throws FMILException {
428 //        synchronized(syncObject) {
429 //
430 //            try {
431 //
432 //                int ret = setBooleanValue_(getModelID(), name, value); 
433 //                if(ret == ERROR)
434 //                    throw new FMILException(getLastErrorMessage());
435 //
436 //            } catch (UnsatisfiedLinkError err) {
437 //                throw new FMILException(UNSATISFIED_LINK);
438 //            } catch (Exception e) {
439 //                throw new FMILException(e.getMessage());
440 //            }
441 //        }
442 //    }
443 //    private native int setBooleanValue_(String id, String name, boolean value);
444 //
445 //    public void setTime(double time) throws FMILException {
446 //        synchronized(syncObject) {
447 //
448 //            try {
449 //
450 //                int ret = setTime_(getModelID(), time); 
451 //                if(ret == ERROR)
452 //                    throw new FMILException(getLastErrorMessage());
453 //
454 //            } catch (UnsatisfiedLinkError err) {
455 //                throw new FMILException(UNSATISFIED_LINK);
456 //            } catch (Exception e) {
457 //                throw new FMILException(e.getMessage());
458 //            }
459 //        }
460 //    }
461 //    private native int setTime_(String id, double time);
462
463     /**
464      * Simulate one step forward. The step length can be set with
465      * setStepLength()
466      * 
467      * @throws FMILException
468      */
469     public void simulateStep() throws FMILException {
470         synchronized(syncObject) {
471
472             try {
473
474                 int ret = simulateStep_(getModelIDNew()); 
475                 if(ret != OK)
476                     LOGGER.warn("Function return value != OK, an exception should have been thrown from native code!");
477
478             } catch (FMILException e) {
479                 throw e;
480             } catch (UnsatisfiedLinkError err) {
481                 throw new FMILException(UNSATISFIED_LINK);
482             } catch (Exception e) {
483                 throw new FMILException(e.getMessage());
484             }
485         }
486     }
487     private native int simulateStep_(int id) throws FMILException;
488
489     /**
490      * Get an array containing the current values for subscribed variables. The
491      * values are in the same order as in the subscription.
492      * 
493      * @param results An array the size of subscribed results
494      * @return
495      */
496     public double[] getSubscribedResults() throws FMILException {
497         synchronized(syncObject) {
498
499             try {
500                 
501                 double[] results = new double[subscription.size()];
502                 Arrays.fill(results, Double.NaN);
503                 
504                 return getSubscribedResults_(getModelIDNew(), results);
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 }