Model loading issues and new types
diff --git a/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/engine/MatlabEngine.java b/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/engine/MatlabEngine.java
index e4008f7..3b985a4 100644
--- a/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/engine/MatlabEngine.java
+++ b/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/engine/MatlabEngine.java
@@ -14,43 +14,71 @@
 
 import org.eclipse.epsilon.emc.simulink.exception.MatlabException;
 import org.eclipse.epsilon.emc.simulink.util.MatlabEngineUtil;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+@SuppressWarnings("unchecked")
 public class MatlabEngine {
 
-	/** ENGINE COMMANDS */
+	/** ENGINE STATIC METHODS */
 	private static final String CONNECT_MATLAB_METHOD = "connectMatlab";
+	private static final String CONNECT_MATLAB_ASYNC_METHOD = "connectMatlabAsync";
+	private static final String START_MATLAB_METHOD = "connectMatlab";
+	private static final String START_MATLAB_ASYNC_METHOD = "connectMatlabAsync";
+	private static final String FIND_MATLAB_METHOD = "connectMatlab";
+	private static final String FIND_MATLAB_ASYNC_METHOD = "connectMatlabAsync";
+
+	/** ENGINE METHODS */
 	private static final String GET_VARIABLE_METHOD = "getVariable";
+	private static final String GET_VARIABLE_ASYNC_METHOD = "getVariableAsync";
+	private static final String PUT_VARIABLE_METHOD = "putVariable";
+	private static final String PUT_VARIABLE_ASYNC_METHOD = "putVariableAsync";
 	private static final String EVAL_METHOD = "eval";
 	private static final String EVAL_ASYNC_METHOD = "evalAsync";
+	private static final String FEVAL_METHOD = "feval";
+	private static final String FEVAL_ASYNC_METHOD = "fevalAsync";
+	private static final String DISCONNECT_METHOD = "disconnect";
+	private static final String DISCONNECT_ASYNC_METHOD = "disconnectAsync";
+	private static final String QUIT_METHOD = "quit";
+	private static final String QUIT_ASYNC_METHOD = "quitAsync";
+	private static final String CLOSE_METHOD = "close";
 
 	private static final String RESULT = "result";
 	private static final String ASIGN = " = ";
 	private static final String PARAM_REGEX = "[?]";
 
-	/** ERRORS */
+	/** MATHWOWRKS CLASS */
+	private static final String MATLAB_ENGINE_CLASS = "com.mathworks.engine.MatlabEngine";
+	
+	/** ERRORS AND LOGS */
 	private static final String ERROR_INVALID_PARAMETER_NUMBER = "%d parameters were expected but %d were provided";
-
 	private static final Logger LOGGER = LoggerFactory.getLogger(MatlabEngine.class);
 	
 	/** VARIABLES */
 	protected Object engine;
-	protected Method evalMethod;
+	private static Class<?> engine_class;
+
+	/** METHODS */
 	protected Method getVariableMethod;
+	protected Method getVariableAsyncMethod;
+	protected Method putVariableMethod;
+	protected Method putVariableAsyncMethod;
+	protected Method evalMethod;
 	protected Method evalAsyncMethod;
+	protected Method fevalMethod;
+	protected Method fevalAsyncMethod;
+	protected Method closeMethod;
+	protected Method quitMethod;
+	protected Method disconnectMethod;
+	
 
 	public MatlabEngine(Class<?> matlabEngineClass) throws Exception {
 		try{
 			engine = matlabEngineClass.getMethod(CONNECT_MATLAB_METHOD).invoke(null);
 		} catch (Exception e) {
-			System.out.println("retrying connection");
+			LOGGER.debug("retrying connection");
 			engine = matlabEngineClass.getMethod(CONNECT_MATLAB_METHOD).invoke(null);
 		}
-		evalMethod = engine.getClass().getMethod(EVAL_METHOD, String.class);
-		getVariableMethod = engine.getClass().getMethod(GET_VARIABLE_METHOD, String.class);
-		evalAsyncMethod = engine.getClass().getMethod(EVAL_ASYNC_METHOD, String.class);
 	}
 
 	public Object evalWithSetupAndResult(String setup, String cmd, Object... parameters) throws MatlabException {
@@ -83,7 +111,96 @@
 		eval(cmd);
 	}
 
+	/** CLASS HELPERS */
+	public static boolean is(Object obj) {
+		return (getMatlabClass() == null) ? false : getMatlabClass().isInstance(obj);  
+	}
+	
+	protected static Class<?> getMatlabClass() {
+		if (engine_class == null) {
+			try {
+				engine_class = ClassLoader.getSystemClassLoader().loadClass(MATLAB_ENGINE_CLASS);
+			} catch (ClassNotFoundException e) {
+				e.printStackTrace();
+			}
+		}
+		return engine_class;
+	}
+	
+	public MatlabEngine(Object engine) {
+		if (is(engine)) {
+			this.engine = engine;
+		}
+	}
+	
+	/** CLASS METHODS */
+	
+	public static MatlabEngine startMatlab() throws MatlabException {
+		try {
+			Method startMatlabMethod = engine_class.getMethod(START_MATLAB_METHOD);
+			Object returnedEngine = startMatlabMethod.invoke(null);
+			return new MatlabEngine(returnedEngine);
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw new MatlabException(e); 
+		}
+	}
+	
+	public static MatlabEngine startMatlab(String[] options) throws MatlabException {
+		try {
+			Method startMatlabMethod = engine_class.getMethod(START_MATLAB_METHOD, String[].class);
+			Object returnedEngine = startMatlabMethod.invoke(null, options);
+			return new MatlabEngine(returnedEngine);
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw new MatlabException(e); 
+		}
+	}
+	
+	public static String[] findMatlab() throws MatlabException {
+		try {
+			Method findMatlabMethod = engine_class.getMethod(FIND_MATLAB_METHOD);
+			return (String[]) findMatlabMethod.invoke(null);
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw new MatlabException(e); 
+		}
+	}
+	
+	public static MatlabEngine connectMatlab() throws MatlabException {
+		try {
+			Method connectMatlabMethod = engine_class.getMethod(CONNECT_MATLAB_METHOD);
+			Object returnedEngine = connectMatlabMethod.invoke(null);
+			return new MatlabEngine(returnedEngine);		
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw new MatlabException(e); 
+		}
+	}
+	
+	public static MatlabEngine connectMatlab(String name) throws MatlabException {
+		try {
+			Method connectMatlabMethod = engine_class.getMethod(CONNECT_MATLAB_METHOD, String.class);
+			Object returnedEngine = connectMatlabMethod.invoke(null, name);
+			return new MatlabEngine(returnedEngine);		
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw new MatlabException(e); 
+		}
+	}
+	
+	// TODO continue with the asynchronous static class methods 
+	
+	/** OBJECT METHODS */
+	
 	public void eval(String cmd) throws MatlabException {
+		if (evalMethod == null) {
+			try {
+				evalMethod = engine.getClass().getMethod(EVAL_METHOD, String.class);
+			} catch (Exception e) {
+				throw new MatlabException(e);
+			}
+		}
 		try {
 			LOGGER.debug(cmd);
 			evalMethod.invoke(engine, cmd);
@@ -93,19 +210,111 @@
 		}
 	}
 
+	public Future<Void> evalAsync(String cmd) throws MatlabException {
+		if (evalAsyncMethod == null) {
+			try {
+				evalAsyncMethod = engine.getClass().getMethod(EVAL_ASYNC_METHOD, String.class);
+			} catch (Exception e) {
+				throw new MatlabException(e);
+			}
+		}
+		try {
+			return (Future<Void>) evalAsyncMethod.invoke(engine, cmd);
+		} catch (Exception e) {
+			throw new MatlabException(e);
+		}
+	}
+	
 	public Object getVariable(String variable) throws MatlabException {
+		if (getVariableMethod == null) {
+			try {
+				getVariableMethod = engine.getClass().getMethod(GET_VARIABLE_METHOD, String.class);
+			} catch (Exception e) {
+				throw new MatlabException(e);
+			}
+		}
 		try {
 			return MatlabEngineUtil.parseMatlabEngineVariable(getVariableMethod.invoke(engine, variable));
 		} catch (Exception e) {
 			throw new MatlabException(e);
 		}
 	}
-
-	@SuppressWarnings("unchecked")
-	public Future<Void> evalAsync(String cmd) throws MatlabException {
+	
+	/*
+	// FIXME
+	public <T> Future<T> getVariableAsync(String variable) throws MatlabException {
+		if (getVariableAsyncMethod == null) {
+			try {
+				getVariableAsyncMethod = engine.getClass().getMethod(GET_VARIABLE_ASYNC_METHOD, String.class);
+			} catch (Exception e) {
+				throw new MatlabException(e);
+			}
+		}
 		try {
-			Method evalSyncMethod = engine.getClass().getMethod(EVAL_ASYNC_METHOD, String.class);
-			return (Future<Void>) evalSyncMethod.invoke(engine, cmd);
+			Future<T> response = (Future<T>) getVariableAsyncMethod.invoke(engine, variable);
+			// TODO Parse into T
+			return (Future<T>) response;
+		} catch (Exception e) {
+			throw new MatlabException(e);
+		}
+	}*/
+
+	public void putVariable(String variableName, Object value) throws MatlabException {
+		if (putVariableMethod == null) {
+			try {
+				putVariableMethod = engine.getClass().getMethod(PUT_VARIABLE_METHOD, String.class, Object.class);
+			} catch (Exception e) {
+				throw new MatlabException(e);
+			}
+		}
+		try {
+			putVariableMethod.invoke(engine, variableName, value);
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw new MatlabException(e);
+		}
+	}
+	
+	public void close() throws MatlabException {
+		if (closeMethod == null) {
+			try {
+				closeMethod = engine.getClass().getMethod(CLOSE_METHOD);
+			} catch (Exception e) {
+				throw new MatlabException(e);
+			}
+		}
+		try {
+			closeMethod.invoke(engine);
+		} catch (Exception e) {
+			throw new MatlabException(e);
+		}
+	}
+	
+	public void quit() throws MatlabException {
+		if (quitMethod == null) {
+			try {
+				quitMethod = engine.getClass().getMethod(QUIT_METHOD);
+			} catch (Exception e) {
+				throw new MatlabException(e);
+			}
+		}
+		try {
+			quitMethod.invoke(engine);
+		} catch (Exception e) {
+			throw new MatlabException(e);
+		}
+	}
+	
+	public void disconnect() throws MatlabException {
+		if (disconnectMethod == null) {
+			try {
+				disconnectMethod = engine.getClass().getMethod(DISCONNECT_METHOD);
+			} catch (Exception e) {
+				throw new MatlabException(e);
+			}
+		}
+		try {
+			disconnectMethod.invoke(engine);
 		} catch (Exception e) {
 			throw new MatlabException(e);
 		}
diff --git a/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/engine/MatlabEngineCommands.java b/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/engine/MatlabEngineCommands.java
index 960f313..b63bb1c 100644
--- a/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/engine/MatlabEngineCommands.java
+++ b/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/engine/MatlabEngineCommands.java
@@ -33,41 +33,4 @@
 	public static final String GET_PROPERTY_FROM_HANDLE = HANDLE + GET_HANDLE_PROPERTY;
 	public static final String SET_PROPERTY_TO_HANDLE = HANDLE + SET_HANDLE_PROPERTY;
 	
-	private static final int SILENT = 0;
-	private static final int DEBUG = 1;
-	
-	protected static String chain(String[] commands, int mode) {
-		StringBuilder builder = new StringBuilder();
-		for(String s : commands) {
-			String sep = " ";
-			switch (mode) {
-			case SILENT:
-				// Does not print command result
-				sep = COMMAND_END; 
-			case DEBUG:
-				// Prints command result at end of line
-				sep = LINE_BREAK; 
-			}
-		    builder.append(s + sep);
-		}
-		return builder.toString();
-	}
-	
-	public static String simulinkHandle(String cmd, String handle, Object...params) {
-		if (handle == null || handle.isEmpty()) {
-			handle = "handle";
-		}
-		String c = cmd + "(" + handle;
-		for (Object parameter : params) 
-			c += ", '" + String.valueOf(parameter).replace("'", "''") + "'";
-		return c + ")";
-	}
-	public static String simulink(String cmd, Object...params) {
-		return simulinkHandle(cmd, "handle", params);
-	}
-	
-	public static String cmd(String cmd, Object... args) {
-		return String.format(cmd, args);
-	}
-	
 }
diff --git a/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/engine/MatlabEnginePool.java b/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/engine/MatlabEnginePool.java
index 7424de4..5b80b24 100644
--- a/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/engine/MatlabEnginePool.java
+++ b/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/engine/MatlabEnginePool.java
@@ -26,12 +26,13 @@
 	private static final String SYS_PATHS = "sys_paths";
 
 	protected static MatlabEnginePool instance;
+	protected static URLClassLoader systemURLClassLoader;
+	protected static String libraryPath;
+	protected static String engineJarPath;
 
 	protected Set<MatlabEngine> pool = new LinkedHashSet<MatlabEngine>();
 	protected Class<?> matlabEngineClass;
-	protected String libraryPath = "";
-	protected String engineJarPath = "";
-
+	
 	private MatlabEnginePool(String libraryPath, String engineJarPath) throws MatlabRuntimeException {
 
 		this.libraryPath = libraryPath;
@@ -49,7 +50,7 @@
 
 			URL engineJarPathURL = new File(engineJarPath).toURI().toURL();
 
-			URLClassLoader systemURLClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
+			systemURLClassLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
 
 			Method method = urlClassLoaderClass.getDeclaredMethod("addURL", urlClass);
 			method.setAccessible(true);
@@ -60,7 +61,7 @@
 			throw new MatlabRuntimeException("Make sure to properly configure the library path and MATLAB engine Jar in Epsilon/Simulink preferences");
 		}
 	}
-
+	
 	public static MatlabEnginePool getInstance(String libraryPath, String engineJarPath) throws MatlabRuntimeException {
 		if (instance == null || (instance != null && (!libraryPath.equalsIgnoreCase(instance.getLibraryPath())
 				|| !engineJarPath.equalsIgnoreCase(instance.getEngineJarPath())))) {
diff --git a/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/model/SimulinkModel.java b/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/model/SimulinkModel.java
index 0a9ce83..922b997 100644
--- a/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/model/SimulinkModel.java
+++ b/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/model/SimulinkModel.java
@@ -60,9 +60,9 @@
 	public static final String SIMULINK = "Simulink";

 	public static final String STATEFLOW = "Stateflow";

 

-	public static final String PWD = "cd ?;";

+	public static final String PWD = "cd '?';";

 	public static final String GET_PARAM = "get_param('?', 'Handle');";

-	public static final String LOAD_SYSTEM = "load_system(?)";

+	public static final String LOAD_SYSTEM = "load_system('?')";

 	public static final String OPEN_SYSTEM = "open_system('?')";

 	public static final String NEW_SYSTEM = "new_system('?', 'Model');";

 	public static final String SAVE_SYSTEM = "save_system('?', '?');";

@@ -104,27 +104,33 @@
 			engine = MatlabEnginePool.getInstance(libraryPath, engineJarPath).getMatlabEngine();

 			simulinkOperationContributor = new ModelOperationContributor(engine);

 				

-			if (workingDir != null) {

+			if ((workingDir != null && workingDir.exists())) {

 				try {

 					engine.eval(PWD, workingDir);

 				} catch (Exception ex) {

 					LOGGER.info(ex.getMessage());

 				}

 			}

-			String cmd = showInMatlabEditor ? OPEN_SYSTEM : LOAD_SYSTEM;

-			boolean useNew = false;

-			if (!readOnLoad) {

+			

+			if (readOnLoad) {

+				String cmd = showInMatlabEditor ? OPEN_SYSTEM : LOAD_SYSTEM;

+				try{

+					engine.eval(cmd, file.getAbsolutePath());				

+				} catch (Exception e) {

+					try {

+						engine.eval(NEW_SYSTEM, getSimulinkModelName());

+					} catch (Exception ex) {

+						// Ignore; system already exists

+					}

+				}

+			} else {

 				try {

 					engine.eval(NEW_SYSTEM, getSimulinkModelName());

 				} catch (Exception ex) {

-					useNew = true;// System already exists	

-				}					

+					// Ignore; system already exists

+				}

 			}

-			if (useNew) {				

-				engine.eval(cmd, getSimulinkModelName());

-			} else {

-				engine.eval(cmd, "" + file.getAbsolutePath() + "");

-			}

+			

 			this.handle = (Double) engine.evalWithResult(GET_PARAM, getSimulinkModelName());

 		} catch (Exception e) {

 			throw new EolModelLoadingException(e, this);

@@ -300,7 +306,7 @@
 		SimulinkModel model = new SimulinkModel();

 		model.setName("M");

 		model.setFile(tmpFile);

-		model.setWorkingDir(tmpFile.getParentFile());

+		model.setWorkingDir(null);

 		model.setReadOnLoad(false);

 		model.setStoredOnDisposal(false);

 		model.setShowInMatlabEditor(true);

@@ -521,6 +527,14 @@
 		}

 	}

 	

+	public Object statementWithResult(String statement) throws EolRuntimeException {

+		try{

+			return engine.evalWithResult(statement);

+		} catch (MatlabException e) {

+			throw new EolRuntimeException(e.getMessage());

+		}

+	}

+	

 	public Object getWorkspaceVariable(String value) {

 		try {

 			return MatlabEngineUtil.parseMatlabEngineVariable(engine,value);

diff --git a/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/types/CellStr.java b/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/types/CellStr.java
new file mode 100644
index 0000000..2862856
--- /dev/null
+++ b/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/types/CellStr.java
@@ -0,0 +1,107 @@
+/*********************************************************************
+* Copyright (c) 2008 The University of York.
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+**********************************************************************/
+package org.eclipse.epsilon.emc.simulink.types;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+public class CellStr {
+
+	private static final String CELL_STR_MATLAB_CLASS = "com.mathworks.matlab.types.CellStr";
+
+	private static Class<?> cell_str_class;
+
+	protected Object cellStr;
+
+	protected Method getStringArrayMethod;
+	
+	protected Method equalsMethod;
+	
+	public static boolean is(Object obj) {
+		return (getMatlabClass() == null) ? false : getMatlabClass().isInstance(obj);  
+	}
+	
+	protected static Class<?> getMatlabClass() {
+		if (cell_str_class == null) {
+			try {
+				cell_str_class = ClassLoader.getSystemClassLoader().loadClass(CELL_STR_MATLAB_CLASS);
+			} catch (ClassNotFoundException e) {
+				e.printStackTrace();
+			}
+		}
+		return cell_str_class;
+	}
+	
+	public CellStr(Object cellStr) {
+		if (is(cellStr)) {
+			this.cellStr = cellStr;
+			init();
+		}
+	}
+	
+	public CellStr(String[] stringArray) {
+		try {
+			Constructor<?> constructor = getMatlabClass().getConstructor(String[].class);
+			cellStr = constructor.newInstance(stringArray);
+		} catch (NoSuchMethodException | SecurityException e) {
+			e.printStackTrace();
+			System.out.println("Problem retrieving constructor of the complex type");
+		} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
+				| InvocationTargetException e) {
+			System.out.println("Problem instantiating the complex type");
+			e.printStackTrace();
+		}		
+	}
+	
+	public CellStr(String[][] stringArray) {
+		try {
+			Constructor<?> constructor = getMatlabClass().getConstructor(String[][].class);
+			cellStr = constructor.newInstance(stringArray);
+		} catch (NoSuchMethodException | SecurityException e) {
+			e.printStackTrace();
+			System.out.println("Problem retrieving constructor of the complex type");
+		} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
+				| InvocationTargetException e) {
+			System.out.println("Problem instantiating the complex type");
+			e.printStackTrace();
+		}		
+	}
+	
+	private void init() {
+		Class<?> clazz = getMatlabClass();
+		try {
+			getStringArrayMethod = getStringArrayMethod == null ? clazz.getDeclaredMethod("getStringArray") : null;
+			equalsMethod = equalsMethod == null ? clazz.getDeclaredMethod("equals", Object.class) : null;
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+	
+	public Object getStringArray() {
+		try {
+			return (Integer) getStringArrayMethod.invoke(cellStr);
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw new IllegalStateException(e.getMessage());
+		}
+	}
+	
+	public boolean equals(Object object){
+		try {
+			return (Boolean) equalsMethod.invoke(cellStr, object);
+		} catch (Exception e) {
+			e.printStackTrace();
+			throw new IllegalStateException(e.getMessage());
+		}
+		
+	}
+
+}
diff --git a/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/types/HandleObject.java b/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/types/HandleObject.java
new file mode 100644
index 0000000..85ed791
--- /dev/null
+++ b/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/types/HandleObject.java
@@ -0,0 +1,40 @@
+/*********************************************************************
+* Copyright (c) 2008 The University of York.
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+**********************************************************************/
+package org.eclipse.epsilon.emc.simulink.types;
+
+public class HandleObject {
+
+	private static final String HANDLE_OBJECT_MATLAB_CLASS = "com.mathworks.matlab.types.HandleObject";
+	private static Class<?> handle_object_class;
+
+	private Object handle;
+
+	public static boolean is(Object obj) {
+		return (getMatlabClass() == null) ? false : getMatlabClass().isInstance(obj);
+	}
+
+	private static Class<?> getMatlabClass() {
+		if (handle_object_class == null) {
+			try {
+				handle_object_class = ClassLoader.getSystemClassLoader().loadClass(HANDLE_OBJECT_MATLAB_CLASS);
+			} catch (ClassNotFoundException e) {
+				e.printStackTrace();
+			}
+		}
+		return handle_object_class;
+	}
+
+	public HandleObject(Object complex) {
+		if (is(complex)) {
+			this.handle = complex;
+		}
+	}
+	
+}
diff --git a/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/types/Struct.java b/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/types/Struct.java
index aca90ab..93147da 100644
--- a/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/types/Struct.java
+++ b/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/types/Struct.java
@@ -10,7 +10,14 @@
 package org.eclipse.epsilon.emc.simulink.types;
 
 import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
 import java.util.Set;
+import java.util.stream.Collector;
+import java.util.stream.Collectors;
+
+import org.eclipse.epsilon.emc.simulink.util.MatlabEngineUtil;
 
 public class Struct {
 
@@ -134,7 +141,8 @@
 	
 	public Object get(Object key) {
 		try {
-			return (Object) getMethod.invoke(struct, key);
+			Object val = getMethod.invoke(struct, key);
+			return MatlabEngineUtil.parseMatlabEngineVariable(val);
 		} catch (Exception e) {
 			e.printStackTrace();
 			throw new IllegalStateException(e.getMessage());
@@ -167,7 +175,9 @@
 	}
 	public Set<?> keySet() {
 		try {
-			return (Set<?>) keySetMethod.invoke(struct);
+			Set<?> set = (Set<?>) keySetMethod.invoke(struct);
+			return set.stream().map(e -> MatlabEngineUtil.parseMatlabEngineVariable(e)).collect(Collectors.toSet());
+
 		} catch (Exception e) {
 			e.printStackTrace();
 			throw new IllegalStateException(e.getMessage());
@@ -181,9 +191,13 @@
 			throw new IllegalStateException(e.getMessage());
 		}
 	}
+	
+	@SuppressWarnings({ "rawtypes", "unchecked" })
 	public Set<?> values() {
 		try {
-			return (Set<?>) valuesMethod.invoke(struct);
+			
+			Set<?> set = new HashSet((Collection) valuesMethod.invoke(struct));
+			return set.stream().map(e -> MatlabEngineUtil.parseMatlabEngineVariable(e)).collect(Collectors.toSet());
 		} catch (Exception e) {
 			e.printStackTrace();
 			throw new IllegalStateException(e.getMessage());
@@ -192,7 +206,7 @@
 	
 	@Override
 	public String toString() {
-		return "Struct: [" +  entrySet().toString() + "]";
+		return "Struct: [" +  keySet().toString() + "]";
 	}
 
 }
diff --git a/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/util/MatlabEngineUtil.java b/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/util/MatlabEngineUtil.java
index 6b9f6e8..82e8087 100644
--- a/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/util/MatlabEngineUtil.java
+++ b/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/util/MatlabEngineUtil.java
@@ -14,6 +14,9 @@
 
 import org.eclipse.epsilon.emc.simulink.engine.MatlabEngine;
 import org.eclipse.epsilon.emc.simulink.exception.MatlabException;
+import org.eclipse.epsilon.emc.simulink.types.CellStr;
+import org.eclipse.epsilon.emc.simulink.types.Complex;
+import org.eclipse.epsilon.emc.simulink.types.HandleObject;
 import org.eclipse.epsilon.emc.simulink.types.Struct;
 
 public class MatlabEngineUtil {
@@ -90,6 +93,10 @@
 	}
 
 	public static Object parseMatlabEngineVariable(Object value) {
+		if (value == null)
+			return null;
+		if (HandleObject.is(value))
+			return new HandleObject(value);
 		if (value instanceof byte[])
 			return MatlabEngineUtil.matlabArrayToList((byte[]) value);
 		if (value instanceof short[])
@@ -112,8 +119,13 @@
 			return String.valueOf(value);
 		if (value instanceof String) 
 			return String.valueOf(value);
+		
 		if (Struct.is(value))
 			return new Struct(value);
+		if (Complex.is(value))
+			return new Complex(value);
+		if (CellStr.is(value))
+			return new CellStr(value);
 		return value;
 	}
 }
diff --git a/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/util/SimulinkUtil.java b/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/util/SimulinkUtil.java
index 8e52d6a..efbd00d 100644
--- a/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/util/SimulinkUtil.java
+++ b/plugins/org.eclipse.epsilon.emc.simulink/src/org/eclipse/epsilon/emc/simulink/util/SimulinkUtil.java
@@ -11,7 +11,6 @@
 
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.List;
 import java.util.stream.Collectors;
 
diff --git a/tests/org.eclipse.epsilon.emc.simulink.test/resources/models/sldemo_varsize_basic_copy.slx b/tests/org.eclipse.epsilon.emc.simulink.test/resources/models/sldemo_varsize_basic_copy.slx
new file mode 100644
index 0000000..21f61da
--- /dev/null
+++ b/tests/org.eclipse.epsilon.emc.simulink.test/resources/models/sldemo_varsize_basic_copy.slx
Binary files differ
diff --git a/tests/org.eclipse.epsilon.emc.simulink.test/src/org/eclipse/epsilon/emc/simulink/test/unit/SimulinkSimpleTypeTest.java b/tests/org.eclipse.epsilon.emc.simulink.test/src/org/eclipse/epsilon/emc/simulink/test/unit/SimulinkSimpleTypeTest.java
new file mode 100644
index 0000000..a1561cc
--- /dev/null
+++ b/tests/org.eclipse.epsilon.emc.simulink.test/src/org/eclipse/epsilon/emc/simulink/test/unit/SimulinkSimpleTypeTest.java
@@ -0,0 +1,76 @@
+/*********************************************************************
+* Copyright (c) 2008 The University of York.
+*
+* This program and the accompanying materials are made
+* available under the terms of the Eclipse Public License 2.0
+* which is available at https://www.eclipse.org/legal/epl-2.0/
+*
+* SPDX-License-Identifier: EPL-2.0
+**********************************************************************/
+package org.eclipse.epsilon.emc.simulink.test.unit;
+
+import org.eclipse.epsilon.emc.simulink.test.util.AbstractSimulinkTest;
+import org.eclipse.epsilon.emc.simulink.test.util.FileUtils;
+import org.junit.Before;
+import org.junit.Test;
+
+public class SimulinkSimpleTypeTest extends AbstractSimulinkTest {
+
+	@Before
+	public void setup(){
+		activeCache = false;
+		modelFile = FileUtils.getModelFile("sldemo_varsize_basic_copy.slx");		
+	}
+
+	@Test
+	public void testSID() {
+		eol = "M.statement(\"a= Simulink.ID.getSID('sldemo_varsize_basic_copy/Constant')\"); M.getWorkspaceVariable('a').println();";
+	}
+	
+	@Test
+	public void testSIDwithResult() {
+		eol = "M.statementWithResult(\"Simulink.ID.getSID('sldemo_varsize_basic_copy/Constant')\").println();";
+	}
+	
+	@Test
+	public void testNames() {
+		eol = 	  "var selector = Selector.all().first();"
+				+ "var params = selector.collect(c | c.ObjectParameters).first().println('params: '); "
+				+ "var values = params.keySet().println('params: '); "
+				+ "for (v in values){ "
+				+ " var e = params.get(v); "
+				+ " if (e.Type == 'matrix'){ "
+				+ " (v + ' ' + e.Type).println();} "
+				+ "}"
+				+ "params.values().collect(v|v.Type).asSet().println('set: '); ";
+	}
+	
+	@Test
+	public void testTypes() {
+		eol = 	  "var selector = Selector.all().first();"
+
+				//+ "selector.Capabilities.println('matrix: '); " //matrix UNSPORTED BY MATLAB
+				+ "selector.ModelParamTableInfo.println('matrix: '); " //matrix
+				+ "selector.IndexOptionArray.println('matrix: '); " //matrix
+				+ "selector.RuntimeObject.println('matrix: '); " //matrix
+				
+				+ "selector.Orientation.println('e num: ');" // enum
+				
+				+ "selector.Handle.println('real: ' );" // real
+				+ "selector.FontSize.println('real: ');" // real
+				
+				+ "selector.MaskObject.println('object: ');" // object
+				
+				+ "selector.RTWdata.println('list: ');" // list
+				
+				// COPLEX
+				+ "M.statement('z=roots([1.0, -1.0, 6.0])');"
+				+ "M.statement('zc=conj(z)');"
+				+ "M.statement('rat=z.*zc');"
+				+ "M.getWorkspaceVariable('z').println('complex: ');"
+				+ "M.getWorkspaceVariable('zc').println('complex: ');"
+				+ "M.getWorkspaceVariable('rat').println('complex: ');"
+				;
+	}
+
+}
\ No newline at end of file
diff --git a/tests/org.eclipse.epsilon.emc.simulink.test/src/org/eclipse/epsilon/emc/simulink/test/util/AssumeMatlabInstalled.java b/tests/org.eclipse.epsilon.emc.simulink.test/src/org/eclipse/epsilon/emc/simulink/test/util/AssumeMatlabInstalled.java
index f6f091e..0402658 100644
--- a/tests/org.eclipse.epsilon.emc.simulink.test/src/org/eclipse/epsilon/emc/simulink/test/util/AssumeMatlabInstalled.java
+++ b/tests/org.eclipse.epsilon.emc.simulink.test/src/org/eclipse/epsilon/emc/simulink/test/util/AssumeMatlabInstalled.java
@@ -32,7 +32,7 @@
 		} catch (Exception e) {}
 	}
 
-	public static String getVersion() {
+	public String getVersion() {
 		return version;
 	}