Add experimental definePrototype() function.

This commit is contained in:
hns 2009-03-31 20:20:13 +00:00
parent 3d882de822
commit 196bf97053
4 changed files with 57 additions and 7 deletions

View file

@ -984,6 +984,23 @@ public final class Application implements Runnable {
return typemgr.getPrototypes(); return typemgr.getPrototypes();
} }
/**
* Programmatically define a new prototype. If a prototype with this name already exists return
* the existing prototype.
* @param name the prototype name
* @param typeProps custom type properties map
* @return the new prototype
*/
public Prototype definePrototype(String name, Map typeProps) {
Prototype proto = typemgr.getPrototype(name);
if (proto == null) {
proto = typemgr.createPrototype(name, null, typeProps);
} else {
proto.setTypeProperties(typeProps);
}
return proto;
}
/** /**
* Return a skin for a given object. The skin is found by determining the prototype * Return a skin for a given object. The skin is found by determining the prototype
* to use for the object, then looking up the skin for the prototype. * to use for the object, then looking up the skin for the prototype.

View file

@ -74,8 +74,9 @@ public final class Prototype {
* @param name the prototype's name * @param name the prototype's name
* @param repository the first prototype's repository * @param repository the first prototype's repository
* @param app the application this prototype is a part of * @param app the application this prototype is a part of
* @param typeProps custom type mapping properties
*/ */
public Prototype(String name, Repository repository, Application app) { public Prototype(String name, Repository repository, Application app, Map typeProps) {
// app.logEvent ("Constructing Prototype "+app.getName()+"/"+name); // app.logEvent ("Constructing Prototype "+app.getName()+"/"+name);
this.app = app; this.app = app;
this.name = name; this.name = name;
@ -87,10 +88,13 @@ public final class Prototype {
// Create and register type properties file // Create and register type properties file
props = new ResourceProperties(app); props = new ResourceProperties(app);
if (repository != null) { if (typeProps != null) {
props.putAll(typeProps);
} else if (repository != null) {
props.addResource(repository.getResource("type.properties")); props.addResource(repository.getResource("type.properties"));
props.addResource(repository.getResource(name + ".properties")); props.addResource(repository.getResource(name + ".properties"));
} }
dbmap = new DbMapping(app, name, props); dbmap = new DbMapping(app, name, props);
// we don't need to put the DbMapping into proto.updatables, because // we don't need to put the DbMapping into proto.updatables, because
// dbmappings are checked separately in TypeManager.checkFiles() for // dbmappings are checked separately in TypeManager.checkFiles() for
@ -392,6 +396,16 @@ public final class Prototype {
lastCodeUpdate = System.currentTimeMillis(); lastCodeUpdate = System.currentTimeMillis();
} }
/**
* Set the custom type properties for this prototype and update the database mapping.
* @param map the custom type mapping properties.
*/
public void setTypeProperties(Map map) {
props.clear();
props.putAll(map);
dbmap.update();
}
/** /**
* Get the prototype's aggregated type.properties * Get the prototype's aggregated type.properties
* *

View file

@ -104,7 +104,7 @@ public final class TypeManager {
public synchronized void createPrototypes() throws IOException { public synchronized void createPrototypes() throws IOException {
// create standard prototypes. // create standard prototypes.
for (int i = 0; i < standardTypes.length; i++) { for (int i = 0; i < standardTypes.length; i++) {
createPrototype(standardTypes[i], null); createPrototype(standardTypes[i], null, null);
} }
// loop through directories and create prototypes // loop through directories and create prototypes
@ -154,7 +154,7 @@ public final class TypeManager {
if (proto == null) { if (proto == null) {
// create new prototype if type name is valid // create new prototype if type name is valid
if (isValidTypeName(name)) if (isValidTypeName(name))
createPrototype(name, list[i]); createPrototype(name, list[i], null);
} else { } else {
proto.addRepository(list[i], update); proto.addRepository(list[i], update);
} }
@ -294,14 +294,15 @@ public final class TypeManager {
* *
* @param typename the name of the prototype * @param typename the name of the prototype
* @param repository the first prototype source * @param repository the first prototype source
* @param typeProps custom type mapping properties
* @return the newly created prototype * @return the newly created prototype
*/ */
public synchronized Prototype createPrototype(String typename, Repository repository) { public synchronized Prototype createPrototype(String typename, Repository repository, Map typeProps) {
if ("true".equalsIgnoreCase(app.getProperty("helma.debugTypeManager"))) { if ("true".equalsIgnoreCase(app.getProperty("helma.debugTypeManager"))) {
System.err.println("CREATE: " + typename + " from " + repository + " in " + Thread.currentThread()); System.err.println("CREATE: " + typename + " from " + repository + " in " + Thread.currentThread());
// Thread.dumpStack(); // Thread.dumpStack();
} }
Prototype proto = new Prototype(typename, repository, app); Prototype proto = new Prototype(typename, repository, app, typeProps);
// put the prototype into our map // put the prototype into our map
prototypes.put(proto.getLowerCaseName(), proto); prototypes.put(proto.getLowerCaseName(), proto);
return proto; return proto;

View file

@ -73,7 +73,7 @@ public class GlobalObject extends ImporterTopLevel implements PropertyRecorder {
"getXmlDocument", "getHtmlDocument", "seal", "getXmlDocument", "getHtmlDocument", "seal",
"getDBConnection", "getURL", "write", "writeln", "getDBConnection", "getURL", "write", "writeln",
"serialize", "deserialize", "defineLibraryScope", "serialize", "deserialize", "defineLibraryScope",
"wrapJavaMap", "unwrapJavaMap", "toJava" "wrapJavaMap", "unwrapJavaMap", "toJava", "definePrototype"
}; };
defineFunctionProperties(globalFuncs, GlobalObject.class, DONTENUM | PERMANENT); defineFunctionProperties(globalFuncs, GlobalObject.class, DONTENUM | PERMANENT);
@ -673,6 +673,24 @@ public class GlobalObject extends ImporterTopLevel implements PropertyRecorder {
return null; return null;
} }
public Object definePrototype(String name, Scriptable desc) {
if (name == null) {
throw new IllegalArgumentException("First argument to definePrototype() must be String");
}
if (desc == null) {
throw new IllegalArgumentException("Second argument to definePrototype() must be Object");
}
Prototype proto = core.app.definePrototype(name, core.scriptableToProperties(desc));
RhinoCore.TypeInfo type = (RhinoCore.TypeInfo) core.prototypes.get(proto.getLowerCaseName());
if (type == null) {
type = core.initPrototype(proto);
}
core.setParentPrototype(proto, type);
return type.objProto;
}
private static String toString(Object obj) { private static String toString(Object obj) {
if (obj == null || obj == Undefined.instance) { if (obj == null || obj == Undefined.instance) {
// Note: we might return "" here in order // Note: we might return "" here in order