oms3.dsl.Model Maven / Gradle / Ivy
package oms3.dsl;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import oms3.ComponentException;
import oms3.annotations.Name;
import oms3.io.CSProperties;
import oms3.io.DataIO;
import oms3.util.Components;
public class Model implements Buildable {
protected static final Logger log = Logger.getLogger("oms3.sim");
String classname;
List params = new ArrayList();
Resource res;
Logging l = new Logging();
//
KVPContainer comps = new KVPContainer();
KVPContainer out2in = new KVPContainer();
KVPContainer feedback = new KVPContainer();
String iter;
//
private URLClassLoader modelClassLoader;
@Override
public Buildable create(Object name, Object value) {
if (name.equals("parameter")) {
Params p = new Params();
params.add(p);
return p;
} else if (name.equals("resource")) {
res.addResource(value);
return LEAF;
} else if (name.equals("logging")) {
return l;
} else if (name.equals("components")) {
return comps;
} else if (name.equals("connect")) {
return out2in;
} else if (name.equals("feedback")) {
return feedback;
}
throw new ComponentException("Unknown element: '" + name.toString() + "'");
}
public Logging getComponentLogging() {
return l;
}
public Resource getRes() {
return res;
}
public void setRes(Resource res) {
this.res = res;
}
public void setIter(String iter) {
this.iter = iter;
}
public void setClassname(String classname) {
this.classname = classname;
}
public List getParams() {
return params;
}
public String getLibpath() {
List f = res.filterDirectories();
StringBuilder b = new StringBuilder();
for (int i = 0; i < f.size(); i++) {
b.append(f.get(i));
if (i < f.size() - 1) {
b.append(File.pathSeparatorChar);
}
}
return b.toString();
}
private static List getExtraResources() {
List sc = new ArrayList();
String simPath = System.getProperty("oms.sim.resources");
if (log.isLoggable(Level.CONFIG)) {
log.config("oms.sim.resources '" + simPath + "'");
}
if (simPath != null && !simPath.isEmpty()) {
simPath = simPath.replaceAll("\"", "");
for (String s : simPath.split("\\s*" + File.pathSeparator + "\\s*")) {
sc.add(new File(s));
}
}
return sc;
}
/** get the URL class loader for all the resources (just for jar files
*
* @return
* @throws Exception
*/
private synchronized URLClassLoader getClassLoader() {
if (modelClassLoader == null) {
List jars = res.filterFiles("jar"); // jars as defined in
List cli_jars = getExtraResources(); // cli extra jars
List dirs = res.filterDirectories(); // testing
List urls = new ArrayList();
try {
for (int i = 0; i < jars.size(); i++) {
urls.add(jars.get(i).toURI().toURL());
if (log.isLoggable(Level.CONFIG)) {
log.config("classpath entry from simulation: " + jars.get(i));
}
}
for (int i = 0; i < dirs.size(); i++) {
urls.add(dirs.get(i).toURI().toURL());
if (log.isLoggable(Level.CONFIG)) {
log.config("dir entry: " + dirs.get(i));
}
}
for (int i = 0; i < cli_jars.size(); i++) {
urls.add(cli_jars.get(i).toURI().toURL());
if (log.isLoggable(Level.CONFIG)) {
log.config("classpath entry from CLI: " + cli_jars.get(i));
}
}
} catch (MalformedURLException ex) {
throw new ComponentException("Illegal resource:" + ex.getMessage());
}
modelClassLoader = new URLClassLoader(urls.toArray(new URL[0]),
Thread.currentThread().getContextClassLoader());
}
return modelClassLoader;
}
public Object getComponent() throws Exception {
URLClassLoader loader = getClassLoader();
if (classname == null) {
return getGeneratedComponent(loader);
}
try {
Class c = loader.loadClass(getComponentClassName(classname));
return c.newInstance();
} catch (ClassNotFoundException E) {
throw new IllegalArgumentException("Component/Model not found '" + classname + "'");
}
}
public List getParam() {
List parameter = new ArrayList();
for (Params paras : getParams()) {
parameter.addAll(paras.getParam());
}
return parameter;
}
public CSProperties getParameter() throws IOException {
CSProperties p = DataIO.properties();
for (Params paras : getParams()) {
String f = paras.getFile();
if (f != null) {
p.putAll(DataIO.properties(new FileReader(new File(f)), "Parameter"));
}
for (Param param : paras.getParam()) {
p.put(param.getName(), param.getValue());
}
}
return p;
}
static Object get(Map inst, String key) {
Object val = inst.get(key);
if (val == null) {
throw new IllegalArgumentException("No such component name '" + key + "'");
}
return val;
}
Map nameClassMap;
private Map getName_ClassMap() {
if (nameClassMap == null) {
nameClassMap = new HashMap();
for (URL url : getClassLoader().getURLs()) {
try {
List> l = Components.getComponentClasses(url);
for (Class> class1 : l) {
Name name = class1.getAnnotation(Name.class);
if (name != null && !name.value().isEmpty()) {
if (name.value().indexOf(".") > -1) {
log.warning("@Name cannot contain '.' character : " + name.value() + " in " + class1.getName());
continue;
}
String prev = nameClassMap.put(name.value(), class1.getName());
if (prev != null) {
log.warning("duplicate @Name: " + name.value() + " for " + prev + " and " + class1.getName());
}
}
}
} catch (IOException E) {
throw new ComponentException("Cannot access: " + url);
}
}
}
return nameClassMap;
}
private String getComponentClassName(String id) {
if (id.indexOf('.') == -1) {
String cn = getName_ClassMap().get(id);
if (cn == null) {
throw new ComponentException("Unknown component name: " + id);
}
return cn;
}
return id;
}
Object getGeneratedComponent(URLClassLoader loader) {
try {
oms3.compiler.Compiler tc = oms3.compiler.Compiler.singleton(loader);
String name = "Comp_" + UUID.randomUUID().toString().replace('-', '_');
String cl = generateSource(name, loader);
if (log.isLoggable(Level.FINE)) {
log.fine("Generated Source:\n" + cl);
}
Class jc = tc.compileSource(name, cl);
return jc.newInstance();
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
private String generateSource(String cname, URLClassLoader loader) throws Exception {
String sc = "oms3.Compound";
if (iter != null) {
sc = "oms3.control.Iteration";
}
StringBuilder b = new StringBuilder();
b.append("import java.util.*;\n");
b.append("import oms3.*;\n");
b.append("import oms3.annotations.*;\n");
b.append("public class " + cname + " extends " + sc + " {\n");
b.append("\n");
// Fields
for (Param param : getParam()) {
String p = param.getName();
if (p.indexOf('.') == -1) {
throw new IllegalArgumentException("Not a valid parameter reference (object.field): '" + p + "'");
}
String[] name = p.split("\\.");
if (name.length != 2) {
throw new IllegalArgumentException("Not a valid parameter reference (object.field): '" + p + "'");
}
String type = getClassForParameter(name[0], name[1]);
b.append(" // " + p + "\n");
b.append(" @Role(Role.PARAMETER)\n");
b.append(" @In public " + type + " " + name[0] + "_" + name[1] + ";\n");
b.append("\n");
}
Map nameClassMap = null;
// Components
for (KVP def : comps.entries) {
String classname = def.getValue().toString();
classname = getComponentClassName(classname); // name -> class
b.append(" public " + classname + " " + def.getKey() + " = new " + classname + "();\n");
}
b.append("\n");
b.append("\n");
// init version.
b.append(" @Initialize\n");
b.append(" public void init() {\n");
if (iter != null) {
String[] it = iter.split("\\.");
b.append(" conditional(" + it[0] + ", \"" + it[1] + "\");\n");
}
// in2in
for (Param param : getParam()) {
String[] name = param.getName().split("\\.");
b.append(" in2in(\"" + name[0] + '_' + name[1] + "\", " + name[0] + ", \"" + name[1] + "\");\n");
}
// out2in
for (KVP c : out2in.entries) {
String[] from = c.getKey().split("\\.");
String[] to = c.getValue().toString().split("\\.");
b.append(" out2in(" + from[0] + ", \"" + from[1] + "\", " + to[0] + ", \"" + to[1] + "\");\n");
}
// feedback
for (KVP kvp : feedback.entries) {
String[] from = kvp.getKey().split("\\.");
String[] to = kvp.getValue().toString().split("\\.");
b.append(" feedback(" + from[0] + ", \"" + from[1] + "\", " + to[0] + ", \"" + to[1] + "\");\n");
}
b.append(" initializeComponents();\n");
b.append(" }\n");
b.append("}\n");
return b.toString();
}
String getClassForParameter(String object, String parameter) {
for (KVP def : comps.entries) {
if (object.equals(def.getKey())) {
String clname = def.getValue().toString();
clname = getComponentClassName(clname);
Class c;
try {
c = getClassLoader().loadClass(clname);
} catch (ClassNotFoundException ex) {
throw new ComponentException("Class not found: " + clname);
}
try {
return c.getDeclaredField(parameter).getType().getSimpleName();
} catch (NoSuchFieldException ex) {
throw new ComponentException("No such field: " + parameter);
} catch (SecurityException ex) {
throw new ComponentException("Cannot access : " + parameter);
}
}
}
throw new ComponentException("Cannot find component '" + object + "'. in '" + object + "." + parameter + "'");
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy