source: trunk/org.modelica.mdt.omc/src/org/modelica/mdt/omc/OMCProxy.java @ 1648

Last change on this file since 1648 was 1648, checked in by magsj467, 12 years ago

BUG FIX: Various bugs with the graph view

File size: 45.6 KB
Line 
1/**
2 * This file is part of Modelica Development Tooling (MDT).
3 * The Modelica Development Tooling (MDT) software is
4 * distributed under the conditions specified below.
5 *
6 * Copyright (c) 2005-2006,
7 * The MDT Team:
8 * @author Adrian Pop [adrpo@ida.liu.se],
9 * @author Elmir Jagudin,
10 * @author Andreas Remar,
11 * Programming Environments Laboratory (PELAB),
12 * Department of Computer and Information Science (IDA),
13 * Linköping University (LiU).
14 *
15 * All rights reserved.
16 *
17 * (The new BSD license, see also
18 *  http://www.opensource.org/licenses/bsd-license.php)
19 *
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions are
22 * met:
23 *
24 * * Redistributions of source code must retain the above copyright
25 *   notice, this list of conditions and the following disclaimer.
26 *
27 * * Redistributions in binary form must reproduce the above copyright
28 *   notice, this list of conditions and the following disclaimer in
29 *   the documentation and/or other materials provided with the
30 *   distribution.
31 *
32 * * Neither the name of Authors nor the name of Linköpings University nor
33 *   the names of its contributors may be used to endorse or promote products
34 *   derived from this software without specific prior written permission.
35 *
36 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
37 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
38 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
39 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
40 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
43 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
46 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47 */
48
49package org.modelica.mdt.omc;
50
51import java.io.BufferedReader;
52import java.io.BufferedWriter;
53import java.io.File;
54import java.io.FileReader;
55import java.io.IOException;
56import java.io.OutputStream;
57import java.io.OutputStreamWriter;
58import java.io.PrintWriter;
59import java.util.ArrayList;
60import java.util.Collection;
61import java.util.Collections;
62import java.util.HashMap;
63import java.util.Iterator;
64import java.util.LinkedList;
65import java.util.Map;
66import java.util.Map.Entry;
67import java.util.Set;
68import java.util.StringTokenizer;
69
70import org.eclipse.core.resources.IFile;
71import org.eclipse.core.runtime.IPath;
72import org.eclipse.core.runtime.Platform;
73import org.modelica.mdt.core.ICompilerResult;
74import org.modelica.mdt.core.IModelicaClass;
75import org.modelica.mdt.core.IllegalRestrictionException;
76import org.modelica.mdt.core.List;
77import org.modelica.mdt.core.ListElement;
78import org.modelica.mdt.core.ModelicaParserException;
79import org.modelica.mdt.core.compiler.ComponentParser;
80import org.modelica.mdt.core.compiler.IClassInfo;
81import org.modelica.mdt.core.compiler.ConnectException;
82import org.modelica.mdt.core.compiler.ElementInfo;
83import org.modelica.mdt.core.compiler.IModelicaCompiler;
84import org.modelica.mdt.core.compiler.InvocationError;
85import org.modelica.mdt.core.compiler.ModelicaParser;
86import org.modelica.mdt.core.compiler.UnexpectedReplyException;
87import org.modelica.mdt.core.preferences.PreferenceManager;
88import org.modelica.mdt.internal.core.CompilerResult;
89import org.modelica.mdt.internal.core.DefinitionLocation;
90import org.modelica.mdt.internal.core.ErrorManager;
91import org.modelica.mdt.omc.internal.ClassInfo;
92import org.modelica.mdt.omc.internal.ParseResults;
93import org.modelica.mdt.omc.internal.OMCParser;
94import org.modelica.mdt.omc.internal.corba.OmcCommunication;
95import org.modelica.mdt.omc.internal.corba.OmcCommunicationHelper;
96import org.omg.CORBA.ORB;
97//import org.eclipse.core.runtime.jobs.ILock;
98
99/**
100 * The OMCProxy is the glue between the OpenModelica Compiler and MDT.
101 * It uses the interactive API of OMC to get information about classes
102 * and to load classes into OMC.
103 *
104 * @author Adrian Pop
105 * @author Andreas Remar
106 */
107public class OMCProxy implements IModelicaCompiler
108{
109
110    /* the CORBA object */
111    private  OmcCommunication omcc;
112
113    enum osType { WINDOWS, UNIX };
114
115    private String corbaSession = "mdt";
116
117    /* what Operating System we're running on */
118    private  osType os;
119
120    /* indicates if we've setup the communication with OMC */
121    private boolean hasInitialized = false;
122
123    /* indicates if we've give up to run OMC as it didn't wanted to start! */
124    private boolean couldNotStartOMC = false;
125    /* number of compiler errors to show */
126    private int showMaxErrors = 10; 
127    /* number of compiler errors to show */
128    private int numberOfErrors = 0; 
129
130
131    /* indicates if the Modelica System Library has been loaded */
132    private String[] omcLibraries = {};
133
134    private java.util.List<String> standardLibraryPackages = null;
135
136    /* should we trace the calls to sendExpression? */
137    private boolean traceOMCCalls = false;
138    private boolean traceOMCStatus = true;
139
140    private boolean traceStatusPreferences = false;
141    private boolean traceCommandsPreferences = false;
142    private boolean traceErrorPreferences = false; 
143    private boolean traceReplyPrefereces = false;   
144
145    {
146        /* load debug options and set debug flag variables accordingly */
147        /*load trace/omcCalls flag */
148        String value = Platform.getDebugOption("org.modelica.mdt.omc/trace/omcCalls");
149        if (value != null && value.equalsIgnoreCase("true"))
150        {
151            traceOMCCalls = true;
152        }       
153
154        value = Platform.getDebugOption("org.modelica.mdt.omc/trace/omcStatus");
155        if (value != null && value.equalsIgnoreCase("true"))
156        {
157            traceOMCStatus = true;
158        }
159    }
160
161    private  OutputStream consoleOutput = null;
162
163    private OMCThread fOMCThread = null;
164    private boolean fOMCThreadHasBeenScheduled = false;
165
166    //private ILock fOMCLock = null;
167
168    public OMCProxy()
169    {
170        /* create the OMC thread */
171        if (fOMCThread == null) 
172        {
173            fOMCThread = new OMCThread();
174            // fOMCLock = Platform.getJobManager().newLock();   
175        }
176    }
177
178    /**
179     * Reads in the OMC CORBA object reference from a file on disk.
180     * @return the object reference as a <code>String</code>
181     */
182    private  String readObjectFromFile() throws ConnectException
183    {
184        File f = new File(getPathToObject());
185        String stringifiedObjectReference = null;
186
187        BufferedReader br = null;
188        FileReader fr = null;
189        try
190        {
191            fr = new FileReader(f);
192        }
193        catch(IOException e)
194        {
195            throw new ConnectException("Unable to read OpenModelica Compiler CORBA object from "+ f.toString());
196        }
197
198        br = new BufferedReader(fr);
199
200        try
201        {
202            stringifiedObjectReference = br.readLine();
203        }
204        catch(IOException e)
205        {
206            throw new ConnectException("Unable to read OpenModelica Compiler CORBA object from " + getPathToObject());
207        }
208        return stringifiedObjectReference;
209    }
210
211    /**
212     * @return Returns the path to the OMC CORBA object that is stored on disk.
213     */
214    private  String getPathToObject()
215    {
216        String fileName = null;
217        String temp = System.getProperty("java.io.tmpdir"); 
218        /* This mirrors the way OMC creates the object file. */     
219        switch (os)
220        {
221        case UNIX:
222            String username = System.getenv("USER");
223            if(username == null)
224            {
225                username = "nobody";
226            }
227            if (corbaSession == null || corbaSession.equalsIgnoreCase(""))
228                fileName = temp + "/openmodelica." + username + ".objid";
229            else
230                fileName = temp + "/openmodelica." + username + ".objid" + "." +  corbaSession;
231            break;
232        case WINDOWS:   
233            if (corbaSession == null || corbaSession.equalsIgnoreCase(""))
234                fileName = temp + "\\openmodelica.objid";
235            else
236                fileName = temp + "\\openmodelica.objid"+ "." + corbaSession;
237            break;
238        default:
239            ErrorManager.logBug("org.modelica.mdt.omc", "os variable set to unexpected os-type");
240        }
241
242        logOMCStatus("Will look for OMC object reference in '" + fileName + "'.", true);
243
244        return fileName;
245    }
246
247    /**
248     * With the help of voodoo magic determines the path to the
249     * omc binary that user (probably) wants to use and the working
250     * directory of where that binary (most likely) should be started in
251     *
252     * This will returns for example 'c:\openmodelica132\omc.exe'
253     * or '/usr/local/share/openmodelica/omc' depending on
254     * such factors as: OS type, environment variables settings,
255     * plugin user preferences, where the first matching
256     * binary found and the weather outside.
257     *
258     * @return full path to the omc binary and the working folder 
259     * @throws ConnectException if the path could not be determined
260     */
261    private  File[] getOmcBinaryPaths() throws ConnectException
262    {
263        String binaryName = "omc";
264
265        if (os == osType.WINDOWS)
266        {
267            binaryName += ".exe";
268        }
269
270        File omcBinary = null;
271        File omcWorkingDirectory = null;
272        File openModelicaHomeDirectory = null;
273        if (PreferenceManager.getUseStandardOmcPath())
274        {
275            /*
276             * user specified that standard path to omc should be used,
277             * try to determine the omc path via the OPENMODELICAHOME and
278             * by checking in it's various subdirectory for the omc binary file
279             */
280            logOMCStatus("Using OPENMODELICAHOME environment variable to find omc-binary", true);
281
282            /*
283             * Standard path to omc (or omc.exe) binary is encoded in OPENMODELICAHOME
284             * variable. If we don't find it just search the path!
285             */
286            String openModelicaHome = System.getenv("OPENMODELICAHOME");
287            if(openModelicaHome == null)
288            {
289                logOMCStatus("OPENMODELICAHOME environment variable is NULL, trying the PATH variable", true);
290                File omc = findExecutableOnPath(binaryName);
291                if (omc != null)
292                {
293                    logOMCStatus("Found omc executable in the path here: " + omc.getAbsolutePath(), true);
294                    openModelicaHome = omc.getParentFile().getParentFile().getAbsolutePath();
295                }
296                else
297                {                   
298                    final String m = "Environment variable OPENMODELICAHOME is not set and we could not find: " + binaryName + " in the PATH";
299                    logOMCStatus(m, true);
300                    throw new ConnectException(m);
301                }
302            }
303
304            openModelicaHomeDirectory = new File(openModelicaHome);
305
306            /* the subdirectories where omc binary may be located, hurray for standards! */
307            // adrpo 2012-06-12 do not support the old ways! "/omc" and "Compiler/omc"
308            String[] subdirs = { "bin" };
309
310            for (String subdir : subdirs)
311            {
312
313                String path = openModelicaHomeDirectory.getAbsolutePath() + File.separator;
314                path += subdir.equals("") ? binaryName :  subdir + File.separator + binaryName;
315
316                File file = new File(path); 
317
318                if (file.exists())
319                {
320                    omcBinary = file;
321                    logOMCStatus("Using omc-binary at '" + omcBinary.getAbsolutePath() + "'", true);
322                    break;
323                }
324                else
325                {
326                    logOMCStatus("No omc binary at: [" + path + "]", true);
327                }
328            }
329
330            if (omcBinary == null)
331            {
332                logOMCStatus("Could not find omc-binary on the OPENMODELICAHOME path or in the PATH variable", true);
333                throw new ConnectException("Unable to start the OpenModelica Compiler, binary not found");
334            }
335        }
336        else
337        {
338            omcBinary = new File(PreferenceManager.getCustomOmcPath());
339
340            logOMCStatus("Using userspecified omc-binary at '" + omcBinary.getAbsolutePath() + "'", true);
341
342            if (!omcBinary.exists())
343            {
344                logOMCStatus("file '" + omcBinary.getAbsolutePath() + "' does not exist", true);
345                throw new ConnectException("Specified omc-binary '" + omcBinary.getAbsolutePath() +
346                        "' does not exist");
347            }
348
349            /*
350             * always start in /tmp
351             */
352        }
353        // set the working directory to temp/OpenModelica
354        omcWorkingDirectory = new File(System.getProperty("java.io.tmpdir"));
355        logOMCStatus("Using working directory '" + omcWorkingDirectory.getAbsolutePath() + "'", true);
356       
357        return new File[] {omcBinary, omcWorkingDirectory};
358    }
359
360    /**
361     * Start a new OMC server.
362     */
363    private synchronized void startServer() throws ConnectException
364    {
365        if (!fOMCThreadHasBeenScheduled)
366        {
367            fOMCThread.start();
368            fOMCThreadHasBeenScheduled = true;
369            /* wait for 10 seconds */
370            try { Thread.sleep(1000); } catch(InterruptedException e) {};
371        }
372    }
373
374    /**
375     * Initializes an ORB, converts the stringified OMC object to a real
376     * CORBA object, and then narrows that object to an OmcCommunication
377     * object.
378     */
379    private synchronized void setupOmcc(String stringifiedObjectReference)
380    {
381        /* Can't remember why this is needed. But it is. */
382        String args[] = {null};
383
384        /* set the CORBA read timeout to a larger value as we send huge amounts of data
385         * from OMC to MDT
386         */
387        System.setProperty("com.sun.CORBA.transport.ORBTCPReadTimeouts", "1:60000:300:1"); 
388
389        ORB orb;
390        orb = ORB.init(args, null);     
391
392        /* Convert string to object. */
393        org.omg.CORBA.Object obj = orb.string_to_object(stringifiedObjectReference);       
394
395        /* Convert object to OmcCommunication object. */
396        omcc = OmcCommunicationHelper.narrow(obj);
397    }
398
399    /**
400     * @return the name of the operating system. If an unknown os is found,
401     * the default is Unix.
402     */
403    private  osType getOs()
404    {
405        String osName = System.getProperty("os.name");
406        if(osName.contains("Linux"))
407        {
408            return osType.UNIX;
409        }
410        else if(osName.contains("Windows"))
411        {
412            return osType.WINDOWS;
413        }
414        else
415        {
416            ErrorManager.logWarning("'" + osName + "' not officialy supported OS");
417            /* If the OS is not GNU/Linux or Windows, default to Unix */
418            return osType.UNIX;
419        }
420    }
421
422    /**
423     * Initialize the communication with OMC
424     * @throws ConnectException if we're unable to start communicating with
425     * the server
426     */
427    private synchronized void init() throws ConnectException
428    {
429        /*
430         * Get type of operating system, used for finding object
431         * reference and starting OMC if the reference is faulty
432         */
433        os = getOs();
434
435        /* See if an OMC server is already running */
436        File f = new File(getPathToObject());
437        String stringifiedObjectReference = null;
438        if(!f.exists())
439        {
440            /* If a server isn't running, start it */
441            logOMCStatus("No OMC object reference found, starting server.", true);
442            startServer();
443        }
444        else
445        {
446            logOMCStatus("Old OMC CORBA object reference present, assuming OMC is running.", true);
447        }
448
449        /* Read in the CORBA OMC object from a file on disk */
450        stringifiedObjectReference = readObjectFromFile();
451
452        /*
453         * Setup up OMC object reference by initializing ORB and then
454         * converting the string object to a real CORBA object.
455         */
456        setupOmcc(stringifiedObjectReference);
457
458        try
459        {
460            /*
461             * Test the server by trying to send an expression to it.
462             * This might fail if the object reference found on disk didn't
463             * have a corresponding server running. If a server is missing,
464             * catch an exception and try starting a server.
465             */
466            logOMCStatus("Trying to send 'getVersion()' expression to OMC.", true);
467            omcc.sendExpression("getVersion()");
468            logOMCStatus("Expression sent successfully.", true);
469        }
470        catch(Exception e)
471        {
472            /* Start server and set up omcc */
473            logOMCStatus("Failed sending expression, will try to start OMC.", true);
474            startServer();
475
476            stringifiedObjectReference = readObjectFromFile();
477            setupOmcc(stringifiedObjectReference);
478
479            try
480            {
481                /* Once again try to send an expression to OMC. If it fails this
482                 * time it's time to send back an exception to the caller of
483                 * this function. */
484                logOMCStatus("Trying to send 'getVersion()' expression to OMC.", true);
485                omcc.sendExpression("getVersion()");
486                logOMCStatus("Expression sent successfully.", true);
487            }
488            catch(org.omg.CORBA.COMM_FAILURE x)
489            {
490                logOMCStatus("Failed sending expression, giving up.", true);
491                throw new ConnectException("Unable to start the OpenModelica Compiler.");
492            }
493        }
494
495        hasInitialized = true;
496    }
497
498    /**
499     * Send expression to OMC. If communication is not initialized, it is initialized here.
500     * @param command the expression to send to OMC
501     * @param showInConsole true or false
502     * @throws ConnectException if we're unable to start communicating with
503     * @return a String[] {result, answerToGetErrorString};
504     * the server
505     */
506    // TODO add synchronization so that two threads don't fudge up each others
507    // communication with OMC
508    // old synchronization aka 'private synchronized String sendExpression(String command)'
509    // doesn't work when there is possibility of multiple instances of OMCProxy objects
510    public ICompilerResult sendExpression(String command, boolean showInConsole) throws ConnectException
511    {   
512        String error = null;       
513        String[] retval = { "" };
514        // if we couldn't start OMC, don't even bother anymore!
515        if (couldNotStartOMC)
516        {
517            return CompilerResult.makeResult(retval, error);
518        }
519
520        if (numberOfErrors > showMaxErrors) return CompilerResult.makeResult(retval, error);
521
522        // trim the start and end spaces
523        command = command.trim();
524        // first try to evaluate commands locally if they start with '!'
525        // commands starting with ! are used by MDT Console.
526        if (command.startsWith("!")) 
527        {
528            retval[0] = evaluateExpressionLocally(command.substring(1));
529            return CompilerResult.makeResult(retval, error);
530        }
531
532        if(hasInitialized == false)
533        {
534            init();
535        }
536
537        if (command.equalsIgnoreCase("quit()")) 
538            hasInitialized = false;
539
540        try
541        {
542            logOMCCall(command, showInConsole);
543            /**
544             * Fetches the error string from OMC. This should be called after an "Error"
545             * is received. (Or whenever the queue of errors should be emptied.)
546             */
547            //synchronized (omcc)
548            {
549                retval[0] = omcc.sendExpression(command); 
550                error = omcc.sendExpression("getErrorString()");
551                /* Make sure the error string isn't empty */
552                if(error != null && error.length() > 2)
553                {
554                    error = error.trim();
555                    error = error.substring(1, error.length() - 1);
556                }
557                else
558                {
559                    error = null;
560                }           
561                logOMCReply(retval[0], showInConsole);
562                logOMCCall("getErrorString()", showInConsole);
563                logOMCReply(error, showInConsole);
564                /*
565                if (error != null && !error.equalsIgnoreCase(""))
566                    System.out.println(" -=> getErrorString() = '" + error + "'");
567                else
568                    System.out.println("");
569                 */
570                return CompilerResult.makeResult(retval, error);               
571            }           
572        }
573        catch(org.omg.CORBA.COMM_FAILURE x)
574        {
575            numberOfErrors++;
576            logOMCCallError("Error while sending command " + command + " ["+x+"]", showInConsole);
577            /* lost connection to OMC or something */
578            throw new ConnectException("Couldn't send command to the OpenModelica Compiler. Tried sending: " + command);
579        }
580
581        //return CompilerResult.makeResult(retval, error);
582    }
583
584    /**
585     * Logs the expression sent to OMC if the
586     * tracing flag (traceOMCCalls) is set
587     *
588     * @param expression the expression that is about to be sent to OMC
589     */
590    private  void logOMCCall(String expression, boolean showInConsole)
591    {
592        if (showInConsole == true && traceCommandsPreferences == true)
593        {
594            if (consoleOutput != null)
595            {
596                ConsoleWriter cWriterCommand = new ConsoleWriter(consoleOutput, "command: ");               
597                cWriterCommand.setMessage(expression);
598                cWriterCommand.start();
599            }
600        }
601
602        if (!traceOMCCalls)
603        {
604            return;
605        }
606        System.out.println(">> " + expression);
607    }
608
609    public void setConsoleOutputStream(OutputStream outputStream)
610    {
611        consoleOutput = outputStream;
612    }
613
614
615    /**
616     * outputs the message about a call error that occurred
617     * when communicating with omc
618     * @param message the message to log
619     */
620    private  void logOMCCallError(String message, boolean showInConsole)
621    {
622        if (showInConsole == true && traceErrorPreferences == true)
623        {
624            if (consoleOutput != null)
625            {
626                ConsoleWriter cWriterError = new ConsoleWriter(consoleOutput, "error: ");
627                cWriterError.setMessage(message);
628                cWriterError.start();
629            }
630        }
631
632        if(!traceOMCCalls)
633        {
634            return;
635        }
636        System.out.println(message);
637    }
638
639    /**
640     * logs the message concerning OMC status if the
641     * tracing flag traceOMCStatus is set
642     * @param message the message to log
643     */
644    private  void logOMCStatus(String message, boolean showInConsole)
645    {
646        if (showInConsole == true && traceStatusPreferences == true)
647        {
648            if (consoleOutput != null)
649            {
650                ConsoleWriter cWriterStatus = new ConsoleWriter(consoleOutput, "status: ");             
651                cWriterStatus.setMessage(message);
652                cWriterStatus.start();
653            }
654        }
655
656        if (!traceOMCStatus)
657        {
658            return;
659        }
660        System.out.println("OMCSTATUS: " + message);
661    }
662
663    /**
664     * Logs the reply received from OMC if
665     * the tracing flag (traceOMCCalls) is set
666     *
667     * @param reply the reply received from the OMC
668     */
669    private  void logOMCReply(String reply, boolean showInConsole)
670    {
671        if (showInConsole == true && traceReplyPrefereces == true)
672        {
673            if (consoleOutput != null)
674            {
675                ConsoleWriter cWriterReply = new ConsoleWriter(consoleOutput, "reply :");               
676                cWriterReply.setMessage(reply);
677                cWriterReply.start();
678            }
679        }
680
681        if (!traceOMCCalls)
682        {
683            return;
684        }
685
686        StringTokenizer tokenizer = new StringTokenizer(reply, "\n");
687
688        while (tokenizer.hasMoreTokens())
689        {
690            System.out.println("<< " + tokenizer.nextToken());
691        }
692    }
693
694    /**
695     * Get the classes contained in a class (a package is a class..)
696     *
697     *
698     * @param className full class name where to look for packages
699     * @return a <code>List</code> of subclasses defined (and loaded into OMC)
700     * inside the class named className.
701     *
702     * @throws ConnectException
703     * @throws UnexpectedReplyException
704     * @throws InitializationException
705     */ 
706    public List getClassNames(String className) throws ConnectException, UnexpectedReplyException
707    {
708        ICompilerResult retval = sendExpression("getClassNames("+className+")", true);
709
710        List list = null;
711        try
712        {
713            list = ModelicaParser.parseList(retval.getFirstResult());
714        }
715        catch(ModelicaParserException e)
716        {
717            throw new UnexpectedReplyException("Unable to parse list: " 
718                    + e.getMessage());
719        }
720
721        return list;
722    }
723
724    /**
725     * Gets the type of restriction of a class.
726     *
727     * @param className fully qualified class name
728     * @return the type of restriction of the class or Type.CLASS if
729     *         type can't be determined
730     * @throws ConnectException
731     * @throws UnexpectedReplyException
732     */
733    public IModelicaClass.Restriction getRestriction(String className)
734            throws ConnectException, UnexpectedReplyException
735            {
736        ICompilerResult result = sendExpression("getClassRestriction(" + className + ")", true);
737
738        String reply = result.getFirstResult(); 
739        /* remove " around the reply */
740        reply = reply.trim();
741
742        if(reply.equals(""))
743        {
744            throw new UnexpectedReplyException("getClassRestriction("+className+") returned an empty result");
745        }
746
747        reply = reply.substring(1, reply.length()-1);
748
749        IModelicaClass.Restriction type = null;
750        try
751        {
752            type = IModelicaClass.Restriction.parse(reply);
753        }
754        catch(IllegalRestrictionException e)
755        {
756            throw new UnexpectedReplyException("Illegal type: " + e.getMessage());
757        }
758
759        return type;
760            }
761
762    /**
763     * @author Adrian Pop [adrpo@ida.liu.se]
764     * @param retval, the string returned by the OMC compiler
765     * @return checks if the string is actually an error
766     */ 
767    public boolean isError(String retval)
768    {
769        if (retval == null) return false;
770        /*
771         * See if there were parse errors, an empty list {} also denotes error
772         */     
773        return 
774                (retval.toLowerCase().contains("error") /* &&
775                !retval.startsWith("{")) ||
776                retval.equals("{}"*/);
777    }
778
779    protected class LazyLoadResult
780    {
781        ParseResults results;
782        long lastModification;
783
784        public LazyLoadResult(ParseResults results, long lastModification)
785        {
786            this.results = results;
787            this.lastModification = lastModification;
788        }
789    }
790    private static Map<IPath, LazyLoadResult> lazyLoadList = new HashMap<IPath, LazyLoadResult>(); 
791
792    public static Map<IPath, LazyLoadResult> getLazyLoadList()
793    {
794        return lazyLoadList;
795    }
796
797    /**
798     * Tries to load file into OMC which causes it to be parsed and the syntax
799     * checked.
800     * @param file the file we want to load
801     * @return a <code>ParseResult</code> containing the classes found in the
802     * file and the error messages from OMC
803     * @throws ConnectException
804     * @throws UnexpectedReplyException
805     * @throws InitializationException
806     */
807    public ParseResults loadSourceFile(IFile file) throws ConnectException, UnexpectedReplyException
808    {
809
810        //System.out.println("Look at this: " + file.getName());
811        synchronized (getLazyLoadList())
812        {                       
813            // activate lazy load
814            if (getLazyLoadList().containsKey(file.getFullPath()))
815            {
816                long lastModification = -1;
817                if (file.exists())
818                {
819                    lastModification = file.getModificationStamp();
820                    if (lastModification != IFile.NULL_STAMP)
821                    {
822                        LazyLoadResult llr = (LazyLoadResult)getLazyLoadList().get(file.getFullPath());
823                        if (llr.lastModification >= lastModification)
824                            return llr.results;
825                    }
826                }
827            }
828        }
829
830        ParseResults res = new ParseResults();
831        String fullName = file.getLocation().toString();
832        ICompilerResult ret = sendExpression("loadFileInteractiveQualified(\"" + fullName + "\")", true);
833
834        String retval = ret.getFirstResult();
835        /* Always keep your stuff nice and tidy! */
836        retval = retval.trim();
837        String errorString = ret.getError();
838
839        if(isError(errorString))
840        {           
841            res.setClassNames(new List());
842            if(errorString.equals("") == false)
843            {
844                res.setCompileErrors(OMCParser.parseErrorString(errorString));
845            }
846        }
847        /*
848         * File loaded and parsed successfully
849         */
850        else
851        {
852            try
853            {
854                res.setClassNames(ModelicaParser.parseList(retval));
855            } 
856            catch (ModelicaParserException e)
857            {
858                System.out.println("Unable to parse list: " + e.getMessage());
859                System.out.flush();
860                throw new UnexpectedReplyException("Unable to parse list: " + e.getMessage());
861            }
862
863            /*
864             * If there were errors, but the compilation went through,
865             * collect the error messages. (Test if errorString != "")
866             */
867            if(errorString.equals("") == false)
868            {
869                res.setCompileErrors(OMCParser.parseErrorString(errorString));             
870            }
871        }
872
873        synchronized (getLazyLoadList())
874        {
875            if (file.exists())
876            {
877                long lastModification = file.getModificationStamp();
878                if (lastModification != IFile.NULL_STAMP)               
879                    getLazyLoadList().put(file.getFullPath(), new LazyLoadResult(res, lastModification));
880            }
881        }       
882        return res;
883    }
884
885    /**
886     * Gets the location (file, starting and ending line number and column
887     * number) of a Modelica element.
888     * @param className the element we want to get location of
889     * @return an <code>ElementLocation</code> containing the file, starting and
890     * ending line number and column number of the given class
891     * @throws ConnectException
892     * @throws UnexpectedReplyException
893     * @throws InvocationError
894     */
895    public DefinitionLocation getClassLocation(String className)
896            throws ConnectException, UnexpectedReplyException, InvocationError
897            {
898        ICompilerResult res = sendExpression("getCrefInfo(" + className + ")", true);
899
900        String retval = res.getFirstResult();
901        retval.trim();
902
903        if(isError(retval))
904        {
905            throw new InvocationError("Fetching file position of " + className, "getCrefInfo(" + className + ")");
906        }
907
908
909        /*
910         * The getCrefInfo reply has the following format:
911         *
912         * {<file path>,<something>,<start line>,<start column>,<end line>,<end column>}
913         *
914         * for example:
915         * {/foo/Modelica/package.mo,writable,1,1,1029,13}
916         */
917        retval = retval.trim();
918
919        List tokens = null;
920        try
921        {
922            tokens = ModelicaParser.parseList(retval);
923        } 
924        catch (ModelicaParserException e1)
925        {
926            throw new UnexpectedReplyException("Unable to parse list: " + e1.getMessage());
927        }
928
929        String filePath = tokens.elementAt(0).toString();
930        int startLine;
931        int startColumn;
932        int endLine;
933        int endColumn;
934
935        try
936        {
937            startLine = Integer.parseInt(tokens.elementAt(2).toString());
938            startColumn = Integer.parseInt(tokens.elementAt(3).toString());
939            endLine = Integer.parseInt(tokens.elementAt(4).toString());
940            endColumn = Integer.parseInt(tokens.elementAt(5).toString());
941
942            if (startColumn == 0) {
943                assert(startLine == 1);
944                startColumn = 1;
945            }
946        }
947        catch (NumberFormatException e)
948        {
949            throw new 
950            UnexpectedReplyException("Can't parse getCrefInfo() reply, "+
951                    "unexpected format");
952        }
953
954        return new DefinitionLocation(filePath, startLine, startColumn, endLine, endColumn);
955            }
956
957    /**
958     * Queries the compiler if a particular modelica class/package is a package.
959     *
960     * @param className fully qualified name of the class/package
961     * @return true if className is a package, false otherwise
962     * @throws ConnectException
963     */
964    public boolean isPackage(String className) throws ConnectException
965    {
966        ICompilerResult res = sendExpression("isPackage(" + className + ")", true);
967
968        String retval = res.getFirstResult();
969        return retval.contains("true");
970    }
971
972    /**
973     * Uses the OMC API call getElementsInfo to fetch lots of information
974     * about a class definition. See interactive_api.txt in the OMC
975     * source tree.
976     * @param className the fully qualified name of a class
977     * @return a <code>Collection</code> (of <code>ElementsInfo</code>)
978     * containing the information about className
979     */
980    public Collection<ElementInfo> getElements(String className)
981            throws ConnectException, InvocationError, UnexpectedReplyException
982            {       
983        ICompilerResult res = sendExpression("getElementsInfo("+ className +")", true);
984        String retval = res.getFirstResult();
985        /*
986         * we need a efficient way to check if the result is
987         * humongosly huge list or 'Error' or maybe 'error'
988         */
989        for (int i = 0; i < retval.length(); i++)
990        {
991            if (retval.charAt(i) == '{')
992            {
993                /*
994                 * we found the beginning of the list, send it to parser and
995                 * hope for the best
996                 */
997                List parsedList = null;
998                try
999                {
1000                    parsedList = ModelicaParser.parseList(retval);
1001                } 
1002                catch (ModelicaParserException e)
1003                {
1004                    throw new UnexpectedReplyException("Unable to parse list: " + e.getMessage());
1005                }
1006
1007                /* convert the parsedList to a collection of ElementsInfo:s */
1008                LinkedList<ElementInfo> elementsInfo = new LinkedList<ElementInfo>();
1009
1010                for (ListElement element : parsedList)
1011                {
1012                    elementsInfo.add(new ElementInfo((List)element));
1013                }
1014
1015                return elementsInfo;
1016            }
1017            else if (retval.charAt(i) == 'E' || retval.charAt(i) == 'e')
1018            {
1019                /*
1020                 * this is the unreadable way to check if the retval
1021                 * equals 'Error' or 'error'
1022                 */
1023                if (retval.substring(i+1,i+5).equals("rror"))
1024                {
1025                    throw new InvocationError("fetching contents of " + className, "getElementsInfo("+ className +")");
1026                }
1027                else
1028                {
1029                    /* OMC returned something weird, panic mode ! */
1030                    break;
1031                }
1032            }
1033        }
1034        /* we have no idea what OMC returned */
1035        throw new UnexpectedReplyException("getElementsInfo("+ className +")" + "replies:'" + retval + "'");
1036            }
1037
1038    public IClassInfo getClassInfo(String className)
1039            throws ConnectException, UnexpectedReplyException
1040            {
1041        ICompilerResult res = sendExpression("getClassInformation("+ className +")", true);
1042        String retval = res.getFirstResult();
1043
1044        ClassInfo ci = null;
1045
1046        try
1047        {
1048            ci = new ClassInfo(retval);
1049        } 
1050        catch (ModelicaParserException e)
1051        {
1052            throw new UnexpectedReplyException(retval);
1053        }
1054        catch (IllegalRestrictionException e)
1055        {
1056            throw new UnexpectedReplyException(retval);
1057        }
1058
1059        return  ci;
1060            }
1061
1062
1063    public String getCompilerVersion() throws ConnectException
1064    {
1065        ICompilerResult res = sendExpression("getVersion()", true); 
1066        String retval = res.getFirstResult();
1067        if (retval.length() == 0) return null;
1068        if (retval.charAt(0) == '"')
1069            retval = retval.substring(1);
1070        int lio = -1;
1071        if ((lio=retval.lastIndexOf('"')) > 0)
1072            retval = retval.substring(0, lio);     
1073        return retval.trim();
1074    }
1075
1076    /**
1077     * @return the name of the compiler that this plugin tries to communicate
1078     * with (at least it tries...)
1079     */
1080    public String getCompilerName()
1081    {
1082        String version = "";
1083        try
1084        {
1085            version = getCompilerVersion();
1086        }
1087        catch(ConnectException e)
1088        {
1089            ErrorManager.logError(e);
1090        }
1091        return "OpenModelica Compiler " + version; 
1092    }
1093
1094    /**
1095     * Loads in the Modelica System Library and returns names of the top-level
1096     * packages.
1097     * 
1098     * @throws ConnectException if we're unable to start communicating with
1099     * the server
1100     */ 
1101    public String[] getStandardLibrary() throws ConnectException {
1102        String[] omcLibrariesFetch = PreferenceManager.getOMCLibrariesArray();
1103        if (omcLibraries != omcLibrariesFetch ) {       
1104            omcLibraries = omcLibrariesFetch;
1105            for (int i=0;i<omcLibraries.length;i++) {
1106                sendExpression("loadModel(" + omcLibraries[i] + ")", true);
1107            }
1108        }
1109        return omcLibraries;
1110    }
1111
1112    /**
1113     * lists the name of a class
1114     * 
1115     * @throws ConnectException if we're unable to start communicating with
1116     * the server
1117     */ 
1118    public ICompilerResult getClassString(String className) throws ConnectException, UnexpectedReplyException {
1119        ICompilerResult res = sendExpression("list("+ className +")", true);
1120
1121        res.trimFirstResult();
1122
1123        return res;
1124    }
1125
1126    /**
1127     *
1128     * @author Adrian Pop
1129     *
1130     */
1131    public class ConsoleWriter extends Thread
1132    {
1133        private PrintWriter consoleWriter = null;
1134        private String message = null;
1135        private String prefix = null;
1136
1137        public ConsoleWriter(OutputStream output, String prefix)
1138        {
1139            super();
1140            if (output != null)
1141            {
1142                consoleWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(output)));
1143            }
1144            this.prefix = prefix;
1145        }
1146
1147        public synchronized void setMessage(String what)
1148        {
1149            message = what;
1150        }
1151
1152        public synchronized void run()
1153        {
1154            if (message != null)
1155            {
1156                StringTokenizer tokenizer = new StringTokenizer(message, "\n");
1157                while (tokenizer.hasMoreTokens())
1158                {
1159                    consoleWriter.write("\nmdt> " + prefix + tokenizer.nextToken());
1160                }
1161                consoleWriter.write("\nomc> ");
1162                consoleWriter.flush();
1163            }
1164        }
1165    }
1166
1167    /**
1168     * Evaluate command locally, don't sent it to OpenModelica Compiler
1169     * @author Adrian Pop
1170     * @param String command
1171     * @return String result
1172     */
1173    String evaluateExpressionLocally(String command)
1174    {
1175        String retval = "Unknown command!";
1176        if (command.equals("help"))
1177        {
1178            retval = 
1179                    "All the MDT Console local commands start with '!'.\n" +
1180                            "All commands not starting with '!' will be sent to the OpenModelica compiler.\n" +
1181                            "For a list of OpenModelica commands available type help().\n" +
1182                            "NOTE: The !trace* commands display traces of all OpenModelica<->MDT\n" +
1183                            "      communication except the commands send from the console!\n" +
1184                            "Available local commands are:\n" +
1185                            "!help         - toggle display help on local commands.\n" +
1186                            "!traceStatus  - toggle display the status of the OpenModelica compiler.\n" +
1187                            "!traceError   - toggle display errors talking with the OpenModelica compiler.\n" +
1188                            "!traceReply   - toggle display the reply of the OpenModelica compiler.\n" +
1189                            "!traceCommand - toggle display the commands send to the OpenModelica compiler.\n" +
1190                            "!traceAll     - toggle on the display of all the traces available.\n" +
1191                            "!traceNone    - toggle off the display of all the traces available.\n";
1192        }
1193
1194        if (command.equals("traceStatus"))
1195        {
1196            traceStatusPreferences = traceStatusPreferences ? false : true;
1197            retval = "Tracing of OpenModelica status is set to: " + traceStatusPreferences;
1198        }
1199
1200        if (command.equals("traceError"))
1201        {
1202            traceErrorPreferences = traceErrorPreferences ? false : true;
1203            retval = 
1204                    "Tracing of errors while talking with OpenModelica is set to: " + traceErrorPreferences;
1205        }       
1206
1207        if (command.equals("traceReply"))
1208        {
1209            traceReplyPrefereces = traceReplyPrefereces ? false : true;
1210            retval = "Tracing of OpenModelica reply to commands is set to: " + traceReplyPrefereces;
1211        }       
1212
1213        if (command.equals("traceCommand"))
1214        {
1215            traceCommandsPreferences = traceCommandsPreferences ? false : true;
1216            retval = "Tracing of commands sent to OpenModelica is set to: " + traceCommandsPreferences;
1217        }
1218
1219        if (command.equals("traceAll"))
1220        {
1221            traceCommandsPreferences = true;           
1222            traceReplyPrefereces     = true;   
1223            traceErrorPreferences    = true;   
1224            traceStatusPreferences   = true;
1225            retval = "All tracing is now enabled!";         
1226        }
1227
1228        if (command.equals("traceNone"))
1229        {
1230            traceCommandsPreferences = false;           
1231            traceReplyPrefereces     = false;   
1232            traceErrorPreferences    = false;   
1233            traceStatusPreferences   = false;
1234            retval = "All tracing is now disabled!";           
1235        }       
1236
1237        return "\n" + retval;
1238    }
1239
1240    class OMCThread extends Thread
1241    {
1242
1243        public OMCThread()
1244        {
1245            super("OpenModelica Interactive Compiler Thread");
1246        }       
1247
1248        public void run() 
1249        {
1250            File tmp[] = null;
1251            try{
1252                tmp = getOmcBinaryPaths();
1253            }
1254            catch (ConnectException e) 
1255            {
1256                ErrorManager.logError(e);
1257                couldNotStartOMC = true; 
1258                hasInitialized = false;
1259                return;
1260            }
1261
1262            File omcBinary = tmp[0];
1263            final File workingDirectory = tmp[1];
1264
1265            File f = new File(getPathToObject());
1266            /*
1267             * Delete old object reference file. We need to do this because we're
1268             * checking if the file exists to determine if the server has started
1269             * or not (further down).
1270             */
1271            long lastModified = 0;
1272            if(f.exists())
1273            {
1274                logOMCStatus("Remember the creation time for old OMC object reference file.", true);
1275                lastModified = f.lastModified();
1276            }
1277
1278            Process proc = null;
1279            StreamReaderThread outThread = null;
1280            StreamReaderThread errThread = null;
1281            /* TODO! FIXME! add corba session to the preferences! */
1282            String command[] = { omcBinary.getAbsolutePath(), "+c="+corbaSession, "+d=interactiveCorba"};
1283            String extraCmds[] = PreferenceManager.getOMCCommandLineParametersArray();
1284            ArrayList<String> both = new ArrayList<String>(command.length + extraCmds.length);
1285            Collections.addAll(both, command);
1286            Collections.addAll(both, extraCmds);
1287            String cmd[] = new String[both.size()];
1288            int nonNull = 0;
1289            for (int i=0; i < both.size(); i++)
1290            {
1291                String str = (String) both.get(i);
1292                if (str != null)
1293                {
1294                    cmd[nonNull] = str;
1295                    nonNull++;
1296                }
1297            }
1298            String fullCMD = "";
1299            for (int i=0; i < nonNull; i++) 
1300                fullCMD += cmd[i] + " ";
1301            logOMCStatus("Running command: " + fullCMD, true);
1302            logOMCStatus("Setting working directory to: " + workingDirectory.getAbsolutePath(), true);             
1303            try
1304            {
1305                String[] env = null;
1306                // prepare buffers for process output and error streams
1307                if (System.getenv("OPENMODELICAHOME") == null)
1308                {
1309                    Map<String, String> envMap = System.getenv();
1310                    Set<Entry<String, String>> entrySet = envMap.entrySet();
1311                    Collection<String> lst = new ArrayList<String>();
1312                    String x = "OPENMODELICAHOME=" + omcBinary.getParentFile().getParentFile().getAbsolutePath();
1313                    lst.add(x);
1314                   
1315                    if (System.getenv("OPENMODELICALIBRARY") == null)
1316                    {
1317                      String y = "OPENMODELICALIBRARY=" + 
1318                        omcBinary.getParentFile().getParentFile().getAbsolutePath() + 
1319                        "/lib/omlibrary";
1320                      lst.add(y);
1321                    }
1322                   
1323                    Iterator<Entry<String, String>> i = entrySet.iterator();
1324                    while (i.hasNext())
1325                    {
1326                        Entry<String,String> z = i.next();
1327                        lst.add(z.getKey() + "=" + z.getValue());
1328                    }
1329                    env = lst.toArray(new String[lst.size()]);
1330                }
1331                proc=Runtime.getRuntime().exec(cmd, env, workingDirectory);
1332                //create thread for reading inputStream (process' stdout)
1333                outThread= new StreamReaderThread(proc.getInputStream(),System.out);
1334                //create thread for reading errorStream (process' stderr)
1335                errThread= new StreamReaderThread(proc.getErrorStream(),System.err);
1336                //start both threads
1337                outThread.start();
1338                errThread.start();
1339            }
1340            catch(IOException e)
1341            {
1342                logOMCStatus("Failed to run command: " + fullCMD, true);
1343                ErrorManager.logError(e);
1344                couldNotStartOMC = true; hasInitialized = false;
1345                return;
1346            }
1347            logOMCStatus("Command run successfully.", true);               
1348            logOMCStatus("Waiting for OMC CORBA object reference to appear on disk.", true);
1349
1350
1351            /*
1352             * Wait until the object exists on disk, but if it takes longer than
1353             * 10 seconds, abort. (Very arbitrary 10 seconds..)
1354             */
1355            int ticks = 0;
1356            while(true)
1357            {
1358                if (f.exists())
1359                    if (lastModified == 0 || (lastModified != 0 && f.lastModified() != lastModified)) 
1360                        break;
1361
1362                try
1363                {
1364                    Thread.sleep(100);
1365                }
1366                catch(InterruptedException e)
1367                {
1368                    /* ignore */
1369                }
1370                ticks++;
1371                /* If we've waited for around 5 seconds, abort the wait for OMC */
1372                if(ticks > 100)
1373                {
1374                    logOMCStatus("The OMC Corba object reference file has not been modified in 100 seconds; we give up starting OMC.", true);
1375                    couldNotStartOMC = true; hasInitialized = false;
1376                    return;
1377                }
1378            }
1379            logOMCStatus("OMC object reference found.", true);
1380            int omcExitCode = 0;
1381            try
1382            {
1383                //wait for process to end
1384                omcExitCode = proc.waitFor();
1385                if (omcExitCode != 0)
1386                {
1387                    ErrorManager.logWarning("OpenModelica compiler exited with code:" + omcExitCode);
1388                }
1389                //finish reading whatever's left in the buffers
1390                outThread.join();
1391                errThread.join();                               
1392            }
1393            catch(InterruptedException e)
1394            {
1395                logOMCStatus("OpenModelica compiler interrupted:" + e.getMessage() + " with code " + proc.exitValue(), true);
1396                couldNotStartOMC = true; hasInitialized = false;
1397                return;
1398            }
1399            logOMCStatus("OpenModelica compiler exited with code: " + proc.exitValue(), true);
1400            couldNotStartOMC = true; hasInitialized = false;
1401        }
1402    }
1403
1404    public boolean isRunning()
1405    {
1406        if (fOMCThread.isAlive()) return true;
1407        if (hasInitialized) return true;
1408        return false;
1409    }
1410
1411    private File findExecutableOnPath(String executableName)
1412    {
1413        String systemPath = System.getenv("PATH");
1414        if (systemPath == null) // try with small letters
1415            systemPath = System.getenv("path");
1416        String[] pathDirs = systemPath.split(File.pathSeparator);
1417 
1418        File fullyQualifiedExecutable = null;
1419        for (String pathDir : pathDirs)
1420        {
1421            File file = new File(pathDir, executableName);
1422            if (file.isFile())
1423            {
1424                fullyQualifiedExecutable = file;
1425                break;
1426            }
1427        }
1428        return fullyQualifiedExecutable;
1429    }
1430   
1431    /*
1432     * Extended by Magnus Sjöstrand
1433     *
1434     */
1435   
1436    /**
1437     * gets the nth inheritance to the given class
1438     * 
1439     * @throws ConnectException if we're unable to start communicating with
1440     * the server
1441     */ 
1442   
1443    public ICompilerResult getNthInheritedClass(String className, int n) throws ConnectException, UnexpectedReplyException {
1444        ICompilerResult res = sendExpression("getNthInheritedClass("+ className + ", " + n + ")", true);
1445        res.trimFirstResult();
1446
1447        return res;
1448    }
1449   
1450    /**
1451     * gets the number of inheritances to the given class
1452     * 
1453     * @throws ConnectException if we're unable to start communicating with
1454     * the server
1455     */ 
1456   
1457    public int getInheritanceCount(String className) throws ConnectException, UnexpectedReplyException {
1458        int resNum = 0;
1459        ICompilerResult res = sendExpression("getInheritanceCount(" + className + ")", true);
1460        res.trimFirstResult();               
1461        if(!res.getFirstResult().isEmpty()){
1462            resNum = Integer.parseInt(res.getFirstResult());
1463        }
1464        return resNum;
1465    }
1466   
1467    /**
1468     * gets the nth algorithm in the given class
1469     * 
1470     * @throws ConnectException if we're unable to start communicating with
1471     * the server
1472     */ 
1473   
1474    public ICompilerResult getNthAlgorithmItem(String className, int n) throws ConnectException, UnexpectedReplyException {
1475        ICompilerResult res = sendExpression("getNthAlgorithmItem("+ className + ", " + n + ")", true);
1476        res.trimFirstResult();
1477
1478        return res;
1479    }
1480   
1481    /**
1482     * gets the number of algorithms in the given class
1483     * 
1484     * @throws ConnectException if we're unable to start communicating with
1485     * the server
1486     */ 
1487       
1488       public int getAlgorithmItemsCount(String className) throws ConnectException, UnexpectedReplyException {
1489        int resNum = 0;
1490        ICompilerResult res = sendExpression("getAlgorithmItemsCount(" + className + ")", true);
1491        res.trimFirstResult();               
1492        if(!res.getFirstResult().isEmpty()){
1493            resNum = Integer.parseInt(res.getFirstResult());
1494        }
1495        return resNum;
1496    }
1497   
1498    /**
1499     * gets the nth equation in the given class
1500     * 
1501     * @throws ConnectException if we're unable to start communicating with
1502     * the server
1503     */ 
1504   
1505    public ICompilerResult getNthEquationItem(String className, int n) throws ConnectException, UnexpectedReplyException {
1506        ICompilerResult res = sendExpression("getNthEquationItem("+ className + ", " + n + ")", true);
1507        res.trimFirstResult();
1508
1509        return res;
1510    }
1511   
1512    /**
1513     * gets the number of equations to the given class
1514     * 
1515     * @throws ConnectException if we're unable to start communicating with
1516     * the server
1517     */ 
1518       
1519       public int getEquationItemsCount(String className) throws ConnectException, UnexpectedReplyException {
1520        int resNum = 0;
1521        ICompilerResult res = sendExpression("getEquationItemsCount(" + className + ")", true);
1522        res.trimFirstResult();               
1523        if(!res.getFirstResult().isEmpty()){
1524            resNum = Integer.parseInt(res.getFirstResult());
1525        }
1526        return resNum;
1527    }
1528   
1529    /**
1530     * lists all of the components in class
1531     * 
1532     * @throws ConnectException if we're unable to start communicating with
1533     * the server
1534     */ 
1535   
1536    public List getComponents(String className) throws ConnectException, UnexpectedReplyException {
1537        ICompilerResult res = sendExpression("getComponents("+ className +")", true);
1538        //System.out.println(res.getFirstResult());
1539        List list = null;
1540        try{
1541            list = ComponentParser.parseList(res.getFirstResult());
1542        }
1543        catch(ModelicaParserException e){
1544            throw new UnexpectedReplyException("Unable to parse list: " 
1545                    + e.getMessage());
1546        }
1547        return list;
1548    }
1549   
1550    public boolean existClass(String className) throws ConnectException, UnexpectedReplyException {
1551        ICompilerResult res = sendExpression("existClass("+ className +")", true);
1552        if (res.getFirstResult().trim().toString().equals("true")){
1553                return true;
1554        }
1555        return false;
1556    }
1557   
1558    public ICompilerResult getErrorString() throws ConnectException, UnexpectedReplyException {
1559        ICompilerResult res = sendExpression("getErrorString()", true);
1560        return res;
1561    }
1562   
1563    public ICompilerResult loadFile(String classPath) throws ConnectException, UnexpectedReplyException {
1564        classPath = classPath.replace("\\", "/");
1565        ICompilerResult res = sendExpression("loadFile(\""+ classPath +"\")", true);
1566        return res;
1567    }
1568   
1569    public ICompilerResult getSourceFile(String className) throws ConnectException, UnexpectedReplyException {
1570        ICompilerResult res = sendExpression("getSourceFile(" + className +")", true);
1571        return res;
1572    }
1573}
Note: See TracBrowser for help on using the repository browser.