Changeset 9557
- Timestamp:
- 03/31/09 13:54:21 (1 year ago)
- Files:
-
- helma/helma/trunk/src/helma/objectmodel/db/DbMapping.java (modified) (10 diffs)
- helma/helma/trunk/src/helma/objectmodel/db/Relation.java (modified) (17 diffs)
- helma/helma/trunk/src/helma/scripting/rhino/HopObjectCtor.java (modified) (3 diffs)
- helma/helma/trunk/src/helma/scripting/rhino/RhinoCore.java (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
helma/helma/trunk/src/helma/objectmodel/db/DbMapping.java
r9520 r9557 37 37 38 38 // properties from where the mapping is read 39 private final ResourceProperties props;39 private final Properties props; 40 40 41 41 // name of data dbSource to which this mapping writes … … 148 148 * Create a DbMapping from a type.properties property file 149 149 */ 150 public DbMapping(Application app, String typename, ResourceProperties props) {150 public DbMapping(Application app, String typename, Properties props) { 151 151 this.app = app; 152 152 // create a unique instance of the string. This is useful so … … 170 170 */ 171 171 public boolean needsUpdate() { 172 return props.lastModified() != lastTypeChange; 172 if (props instanceof ResourceProperties) { 173 return ((ResourceProperties) props).lastModified() != lastTypeChange; 174 } 175 return false; 173 176 } 174 177 … … 234 237 } 235 238 236 lastTypeChange = props.lastModified(); 239 lastTypeChange = props instanceof ResourceProperties ? 240 ((ResourceProperties) props).lastModified() : System.currentTimeMillis(); 237 241 238 242 // see if this prototype extends (inherits from) any other prototype … … 299 303 ArrayList joinList = new ArrayList(); 300 304 301 for ( Enumeration e = props.keys(); e.hasMoreElements();) {302 String propName = (String) e.nextElement();305 for (Iterator it = props.entrySet().iterator(); it.hasNext(); ) { 306 Map.Entry entry = (Map.Entry) it.next(); 303 307 304 308 try { 309 String propName = (String) entry.getKey(); 310 305 311 // ignore internal properties (starting with "_") and sub-options (containing a ".") 306 312 if (!propName.startsWith("_") && (propName.indexOf(".") < 0)) { 307 String dbField = props.getProperty(propName);313 Object propValue = entry.getValue(); 308 314 309 315 // check if a relation for this propery already exists. If so, reuse it … … 314 320 } 315 321 316 rel.update( dbField, props);322 rel.update(propValue, getSubProperties(propName)); 317 323 p2d.put(propName, rel); 318 324 … … 355 361 joins = (Relation[]) joinList.toArray(joins); 356 362 357 String subnodeMapping = props.getProperty("_children");363 Object subnodeMapping = props.get("_children"); 358 364 359 365 if (subnodeMapping != null) { … … 364 370 } 365 371 366 subRelation.update(subnodeMapping, props);372 subRelation.update(subnodeMapping, getSubProperties("_children")); 367 373 368 374 // if subnodes are accessed via access name or group name, … … 397 403 private void registerExtension(String extID, String extName) { 398 404 // lazy initialization of extensionMap 405 if (extID == null) { 406 return; 407 } 399 408 if (extensionMap == null) { 400 409 extensionMap = new ResourceProperties(); … … 1470 1479 * @return our properties 1471 1480 */ 1472 public ResourceProperties getProperties() {1481 public Properties getProperties() { 1473 1482 return props; 1483 } 1484 1485 public Properties getSubProperties(String prefix) { 1486 if (props.get(prefix) instanceof Properties) { 1487 return (Properties) props.get(prefix); 1488 } else if (props instanceof ResourceProperties) { 1489 return ((ResourceProperties) props).getSubProperties(prefix + "."); 1490 } else { 1491 Properties subprops = new Properties(); 1492 prefix = prefix + "."; 1493 Iterator it = props.entrySet().iterator(); 1494 int prefixLength = prefix.length(); 1495 while (it.hasNext()) { 1496 Map.Entry entry = (Map.Entry) it.next(); 1497 String key = entry.getKey().toString(); 1498 if (key.regionMatches(false, 0, prefix, 0, prefixLength)) { 1499 subprops.put(key.substring(prefixLength), entry.getValue()); 1500 } 1501 } 1502 return subprops; 1503 } 1474 1504 } 1475 1505 helma/helma/trunk/src/helma/objectmodel/db/Relation.java
r9519 r9557 103 103 Vector filterPropertyRefs; 104 104 int maxSize = 0; 105 int offset = 0; 105 106 106 107 /** … … 124 125 this.queryHints = rel.queryHints; 125 126 this.maxSize = rel.maxSize; 127 this.offset = rel.offset; 126 128 this.constraints = rel.constraints; 127 129 this.accessName = rel.accessName; … … 145 147 // parse methods for new file format 146 148 //////////////////////////////////////////////////////////////////////////////////////////// 147 public void update( String desc, ResourceProperties props) {149 public void update(Object desc, Properties props) { 148 150 Application app = ownType.getApplication(); 149 151 150 if ((desc == null) || "".equals(desc.trim())) { 151 if (propName != null) { 152 reftype = PRIMITIVE; 153 columnName = propName; 152 if (desc instanceof Properties || parseDescriptor(desc, props)) { 153 // new style foo.collectionOf = Bar mapping 154 String proto; 155 if (props.containsKey("collection")) { 156 proto = props.getProperty("collection"); 157 virtual = !"_children".equalsIgnoreCase(propName); 158 reftype = COLLECTION; 159 } else if (props.containsKey("mountpoint")) { 160 proto = props.getProperty("mountpoint"); 161 reftype = COLLECTION; 162 virtual = true; 163 this.prototype = proto; 164 } else if (props.containsKey("object")) { 165 proto = props.getProperty("object"); 166 if (reftype != COMPLEX_REFERENCE) { 167 reftype = REFERENCE; 168 } 169 virtual = false; 154 170 } else { 155 reftype = INVALID; 156 columnName = propName; 157 } 158 } else { 159 desc = desc.trim(); 160 161 int open = desc.indexOf("("); 162 int close = desc.indexOf(")"); 163 164 if ((open > -1) && (close > open)) { 165 String ref = desc.substring(0, open).trim(); 166 String proto = desc.substring(open + 1, close).trim(); 167 168 if ("collection".equalsIgnoreCase(ref)) { 169 virtual = !"_children".equalsIgnoreCase(propName); 170 reftype = COLLECTION; 171 } else if ("mountpoint".equalsIgnoreCase(ref)) { 172 virtual = true; 173 reftype = COLLECTION; 174 prototype = proto; 175 } else if ("object".equalsIgnoreCase(ref)) { 176 virtual = false; 177 if (reftype != COMPLEX_REFERENCE) { 178 reftype = REFERENCE; 179 } 180 } else { 181 throw new RuntimeException("Invalid property Mapping: " + desc); 182 } 183 184 otherType = app.getDbMapping(proto); 185 186 if (otherType == null) { 187 throw new RuntimeException("DbMapping for " + proto + 188 " not found from " + ownType.getTypeName()); 189 } 190 191 // make sure the type we're referring to is up to date! 192 if (otherType.needsUpdate()) { 193 otherType.update(); 194 } 195 196 } else { 197 virtual = false; 198 columnName = desc; 199 reftype = PRIMITIVE; 200 } 201 } 202 203 ResourceProperties config = props.getSubProperties(propName + '.'); 204 205 readonly = "true".equalsIgnoreCase(config.getProperty("readonly")); 206 207 isPrivate = "true".equalsIgnoreCase(config.getProperty("private")); 171 throw new RuntimeException("Invalid property Mapping: " + desc); 172 } 173 174 otherType = app.getDbMapping(proto); 175 176 if (otherType == null) { 177 throw new RuntimeException("DbMapping for " + proto + 178 " not found from " + ownType.getTypeName()); 179 } 180 181 // make sure the type we're referring to is up to date! 182 if (otherType.needsUpdate()) { 183 otherType.update(); 184 } 185 186 } 187 188 readonly = "true".equalsIgnoreCase(props.getProperty("readonly")); 189 isPrivate = "true".equalsIgnoreCase(props.getProperty("private")); 208 190 209 191 // the following options only apply to object and collection relations … … 211 193 Vector newConstraints = new Vector(); 212 194 213 parseOptions(newConstraints, config);195 parseOptions(newConstraints, props); 214 196 215 197 constraints = new Constraint[newConstraints.size()]; … … 257 239 } 258 240 259 protected void parseOptions(Vector cnst, Properties config) { 260 String loading = config.getProperty("loadmode"); 241 /** 242 * Converts old style foo = collection(Bar) mapping to new style 243 * foo.collection = Bar mappinng and returns true if a non-primitive mapping 244 * was encountered. 245 * @param value the value of the top level property mapping 246 * @param config the sub-map for this property mapping 247 * @return true if the value describes a valid, non-primitive property mapping 248 */ 249 protected boolean parseDescriptor(Object value, Map config) { 250 String desc = value instanceof String ? (String) value : null; 251 252 if ((desc == null) || "".equals(desc.trim())) { 253 if (propName != null) { 254 reftype = PRIMITIVE; 255 columnName = propName; 256 } else { 257 reftype = INVALID; 258 columnName = propName; 259 } 260 return false; 261 } else { 262 desc = desc.trim(); 263 264 int open = desc.indexOf("("); 265 int close = desc.indexOf(")"); 266 267 if ((open > -1) && (close > open)) { 268 String ref = desc.substring(0, open).trim(); 269 String proto = desc.substring(open + 1, close).trim(); 270 271 if ("collection".equalsIgnoreCase(ref)) { 272 config.put("collection", proto); 273 } else if ("mountpoint".equalsIgnoreCase(ref)) { 274 config.put("mountpoint", proto); 275 } else if ("object".equalsIgnoreCase(ref)) { 276 config.put("object", proto); 277 } else { 278 throw new RuntimeException("Invalid property Mapping: " + desc); 279 } 280 281 return true; 282 283 } else { 284 virtual = false; 285 columnName = desc; 286 reftype = PRIMITIVE; 287 return false; 288 } 289 } 290 291 } 292 293 protected void parseOptions(Vector cnst, Properties props) { 294 String loading = props.getProperty("loadmode"); 261 295 262 296 aggressiveLoading = (loading != null) && 263 297 "aggressive".equalsIgnoreCase(loading.trim()); 264 298 265 String caching = config.getProperty("cachemode");299 String caching = props.getProperty("cachemode"); 266 300 267 301 aggressiveCaching = (caching != null) && … … 269 303 270 304 // get order property 271 order = config.getProperty("order");305 order = props.getProperty("order"); 272 306 273 307 if ((order != null) && (order.trim().length() == 0)) { … … 276 310 277 311 // get the criteria(s) for updating this collection 278 updateCriteria = config.getProperty("updatecriteria");312 updateCriteria = props.getProperty("updatecriteria"); 279 313 280 314 // get the autosorting flag 281 autoSorted = "auto".equalsIgnoreCase( config.getProperty("sortmode"));315 autoSorted = "auto".equalsIgnoreCase(props.getProperty("sortmode")); 282 316 283 317 // get additional filter property 284 filter = config.getProperty("filter");318 filter = props.getProperty("filter"); 285 319 286 320 if (filter != null) { … … 305 339 306 340 // get additional tables 307 additionalTables = config.getProperty("filter.additionalTables");341 additionalTables = props.getProperty("filter.additionalTables"); 308 342 309 343 if (additionalTables != null) { … … 335 369 336 370 // get query hints 337 queryHints = config.getProperty("hints");371 queryHints = props.getProperty("hints"); 338 372 339 373 // get max size of collection 340 String max = config.getProperty("maxSize"); 341 342 if (max != null) { 343 try { 344 maxSize = Integer.parseInt(max); 345 } catch (NumberFormatException nfe) { 346 maxSize = 0; 347 } 348 } else { 349 maxSize = 0; 350 } 374 maxSize = getIntegerProperty("maxSize", props, 0); 375 if (maxSize == 0) { 376 // use limit as alias for maxSize 377 maxSize = getIntegerProperty("limit", props, 0); 378 } 379 offset = getIntegerProperty("offset", props, 0); 351 380 352 381 // get group by property 353 groupby = config.getProperty("group");382 groupby = props.getProperty("group"); 354 383 355 384 if ((groupby != null) && (groupby.trim().length() == 0)) { … … 358 387 359 388 if (groupby != null) { 360 groupbyOrder = config.getProperty("group.order");389 groupbyOrder = props.getProperty("group.order"); 361 390 362 391 if ((groupbyOrder != null) && (groupbyOrder.trim().length() == 0)) { … … 364 393 } 365 394 366 groupbyPrototype = config.getProperty("group.prototype");395 groupbyPrototype = props.getProperty("group.prototype"); 367 396 368 397 if ((groupbyPrototype != null) && (groupbyPrototype.trim().length() == 0)) { … … 375 404 376 405 // check if subnode condition should be applied for property relations 377 accessName = config.getProperty("accessname");406 accessName = props.getProperty("accessname"); 378 407 379 408 // parse contstraints 380 String local = config.getProperty("local");381 String foreign = config.getProperty("foreign");409 String local = props.getProperty("local"); 410 String foreign = props.getProperty("foreign"); 382 411 383 412 if ((local != null) && (foreign != null)) { … … 388 417 // parse additional contstraints from *.1 to *.9 389 418 for (int i=1; i<10; i++) { 390 local = config.getProperty("local."+i);391 foreign = config.getProperty("foreign."+i);419 local = props.getProperty("local."+i); 420 foreign = props.getProperty("foreign."+i); 392 421 393 422 if ((local != null) && (foreign != null)) { … … 398 427 // parse constraints logic 399 428 if (cnst.size() > 1) { 400 String logic = config.getProperty("logicalOperator");429 String logic = props.getProperty("logicalOperator"); 401 430 if ("and".equalsIgnoreCase(logic)) { 402 431 logicalOperator = AND; … … 414 443 } 415 444 445 private int getIntegerProperty(String name, Properties props, int defaultValue) { 446 Object value = props.get(name); 447 448 if (value instanceof Number) { 449 return ((Number) value).intValue(); 450 } else if (value instanceof String) { 451 return Integer.parseInt((String) value); 452 } 453 return defaultValue; 454 } 455 416 456 /////////////////////////////////////////////////////////////////////////////////////////// 417 457 … … 419 459 * Get the configuration properties for this relation. 420 460 */ 421 public ResourcePropertiesgetConfig() {422 return ownType.get Properties().getSubProperties(propName + '.');461 public Map getConfig() { 462 return ownType.getSubProperties(propName + '.'); 423 463 } 424 464 … … 874 914 } else if (useOrder && (order != null)) { 875 915 q.append(" ORDER BY ").append(order); 916 } 917 918 if (maxSize > 0 && !ownType.isOracle()) { 919 q.append(" LIMIT ").append(maxSize); 920 if (offset > 0) { 921 q.append(" OFFSET ").append(offset); 922 } 876 923 } 877 924 helma/helma/trunk/src/helma/scripting/rhino/HopObjectCtor.java
r9327 r9557 18 18 import java.lang.reflect.Constructor; 19 19 import java.lang.reflect.Method; 20 import java.util.Properties; 20 21 21 22 import helma.objectmodel.INode; … … 59 60 addAsConstructor(core.global, prototype); 60 61 defineProperty("getById", new GetById(core.global), attr); 62 defineProperty("getCollection", new HopCollection(core.global), attr); 61 63 } 62 64 … … 181 183 } 182 184 185 class HopCollection extends BaseFunction { 186 187 public HopCollection(Scriptable scope) { 188 ScriptRuntime.setFunctionProtoAndParent(this, scope); 189 } 190 191 public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { 192 if (args.length != 1) { 193 throw new IllegalArgumentException("Wrong number of arguments in definePrototype()"); 194 } 195 if (!(args[0] instanceof Scriptable)) { 196 throw new IllegalArgumentException("Second argument to HopObject.definePrototype() must be Object"); 197 } 198 199 Scriptable desc = (Scriptable) args[0]; 200 Properties childmapping = core.scriptableToProperties(desc); 201 if (!childmapping.containsKey("collection")) { 202 // if contained type isn't defined explicitly limit collection to our own type 203 childmapping.put("collection", HopObjectCtor.this.getFunctionName()); 204 } 205 206 Node node = new Node("HopQuery", null, core.app.getWrappedNodeManager()); 207 Properties props = new Properties(); 208 props.put("_children", childmapping); 209 DbMapping dbmap = new DbMapping(core.app, null, props); 210 dbmap.update(); 211 node.setDbMapping(dbmap); 212 node.setState(Node.VIRTUAL); 213 return new HopObject("HopQuery", core, node, core.hopObjectProto); 214 } 215 216 public int getArity() { 217 return 1; 218 } 219 220 public int getLength() { 221 return 1; 222 } 223 } 224 183 225 } helma/helma/trunk/src/helma/scripting/rhino/RhinoCore.java
r9518 r9557 24 24 import helma.objectmodel.db.DbMapping; 25 25 import helma.scripting.*; 26 import helma.util.CacheMap; 27 import helma.util.SystemMap; 28 import helma.util.WrappedMap; 29 import helma.util.WeakCacheMap; 26 import helma.util.*; 30 27 import org.mozilla.javascript.*; 31 28 import org.mozilla.javascript.tools.debugger.ScopeProvider; … … 217 214 * @param prototype the prototype to be created 218 215 */ 219 pr ivate synchronized voidinitPrototype(Prototype prototype) {216 protected synchronized TypeInfo initPrototype(Prototype prototype) { 220 217 221 218 String name = prototype.getName(); … … 237 234 op = new HopObject(name, this); 238 235 } 239 registerPrototype(prototype, op);236 type = registerPrototype(prototype, op); 240 237 } 241 238 … … 251 248 } 252 249 } 250 251 return type; 253 252 } 254 253 … … 292 291 * @param type the prototype object info 293 292 */ 294 pr ivatevoid setParentPrototype(Prototype prototype, TypeInfo type) {293 protected void setParentPrototype(Prototype prototype, TypeInfo type) { 295 294 String name = prototype.getName(); 296 295 String lowerCaseName = prototype.getLowerCaseName(); … … 434 433 TypeInfo type = getPrototypeInfo(protoName); 435 434 SystemMap map = new SystemMap(); 436 Iterator it = type.compiledProperties.iterator();435 Iterator it = type.compiledProperties.iterator(); 437 436 while(it.hasNext()) { 438 437 Object key = it.next(); … … 748 747 return href; 749 748 } 749 750 751 Properties scriptableToProperties(Scriptable obj) { 752 Object[] ids = obj.getIds(); 753 Properties props = new ResourceProperties(app, null, null, true); 754 for (int i = 0; i < ids.length; i++) { 755 // we ignore non-string keys 756 if (ids[i] instanceof String) { 757 String key = (String) ids[i]; 758 Object value = obj.get(key, obj); 759 if (value == Undefined.instance || value == Scriptable.NOT_FOUND) { 760 value = null; 761 } else if (value instanceof Scriptable) { 762 value = scriptableToProperties((Scriptable) value); 763 } 764 props.put(key, value); 765 } 766 } 767 return props; 768 } 750 769 751 770 /**