Skip to content

Commit

Permalink
- Changes to the OMC-Java interface (Java code)
Browse files Browse the repository at this point in the history
  - Replaced the ANTLR grammar for parsing the CORBA communication
    + Max heap size reduced by 66% (down to 1GB from 3GB on 64-bit platforms)
    + Time to parse reduced to 33-50% of the original time taken (depending on typed or untyped parsing)
    + Added proper typed parsing also for list,tuple and Option
  - Added the TypeSpec.java class to represent complex types fully
  - Added missing JreSocketFactory
  - Parsing an AST with type information is no longer done in two phases
  - Updated the templated to generate jar files to reflect the changes above
  - MSL 3.1 can now be parsed fully, with full type information
    + Typecasting needs to be done for tuples due to Java weaknesses,
      but no longer using ModelicaAny.cast - standard (T)myTuple.get(0) should work.
    + The string is possibly too large for 32-bit OpenModelica to handle.
      However, it is no longer manipulated within OpenModelica, so it might accept it. Needs to be tested.


git-svn-id: https://openmodelica.org/svn/OpenModelica/trunk@4772 f25d12d1-65f4-0310-ae8a-bbce733d8d8e
  • Loading branch information
sjoelund committed Jan 13, 2010
1 parent 54f13f7 commit 44b7e3c
Show file tree
Hide file tree
Showing 48 changed files with 852 additions and 307 deletions.
7 changes: 3 additions & 4 deletions c_runtime/java_interface/Makefile.common
Expand Up @@ -29,14 +29,16 @@ src/org/openmodelica/ModelicaReal.java \
src/org/openmodelica/ModelicaString.java \
src/org/openmodelica/ModelicaBaseArray.java \
src/org/openmodelica/ModelicaRecordException.java \
src/org/openmodelica/TypeSpec.java \
src/org/openmodelica/SimpleTypeSpec.java \
src/org/openmodelica/ComplexTypeSpec.java \
src/org/openmodelica/corba/SmartProxy.java \
src/org/openmodelica/corba/OmcCommunicationHelper.java \
src/org/openmodelica/corba/Result.java \
src/org/openmodelica/corba/OmcCommunicationOperations.java \
src/org/openmodelica/corba/InvocationError.java \
src/org/openmodelica/corba/OmcCommunication.java \
src/org/openmodelica/corba/OMCProxy.java \
src/org/openmodelica/corba/parser/OMCorbaParser.java \
src/org/openmodelica/corba/parser/UniontypeDefinition.java \
src/org/openmodelica/corba/parser/ComplexTypeDefinition.java \
src/org/openmodelica/corba/parser/ParseException.java \
Expand All @@ -46,7 +48,6 @@ src/org/openmodelica/corba/parser/JarCreator.java \
src/org/openmodelica/corba/parser/OMCorbaDefinitionsLexer.java \
src/org/openmodelica/corba/parser/RecordDefinition.java \
src/org/openmodelica/corba/parser/PackageDefinition.java \
src/org/openmodelica/corba/parser/OMCorbaLexer.java \
src/org/openmodelica/corba/parser/SymbolTable.java \
src/org/openmodelica/corba/parser/OMCStringParser.java \
src/org/openmodelica/corba/parser/VariableDefinition.java \
Expand Down Expand Up @@ -77,8 +78,6 @@ src/org/openmodelica/corba/parser/JavaDefinitions/uniontype.st \
src/org/openmodelica/corba/parser/JavaDefinitions/record.st \
src/org/openmodelica/corba/parser/JavaDefinitions/function.st \
src/org/openmodelica/corba/parser/JavaDefinitions/header.st \
src/org/openmodelica/corba/parser/OMCorba.g \
src/org/openmodelica/corba/parser/OMCorba.tokens \
src/org/openmodelica/corba/parser/OMCorbaDefinitions.g \
src/org/openmodelica/corba/parser/OMCorbaDefinitions.tokens

Expand Down
15 changes: 15 additions & 0 deletions c_runtime/java_interface/src/org/openmodelica/ComplexTypeSpec.java
@@ -0,0 +1,15 @@
package org.openmodelica;

/**
* Similar to OpenModelica TCOMPLEX
*/
public class ComplexTypeSpec<T extends ModelicaObject> extends TypeSpec<T> {
private final TypeSpec<? extends ModelicaObject>[] spec;
public ComplexTypeSpec(Class<T> c,TypeSpec<? extends ModelicaObject>[] spec) {
super(c);
this.spec = spec;
}
public TypeSpec<? extends ModelicaObject>[] getSubClassType() {
return spec;
}
}
199 changes: 183 additions & 16 deletions c_runtime/java_interface/src/org/openmodelica/ModelicaAny.java
@@ -1,35 +1,26 @@
package org.openmodelica;

import java.io.IOException;
import java.io.Reader;
import java.lang.reflect.Constructor;

import org.openmodelica.corba.parser.ParseException;

public class ModelicaAny {
@SuppressWarnings("unchecked")
public static <T extends ModelicaObject> T cast(ModelicaObject o, Class<T> c) throws Exception {
/* ModelicaObject -> ModelicaObject: Simple */
if (c == ModelicaObject.class) {
return c.cast(o);
/* ModelicaObject -> Interface extends ModelicaObject (must be Uniontype) */
/* ModelicaObject -> Interface extends ModelicaObject (must be Uniontype) */
} else if (c.isInterface()) {
if (!(o instanceof ModelicaRecord))
throw new Exception(o + " is not a record, but tried to cast it to Uniontype " + c);
/* Find the Java name of the record. We know the record will be part of the same package */
ModelicaRecord rec = ModelicaRecord.class.cast(o);
String recordName = rec.getRecordName();
String[] recordNameParts = recordName.split("\\.");
recordName = recordNameParts[recordNameParts.length-1];
String className = c.getPackage().getName()+"."+recordName;
/* Load the class of the record and verify that it is of the expected Uniontype */
ClassLoader cl = c.getClassLoader();
Class<?> nc = cl.loadClass(className);
if (nc == null)
throw new Exception("Couldn't find class " + className);
if (!ModelicaObject.class.isAssignableFrom(nc))
throw new Exception(nc + " is not a ModelicaObject");
for (Class<?> iface : nc.getInterfaces()) {
if (iface == c)
return c.cast(ModelicaAny.cast(o, (Class<? extends ModelicaObject>) nc));
}
throw new Exception(nc + " is not a " + c);
Class<?> nc = findUniontypeRecordClass(c,recordName);
return c.cast(ModelicaAny.cast(o, (Class<? extends ModelicaObject>) nc));
} else {
try {
if (c.isAssignableFrom(o.getClass()))
Expand All @@ -49,4 +40,180 @@ public static <T extends ModelicaObject> T cast(ModelicaObject o, Class<T> c) th
}
}
}

@SuppressWarnings("unchecked")
private static <T extends ModelicaObject> Class<? extends T> findUniontypeRecordClass(Class<T> c,String recordName) throws ParseException {
String[] recordNameParts = recordName.split("\\.");
recordName = recordNameParts[recordNameParts.length-1];
String className = c.getPackage().getName()+"."+recordName;
/* Load the class of the record and verify that it is of the expected Uniontype */
ClassLoader cl = c.getClassLoader();
Class<?> nc;
try {
nc = cl.loadClass(className);
} catch (ClassNotFoundException e) {
throw new ParseException(e);
}
if (nc == null)
throw new ParseException("Couldn't find class " + className);
if (!ModelicaObject.class.isAssignableFrom(nc))
throw new ParseException(nc + " is not a ModelicaObject");
for (Class<?> iface : nc.getInterfaces()) {
if (iface == c)
return (Class<? extends T>) nc;
}
throw new ParseException(nc + " is not a " + c);
}

public static ModelicaObject parse(Reader r) throws IOException, ParseException {
skipWhiteSpace(r);
r.mark(1);
if (r.read() == -1) return new ModelicaVoid();
r.reset();
r.mark(6);
char[] cbuf = new char[6];
r.read(cbuf, 0, 6);
r.reset();
String s = new String(cbuf);
if (cbuf[0] == '{') return ModelicaArray.parse(r,SimpleTypeSpec.modelicaObject);
if (cbuf[0] == '(') return ModelicaTuple.parse(r,null);
if (cbuf[0] == '\"') return ModelicaString.parse(r);
if (s.startsWith("NONE(")) return ModelicaOption.parse(r,SimpleTypeSpec.modelicaObject);
if (s.startsWith("SOME(")) return ModelicaOption.parse(r,SimpleTypeSpec.modelicaObject);
if (s.startsWith("record")) return ModelicaRecord.parse(r);
if (s.startsWith("true")) return ModelicaBoolean.parse(r);
if (s.startsWith("false")) return ModelicaBoolean.parse(r);

try {
r.mark(100);
StringBuilder b = new StringBuilder();
Boolean bool = parseIntOrReal(r,b);
if (bool) {
return new ModelicaReal(Double.parseDouble(b.toString()));
} else {
return new ModelicaInteger(Integer.parseInt(b.toString()));
}
} catch (NumberFormatException e) {
r.reset();
throw new ParseException("Couldn't match any object");
}
}

public static void skipWhiteSpace(Reader r) throws IOException {
int i;
char c;
do {
r.mark(1);
i = r.read();
if (i == -1)
return;
c = (char) i;
} while (Character.isWhitespace(c));
r.reset();
}

/**
* Returns true if the value is a Real, else returns an Integer
*/
public static boolean parseIntOrReal(Reader r, StringBuilder b) throws ParseException, IOException {
boolean bool = false;
int i;
char ch;
skipWhiteSpace(r);
do {
r.mark(1);
i = r.read();
if (i == -1)
break;
ch = (char) i;
if (Character.isDigit(ch) || ch == '-')
b.append(ch);
else if (ch == 'e' || ch == 'E' || ch == '+' || ch == '.') {
b.append(ch);
bool = true;
} else {
r.reset();
break;
}
} while (true);
return bool;
}

static String lexIdent(Reader r) throws IOException, ParseException {
return lexIdent(r,true);
}

static String lexIdent(Reader r, boolean mark) throws IOException, ParseException {
int i;
char ch;
do {
i = r.read();
if (i == -1)
throw new ParseException("Expected identifier, got EOF");
ch = (char) i;
} while (Character.isWhitespace(ch));

StringBuffer b = new StringBuffer();
do {
if (ch == '_' || ch == '.' || Character.isLetterOrDigit(ch))
b.append(ch);
else {
break;
}
if (mark) r.mark(1);
i = r.read();
if (i == -1)
break;
ch = (char) i;
} while (true);
if (mark) r.reset();
if (b.length() == 0)
throw new ParseException("Expected identifier");
return b.toString();
}

@SuppressWarnings("unchecked")
public static <T extends ModelicaObject> T parse(Reader r, TypeSpec<T> spec) throws IOException, ParseException {
if (spec instanceof ComplexTypeSpec)
return parseComplex(r,(ComplexTypeSpec<T>) spec);
else
return parse(r,spec.getClassType());
}

@SuppressWarnings("unchecked")
private static <T extends ModelicaObject> T parse(Reader r, Class<T> c) throws IOException, ParseException {
if (c == ModelicaObject.class)
return (T)parse(r);
if (c.isInterface()) {
/* Uniontypes are special */
r.mark(500);
String rec = lexIdent(r,false);
if (!rec.equals("record"))
throw new ParseException("Expected 'record' got " + rec);
String id = lexIdent(r,false);
r.reset();
return parse(r,new SimpleTypeSpec<T>((Class<T>)findUniontypeRecordClass(c,id)));
}
try {
return (T) c.getMethod("parse", java.io.Reader.class).invoke(null, r);
} catch (Exception e) {
throw new ParseException(e);
}
}

@SuppressWarnings("unchecked")
public static <T extends ModelicaObject> T parseComplex(Reader r, ComplexTypeSpec<T> spec) throws IOException, ParseException {
Class<T> c = spec.getClassType();
TypeSpec<? extends ModelicaObject>[] specs = spec.getSubClassType();
if (specs.length > 1) {
if (c == ModelicaTuple.class)
return (T)ModelicaTuple.parse(r, specs);
} else if (specs.length == 1){
if (c == ModelicaArray.class)
return (T) ModelicaArray.parse(r, spec.getSubClassType()[0]);
if (c == ModelicaOption.class)
return (T)ModelicaOption.parse(r, spec.getSubClassType()[0]);
}
throw new ParseException("Couldn't find a complex class for " + c.getName() + " with " + specs.length + " types");
}
}
42 changes: 42 additions & 0 deletions c_runtime/java_interface/src/org/openmodelica/ModelicaArray.java
@@ -1,8 +1,12 @@
package org.openmodelica;

import java.io.IOException;
import java.io.Reader;
import java.util.Arrays;
import java.util.List;

import org.openmodelica.corba.parser.ParseException;

public class ModelicaArray<T extends ModelicaObject> extends ModelicaBaseArray<T> implements ModelicaObject {
private static final long serialVersionUID = 2151613083277374538L;
public int firstDim = 0;
Expand Down Expand Up @@ -157,4 +161,42 @@ public void setObject(ModelicaObject o) {
this.isFlat = arr.isFlat;
}

@SuppressWarnings("unchecked")
static <T extends ModelicaObject> ModelicaArray<T> parse(Reader r, TypeSpec<T> spec) throws IOException, ParseException {
ModelicaArray<T> arr = new ModelicaArray<T>();
ModelicaAny.skipWhiteSpace(r);
int i;
char ch;
i = r.read();
if (i == -1) throw new ParseException("EOF, expected array");
ch = (char) i;
if (ch != '{') throw new ParseException("Expected array");
ModelicaAny.skipWhiteSpace(r);
r.mark(1);
i = r.read();
if (i == -1) throw new ParseException("EOF, expected array");
ch = (char) i;
if (ch == '}') return new ModelicaArray<T>();
r.reset();
do {
ModelicaAny.skipWhiteSpace(r);
T o = ModelicaAny.parse(r,spec);
if (arr.size() > 0 && spec.getClass().equals(ModelicaObject.class))
try {
o = (T) ModelicaAny.cast(o, arr.get(0).getClass());
} catch (Exception ex) {
throw new ParseException("Array type mismatch: tried adding " + o + " to " + arr);
}
arr.add(o);
ModelicaAny.skipWhiteSpace(r);
i = r.read();
if (i == -1)
throw new ParseException("EOF, expected a comma or closing array");
ch = (char) i;
} while (ch == ',');
if (ch != '}') {
throw new ParseException("Expected closing array");
}
return arr;
}
}
30 changes: 30 additions & 0 deletions c_runtime/java_interface/src/org/openmodelica/ModelicaBoolean.java
@@ -1,5 +1,10 @@
package org.openmodelica;

import java.io.IOException;
import java.io.Reader;

import org.openmodelica.corba.parser.ParseException;

public class ModelicaBoolean implements ModelicaObject {
public boolean b;
public ModelicaBoolean(ModelicaObject o) {
Expand Down Expand Up @@ -42,4 +47,29 @@ public void setObject(ModelicaObject o) {
b = ((ModelicaBoolean) o).b;
}
}

public static ModelicaBoolean parse(Reader r) throws ParseException, IOException {
int i;
char ch;
ModelicaAny.skipWhiteSpace(r);
i = r.read();
if (i == -1) throw new ParseException("EOF, expected Boolean");
ch = (char) i;

char cbuf[];
if (ch == 't') {
cbuf = new char[3];
if (r.read(cbuf,0,3) == -1)
throw new ParseException("EOF, expected Boolean");
if (cbuf[0] == 'r' && cbuf[1] == 'u' && cbuf[2] == 'e')
return new ModelicaBoolean(true);
} else if (ch == 'f') {
cbuf = new char[4];
if (r.read(cbuf,0,4) == -1)
throw new ParseException("EOF, expected Boolean");
if (cbuf[0] == 'a' && cbuf[1] == 'l' && cbuf[2] == 's' && cbuf[3] == 'e')
return new ModelicaBoolean(false);
}
throw new ParseException("Expected Boolean");
}
}
Expand Up @@ -12,11 +12,11 @@ public ModelicaFunction(String functionName, SmartProxy proxy) {
this.functionName = functionName;
this.proxy = proxy;
}

public ModelicaFunctionReference getReference() {
return new ModelicaFunctionReference(functionName);
}

protected <T extends ModelicaObject> T call(Class<T> c, ModelicaObject... args) throws ConnectException, ParseException {
return proxy.callModelicaFunction(functionName, c, args);
}
Expand Down

0 comments on commit 44b7e3c

Please sign in to comment.