* Clean up HopObject wrapper, move constructor code into separate HopObjectCtor class
* Implement HopObject compilation trigger on HopObject constructor property access * Fix race condition in RhinoCore.updatePrototypes() that could result in failed requests at application startup time; tighten up synchronization. * Fix ListViewWrapper to perform static JS function setup rather than setting up functions for each wrapper. * Implement getOrderedView() in SubnodeList (pulled out of OrderedSubnodeList). * Cleaned up and simplified OrderedSubnodeList. * Change ordering for null properties: add at the end of the list instead of the beginning. * Cache nodes fetched in NodeManager.updateSubnodeList()
This commit is contained in:
		
							parent
							
								
									91a92b6072
								
							
						
					
					
						commit
						80e0d4e012
					
				
					 10 changed files with 494 additions and 412 deletions
				
			
		| 
						 | 
				
			
			@ -1244,7 +1244,7 @@ public final class Node implements INode, Serializable {
 | 
			
		|||
        loadNodes();
 | 
			
		||||
 | 
			
		||||
        if (subnodes == null) {
 | 
			
		||||
            subnodes = new SubnodeList();
 | 
			
		||||
            subnodes = new SubnodeList(nmgr, dbmap.getSubnodeRelation());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (create || subnodes.contains(new NodeHandle(new SyntheticKey(getKey(), sid)))) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1582,11 +1582,11 @@ public final class Node implements INode, Serializable {
 | 
			
		|||
    public SubnodeList createSubnodeList() {
 | 
			
		||||
        Relation rel = this.dbmap == null ? null : this.dbmap.getSubnodeRelation();
 | 
			
		||||
        if (rel != null && rel.updateCriteria != null) {
 | 
			
		||||
            subnodes = new UpdateableSubnodeList(rel);
 | 
			
		||||
            subnodes = new UpdateableSubnodeList(nmgr, rel);
 | 
			
		||||
        } else if (rel != null && rel.autoSorted) {
 | 
			
		||||
            subnodes = new OrderedSubnodeList(rel);
 | 
			
		||||
            subnodes = new OrderedSubnodeList(nmgr, rel);
 | 
			
		||||
        } else {
 | 
			
		||||
            subnodes = new SubnodeList();
 | 
			
		||||
            subnodes = new SubnodeList(nmgr, rel);
 | 
			
		||||
        }
 | 
			
		||||
        return subnodes;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1661,11 +1661,11 @@ public final class Node implements INode, Serializable {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Return this Node's subnode list
 | 
			
		||||
     *
 | 
			
		||||
     *
 | 
			
		||||
     * @return ...
 | 
			
		||||
     * @return the subnode list
 | 
			
		||||
     */
 | 
			
		||||
    public List getSubnodeList() {
 | 
			
		||||
    public SubnodeList getSubnodeList() {
 | 
			
		||||
        return subnodes;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1186,6 +1186,12 @@ public final class NodeManager {
 | 
			
		|||
                            continue;
 | 
			
		||||
                        }
 | 
			
		||||
                        key = node.getKey();
 | 
			
		||||
                        synchronized (cache) {
 | 
			
		||||
                            Node oldnode = (Node) cache.put(key, node);
 | 
			
		||||
                            if ((oldnode != null) && (oldnode.getState() != INode.INVALID)) {
 | 
			
		||||
                                cache.put(key, oldnode);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    } else {
 | 
			
		||||
                        key = new DbKey(rel.otherType, kstr);
 | 
			
		||||
                    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1320,7 +1326,7 @@ public final class NodeManager {
 | 
			
		|||
                            SubnodeList sn = (SubnodeList) groupbySubnodes.get(groupName);
 | 
			
		||||
 | 
			
		||||
                            if (sn == null) {
 | 
			
		||||
                                sn = new SubnodeList();
 | 
			
		||||
                                sn = new SubnodeList(safe, rel);
 | 
			
		||||
                                groupbySubnodes.put(groupName, sn);
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,49 +29,24 @@ import java.util.List;
 | 
			
		|||
 * or remove-methods are called.
 | 
			
		||||
 */
 | 
			
		||||
public class OrderedSubnodeList extends SubnodeList {
 | 
			
		||||
    HashMap views = null;
 | 
			
		||||
    private final OrderedSubnodeList origin;
 | 
			
		||||
 | 
			
		||||
    // the base subnode list, in case this is an ordered view
 | 
			
		||||
    private SubnodeList origin;
 | 
			
		||||
    // an array containing the order-fields
 | 
			
		||||
    private final String orderProperties[];
 | 
			
		||||
    private String orderProperties[];
 | 
			
		||||
    // an array containing the direction for ordering 
 | 
			
		||||
    private final boolean orderIsDesc[];
 | 
			
		||||
 | 
			
		||||
    // the relation which is the basis for this collection
 | 
			
		||||
    final Relation rel;
 | 
			
		||||
    private boolean orderIsDesc[];
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Construct a new OrderedSubnodeList. The Relation is needed
 | 
			
		||||
     * to get the information about the ORDERING
 | 
			
		||||
     */
 | 
			
		||||
    public OrderedSubnodeList (Relation rel) {
 | 
			
		||||
        this.rel = rel;
 | 
			
		||||
    public OrderedSubnodeList (WrappedNodeManager nmgr, Relation rel) {
 | 
			
		||||
        super(nmgr, rel);
 | 
			
		||||
        this.origin = null;
 | 
			
		||||
        // check the order of this collection for automatically sorting
 | 
			
		||||
        // in the values in the correct order
 | 
			
		||||
        if (rel.order == null) {
 | 
			
		||||
            orderProperties=null;
 | 
			
		||||
            orderIsDesc=null;
 | 
			
		||||
        } else {
 | 
			
		||||
            String singleOrders[] = rel.order.split(",");
 | 
			
		||||
            orderProperties = new String[singleOrders.length];
 | 
			
		||||
            orderIsDesc = new boolean[singleOrders.length];
 | 
			
		||||
            DbMapping dbm = rel.otherType;
 | 
			
		||||
            for (int i = 0; i < singleOrders.length; i++) {
 | 
			
		||||
                String currOrder[] = singleOrders[i].trim().split(" ");
 | 
			
		||||
                if (currOrder[0].equalsIgnoreCase(rel.otherType.getIDField())) {
 | 
			
		||||
                    orderProperties[i]=null;
 | 
			
		||||
                } else {
 | 
			
		||||
                    orderProperties[i] = dbm.columnNameToProperty(currOrder[0]);
 | 
			
		||||
                }
 | 
			
		||||
                System.err.println("ORDER PROP " + i + " IS " + orderProperties[i] + " FROM " +currOrder[0]);
 | 
			
		||||
                if (currOrder.length < 2
 | 
			
		||||
                        || "ASC".equalsIgnoreCase(currOrder[1]))
 | 
			
		||||
                    orderIsDesc[i]=false;
 | 
			
		||||
                else
 | 
			
		||||
                    orderIsDesc[i]=true;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        initOrder(rel.order);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			@ -80,36 +55,31 @@ public class OrderedSubnodeList extends SubnodeList {
 | 
			
		|||
     * @param expr the new order for this view
 | 
			
		||||
     * @param rel the relation given for the origin-list
 | 
			
		||||
     */
 | 
			
		||||
    public OrderedSubnodeList (OrderedSubnodeList origin, String expr, Relation rel) {
 | 
			
		||||
    public OrderedSubnodeList (WrappedNodeManager nmgr, Relation rel, SubnodeList origin, String expr) {
 | 
			
		||||
        super(nmgr, rel);
 | 
			
		||||
        this.origin = origin;
 | 
			
		||||
        this.rel = rel;
 | 
			
		||||
        if (expr==null) {
 | 
			
		||||
        initOrder(expr);
 | 
			
		||||
        if (origin != null) {
 | 
			
		||||
            sortIn(origin, false);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void initOrder(String order) {
 | 
			
		||||
        if (order == null) {
 | 
			
		||||
            orderProperties=null;
 | 
			
		||||
            orderIsDesc=null;
 | 
			
		||||
        } else {
 | 
			
		||||
            String singleOrders[] = expr.split(",");
 | 
			
		||||
            orderProperties = new String[singleOrders.length];
 | 
			
		||||
            orderIsDesc = new boolean[singleOrders.length];
 | 
			
		||||
            DbMapping dbm = rel.otherType;
 | 
			
		||||
            for (int i = 0; i<singleOrders.length; i++) {
 | 
			
		||||
                String currOrder[] = singleOrders[i].trim().split(" ");
 | 
			
		||||
                if (currOrder[0].equalsIgnoreCase("_id")) {
 | 
			
		||||
                    orderProperties[i]=null;
 | 
			
		||||
                } else {
 | 
			
		||||
                    if (dbm.propertyToColumnName(currOrder[0])==null)
 | 
			
		||||
                        throw new RuntimeException ("Properties must be mapped to get an ordered collection for these properties.");
 | 
			
		||||
                    orderProperties[i]=currOrder[0];
 | 
			
		||||
                }
 | 
			
		||||
                if (currOrder.length < 2
 | 
			
		||||
                        || "ASC".equalsIgnoreCase(currOrder[1]))
 | 
			
		||||
                    orderIsDesc[i]=false;
 | 
			
		||||
                else
 | 
			
		||||
                    orderIsDesc[i]=true;
 | 
			
		||||
            String orderParts[] = order.split(",");
 | 
			
		||||
            orderProperties = new String[orderParts.length];
 | 
			
		||||
            orderIsDesc = new boolean[orderParts.length];
 | 
			
		||||
            for (int i = 0; i < orderParts.length; i++) {
 | 
			
		||||
                String part[] = orderParts[i].trim().split(" ");
 | 
			
		||||
                orderProperties[i] =  part[0].equals("_id") ?
 | 
			
		||||
                    null : part[0];
 | 
			
		||||
                orderIsDesc[i] = part.length == 2 &&
 | 
			
		||||
                        "DESC".equalsIgnoreCase(part[1]);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (origin == null)
 | 
			
		||||
            return;
 | 
			
		||||
        this.sortIn(origin, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
| 
						 | 
				
			
			@ -119,8 +89,19 @@ public class OrderedSubnodeList extends SubnodeList {
 | 
			
		|||
    * @param obj element to be inserted.
 | 
			
		||||
    */
 | 
			
		||||
    public boolean add(Object obj) {
 | 
			
		||||
        System.err.println("******** SORT-ADDING " + obj);
 | 
			
		||||
        return add(obj, false);
 | 
			
		||||
        return add(obj, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Adds the specified object to the list at the given position
 | 
			
		||||
     * @param idx the index to insert the element at
 | 
			
		||||
     * @param obj the object t add
 | 
			
		||||
     */
 | 
			
		||||
    public void add(int idx, Object obj) {
 | 
			
		||||
        if (this.orderProperties!=null)
 | 
			
		||||
            throw new RuntimeException ("Indexed add isn't alowed for ordered subnodes");
 | 
			
		||||
        super.add(idx, obj);
 | 
			
		||||
        addToViews(obj);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
| 
						 | 
				
			
			@ -130,20 +111,23 @@ public class OrderedSubnodeList extends SubnodeList {
 | 
			
		|||
    * @param obj element to be inserted.
 | 
			
		||||
    */
 | 
			
		||||
    public boolean addSorted(Object obj) {
 | 
			
		||||
        return add(obj, true);
 | 
			
		||||
        return add(obj, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private boolean add(Object obj, boolean sorted) {
 | 
			
		||||
        if (origin != null)
 | 
			
		||||
    boolean add(Object obj, boolean sort) {
 | 
			
		||||
        if (origin != null) {
 | 
			
		||||
            return origin.add(obj);
 | 
			
		||||
        vAdd(obj);
 | 
			
		||||
        while (rel.maxSize>0 && this.size() >= rel.maxSize)
 | 
			
		||||
            super.remove(0);
 | 
			
		||||
        }
 | 
			
		||||
        addToViews(obj);
 | 
			
		||||
        int maxSize = rel == null ? 0 : rel.maxSize;
 | 
			
		||||
        while (maxSize > 0 && this.size() >= maxSize) {
 | 
			
		||||
            remove(size() - 1);
 | 
			
		||||
        }
 | 
			
		||||
        // escape sorting for presorted adds and grouped nodes
 | 
			
		||||
        if (sorted || rel.groupby != null) {
 | 
			
		||||
            super.add(obj);
 | 
			
		||||
        } else {
 | 
			
		||||
        if (sort && (rel == null || rel.groupby == null)) {
 | 
			
		||||
            sortIn(obj);
 | 
			
		||||
        } else {
 | 
			
		||||
            super.add(obj);
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -156,36 +140,23 @@ public class OrderedSubnodeList extends SubnodeList {
 | 
			
		|||
        // no order, just add
 | 
			
		||||
        if (this.orderProperties==null)
 | 
			
		||||
            return super.add(obj);
 | 
			
		||||
        vAdd(obj);
 | 
			
		||||
        long start = System.currentTimeMillis();
 | 
			
		||||
        try {
 | 
			
		||||
            int idx = this.determineNodePosition((NodeHandle) obj, 0);
 | 
			
		||||
            System.err.println("Position: " + idx);
 | 
			
		||||
            if (idx<0)
 | 
			
		||||
                return super.add(obj);
 | 
			
		||||
            else
 | 
			
		||||
                super.add(idx, obj);
 | 
			
		||||
            return true;
 | 
			
		||||
        } finally {
 | 
			
		||||
            System.out.println("Sortmillis: " + (System.currentTimeMillis() - start));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void vAdd (Object obj) {
 | 
			
		||||
        if (views==null || origin!=null || views.size()<1)
 | 
			
		||||
            return;
 | 
			
		||||
        for (Iterator i = views.values().iterator(); i.hasNext(); ) {
 | 
			
		||||
            OrderedSubnodeList osl = (OrderedSubnodeList) i.next();
 | 
			
		||||
            osl.sortIn(obj);
 | 
			
		||||
        }
 | 
			
		||||
        addToViews(obj);
 | 
			
		||||
        Node node = ((NodeHandle) obj).getNode(nmgr);
 | 
			
		||||
        int idx = this.determineNodePosition(node, 0);
 | 
			
		||||
        // System.err.println("Position: " + idx);
 | 
			
		||||
        if (idx<0)
 | 
			
		||||
            return super.add(obj);
 | 
			
		||||
        else
 | 
			
		||||
            super.add(idx, obj);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public boolean addAll(Collection col) {
 | 
			
		||||
        return sortIn(col, true) > 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void vAddAll (Collection col) {
 | 
			
		||||
        if (views==null || origin!=null || views.size()<1)
 | 
			
		||||
    private void addAllToViews (Collection col) {
 | 
			
		||||
        if (views == null || origin != null || views.isEmpty())
 | 
			
		||||
            return;
 | 
			
		||||
        for (Iterator i = views.values().iterator(); i.hasNext(); ) {
 | 
			
		||||
            OrderedSubnodeList osl = (OrderedSubnodeList) i.next();
 | 
			
		||||
| 
						 | 
				
			
			@ -193,37 +164,32 @@ public class OrderedSubnodeList extends SubnodeList {
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public void add(int idx, Object obj) {
 | 
			
		||||
        if (this.orderProperties!=null)
 | 
			
		||||
            throw new RuntimeException ("Indexed add isn't alowed for ordered subnodes");
 | 
			
		||||
        super.add(idx, obj);
 | 
			
		||||
        vAdd(obj);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Add all nodes contained inside the specified Collection to this
 | 
			
		||||
     * UpdateableSubnodeList. The order of the added Nodes is asumed to
 | 
			
		||||
     * be ordered according to the SQL-Order-Clausel given for this 
 | 
			
		||||
     * Subnodecollection but doesn't prevent adding of unordered Collections.
 | 
			
		||||
     * Ordered Collections will be sorted in more efficient than unordered ones.
 | 
			
		||||
     * UpdateableSubnodeList. The order of the added Nodes is assumed to
 | 
			
		||||
     * be ordered according to the SQL-Order-Clause given for this
 | 
			
		||||
     * Subnode collection but doesn't prevent adding of unordered Collections.
 | 
			
		||||
     * Ordered Collections will be sorted in more efficiently than unordered ones.
 | 
			
		||||
     *
 | 
			
		||||
     * @param col the collection containing all elements to add in the order returned by the select-statement
 | 
			
		||||
     * @param colHasDefaultOrder true if the given collection does have the default-order defined by the relation
 | 
			
		||||
     */
 | 
			
		||||
    public int sortIn (Collection col, boolean colHasDefaultOrder) {
 | 
			
		||||
        vAddAll(col);
 | 
			
		||||
        addAllToViews(col);
 | 
			
		||||
        int cntr=0;
 | 
			
		||||
        // there is no order specified, add on top
 | 
			
		||||
        if (orderProperties==null) {
 | 
			
		||||
        if (orderProperties == null) {
 | 
			
		||||
            for (Iterator i = col.iterator(); i.hasNext(); ) {
 | 
			
		||||
                super.add(cntr, i.next());
 | 
			
		||||
                cntr++;
 | 
			
		||||
            }
 | 
			
		||||
            if (rel.maxSize > 0) {
 | 
			
		||||
                int diff = this.size() - rel.maxSize;
 | 
			
		||||
            int maxSize = rel == null ? 0 : rel.maxSize;
 | 
			
		||||
            if (maxSize > 0) {
 | 
			
		||||
                int diff = this.size() - maxSize;
 | 
			
		||||
                if (diff > 0)
 | 
			
		||||
                    super.removeRange(this.size()-1-diff, this.size()-1);
 | 
			
		||||
            }
 | 
			
		||||
        } else if (!colHasDefaultOrder || origin!=null) {
 | 
			
		||||
        } else if (!colHasDefaultOrder || origin != null) {
 | 
			
		||||
            // this collection is a view or the given collection doesn't have the
 | 
			
		||||
            // default order
 | 
			
		||||
            for (Iterator i = col.iterator(); i.hasNext(); ) {
 | 
			
		||||
| 
						 | 
				
			
			@ -235,21 +201,21 @@ public class OrderedSubnodeList extends SubnodeList {
 | 
			
		|||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            NodeHandle[] nhArr = (NodeHandle[]) col.toArray (new NodeHandle[0]);
 | 
			
		||||
            int locIdx=determineNodePosition(nhArr[0], 0); // determine start-point
 | 
			
		||||
            if (locIdx==-1)
 | 
			
		||||
                locIdx=this.size();
 | 
			
		||||
            Node node = nhArr[0].getNode(nmgr);
 | 
			
		||||
            int locIdx = determineNodePosition(node, 0); // determine start-point
 | 
			
		||||
            if (locIdx == -1)
 | 
			
		||||
                locIdx = this.size();
 | 
			
		||||
            // int interval=Math.max(1, this.size()/2);
 | 
			
		||||
            int addIdx=0;
 | 
			
		||||
            for (; addIdx < nhArr.length; addIdx++) {
 | 
			
		||||
                while (locIdx < this.size() && compareNodes(nhArr[addIdx], (NodeHandle) this.get(locIdx)) >= 0)
 | 
			
		||||
            for (int addIdx=0; addIdx < nhArr.length; addIdx++) {
 | 
			
		||||
                node = nhArr[addIdx].getNode(nmgr);
 | 
			
		||||
                while (locIdx < this.size() &&
 | 
			
		||||
                        compareNodes(node, (NodeHandle) this.get(locIdx)) >= 0)
 | 
			
		||||
                    locIdx++;
 | 
			
		||||
                if (locIdx >= this.size())
 | 
			
		||||
                    break;
 | 
			
		||||
                this.add(locIdx, nhArr[addIdx]);
 | 
			
		||||
                cntr++;
 | 
			
		||||
            }
 | 
			
		||||
            for (; addIdx < nhArr.length; addIdx++) {
 | 
			
		||||
                this.add(nhArr[addIdx]);
 | 
			
		||||
                if (locIdx < this.size()) {
 | 
			
		||||
                    this.add(locIdx, nhArr[addIdx]);
 | 
			
		||||
                } else {
 | 
			
		||||
                    this.add(nhArr[addIdx]);
 | 
			
		||||
                }
 | 
			
		||||
                cntr++;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -257,54 +223,18 @@ public class OrderedSubnodeList extends SubnodeList {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * remove the object specified by the given index-position
 | 
			
		||||
     * @param idx the index-position of the NodeHandle to remove
 | 
			
		||||
     */
 | 
			
		||||
    public Object remove (int idx) {
 | 
			
		||||
        vRemove(idx);
 | 
			
		||||
        return super.remove(idx);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void vRemove(int idx) {
 | 
			
		||||
        if (views==null || origin!=null || views.size()<1)
 | 
			
		||||
            return;
 | 
			
		||||
        for (Iterator i = views.values().iterator(); i.hasNext(); ) {
 | 
			
		||||
            OrderedSubnodeList osl = (OrderedSubnodeList) i.next();
 | 
			
		||||
            osl.remove(idx);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * remove the given Object from this List
 | 
			
		||||
     * @param obj the NodeHandle to remove
 | 
			
		||||
     */
 | 
			
		||||
    public boolean remove (Object obj) {
 | 
			
		||||
        vRemove(obj);
 | 
			
		||||
        return super.remove(obj);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void vRemove(Object obj) {
 | 
			
		||||
        if (views==null || origin!=null || views.size()<1)
 | 
			
		||||
            return;
 | 
			
		||||
        for (Iterator i = views.values().iterator(); i.hasNext(); ) {
 | 
			
		||||
            OrderedSubnodeList osl = (OrderedSubnodeList) i.next();
 | 
			
		||||
            osl.remove(obj);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * remove all elements conteined inside the specified collection
 | 
			
		||||
     * remove all elements contained inside the specified collection
 | 
			
		||||
     * from this List
 | 
			
		||||
     * @param c the Collection containing all Objects to remove from this List
 | 
			
		||||
     * @return true if the List has been modified
 | 
			
		||||
     */
 | 
			
		||||
    public boolean removeAll(Collection c) {
 | 
			
		||||
        vRemoveAll(c);
 | 
			
		||||
        removeAllFromViews(c);
 | 
			
		||||
        return super.removeAll(c);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void vRemoveAll(Collection c) {
 | 
			
		||||
        if (views==null || origin!=null || views.size()<1)
 | 
			
		||||
    private void removeAllFromViews(Collection c) {
 | 
			
		||||
        if (views == null || origin != null || views.isEmpty())
 | 
			
		||||
            return;
 | 
			
		||||
        for (Iterator i = views.values().iterator(); i.hasNext(); ) {
 | 
			
		||||
            OrderedSubnodeList osl = (OrderedSubnodeList) i.next();
 | 
			
		||||
| 
						 | 
				
			
			@ -319,12 +249,12 @@ public class OrderedSubnodeList extends SubnodeList {
 | 
			
		|||
     * @return true if the List has been modified
 | 
			
		||||
     */
 | 
			
		||||
    public boolean retainAll (Collection c) {
 | 
			
		||||
        vRetainAll(c);
 | 
			
		||||
        retainAllInViews(c);
 | 
			
		||||
        return super.retainAll(c);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void vRetainAll(Collection c) {
 | 
			
		||||
        if (views==null || origin!=null || views.size()<1)
 | 
			
		||||
    private void retainAllInViews(Collection c) {
 | 
			
		||||
        if (views == null || origin != null || views.isEmpty())
 | 
			
		||||
            return;
 | 
			
		||||
        for (Iterator i = views.values().iterator(); i.hasNext(); ) {
 | 
			
		||||
            OrderedSubnodeList osl = (OrderedSubnodeList) i.next();
 | 
			
		||||
| 
						 | 
				
			
			@ -332,21 +262,22 @@ public class OrderedSubnodeList extends SubnodeList {
 | 
			
		|||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private int determineNodePosition (NodeHandle nh, int startIdx) {
 | 
			
		||||
    private int determineNodePosition (Node node, int startIdx) {
 | 
			
		||||
        int size = this.size();
 | 
			
		||||
        int interval = Math.max(1, (size-startIdx)/2);
 | 
			
		||||
        int interval = Math.max(1, (size - startIdx) / 2);
 | 
			
		||||
        boolean dirUp=true;
 | 
			
		||||
        int cntr = 0;
 | 
			
		||||
        int maxSize = rel == null ? 0 : rel.maxSize;
 | 
			
		||||
        for (int i = 0; i < size
 | 
			
		||||
                && (i < rel.maxSize || rel.maxSize <= 0)
 | 
			
		||||
                && cntr<(size*2); cntr++) {  // cntr is used to avoid endless-loops which shouldn't happen
 | 
			
		||||
                && (i < maxSize || maxSize <= 0)
 | 
			
		||||
                && cntr < (size * 2); cntr++) {  // cntr is used to avoid endless-loops which shouldn't happen
 | 
			
		||||
            NodeHandle curr = (NodeHandle) this.get(i);
 | 
			
		||||
            int comp = compareNodes(nh, curr);
 | 
			
		||||
            int comp = compareNodes(node, curr);
 | 
			
		||||
            // current NodeHandle is below the given NodeHandle
 | 
			
		||||
            // interval has to be 1 and 
 | 
			
		||||
            // idx must be zero or the node before the current node must be higher or equal
 | 
			
		||||
            // all conditions must be met to determine the correct position of a node
 | 
			
		||||
            if (comp < 0 && interval==1 && (i==0 || compareNodes(nh, (NodeHandle) this.get(i-1)) >= 0)) {
 | 
			
		||||
            if (comp < 0 && interval==1 && (i==0 || compareNodes(node, (NodeHandle) this.get(i-1)) >= 0)) {
 | 
			
		||||
                return i;
 | 
			
		||||
            } else if (comp < 0) {
 | 
			
		||||
                dirUp=false;
 | 
			
		||||
| 
						 | 
				
			
			@ -359,7 +290,7 @@ public class OrderedSubnodeList extends SubnodeList {
 | 
			
		|||
            if (dirUp) {
 | 
			
		||||
                i=i+interval;
 | 
			
		||||
                if (i >= this.size()) {
 | 
			
		||||
                    if (compareNodes(nh, (NodeHandle) this.get(size-1)) >= 0)
 | 
			
		||||
                    if (compareNodes(node, (NodeHandle) this.get(size-1)) >= 0)
 | 
			
		||||
                        break;
 | 
			
		||||
                    interval = Math.max(1, (i - size-1)/2);
 | 
			
		||||
                    i = this.size()-1;
 | 
			
		||||
| 
						 | 
				
			
			@ -367,58 +298,58 @@ public class OrderedSubnodeList extends SubnodeList {
 | 
			
		|||
                    interval = Math.max(1,interval/2);
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                i=i-interval;
 | 
			
		||||
                i = i-interval;
 | 
			
		||||
                if (i < 0) { // shouldn't happen i think
 | 
			
		||||
                    interval=Math.max(1,(interval+i)/2);
 | 
			
		||||
                    interval=Math.max(1, (interval+i)/2);
 | 
			
		||||
                    i=0;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        if (cntr >= size*2 && size>1) {
 | 
			
		||||
            System.err.println("determineNodePosition needed more than the allowed iterations" + this.rel.prototype);
 | 
			
		||||
        if (cntr >= size * 2 && size > 1) {
 | 
			
		||||
            System.err.println("determineNodePosition needed more than the allowed iterations");
 | 
			
		||||
        }
 | 
			
		||||
        return -1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Compare two nodes depending on the specified ORDER for this collection.
 | 
			
		||||
     * @param nh1 the first NodeHandle
 | 
			
		||||
     * @param nh2 the second NodeHandle
 | 
			
		||||
     * @param node the first Node
 | 
			
		||||
     * @param nodeHandle the second Node
 | 
			
		||||
     * @return an integer lesser than zero if nh1 is less than, zero if nh1 is equal to and a value greater than zero if nh1 is bigger than nh2.
 | 
			
		||||
     */
 | 
			
		||||
    private int compareNodes(NodeHandle nh1, NodeHandle nh2) {
 | 
			
		||||
        WrappedNodeManager wnmgr=null;
 | 
			
		||||
    private int compareNodes(Node node, NodeHandle nodeHandle) {
 | 
			
		||||
        for (int i = 0; i < orderProperties.length; i++) {
 | 
			
		||||
            if (orderProperties[i]==null) {
 | 
			
		||||
                // we have the id as order-criteria-> avoid loading node
 | 
			
		||||
                // and compare numerically instead of lexicographically
 | 
			
		||||
                String s1 = nh1.getID();
 | 
			
		||||
                String s2 = nh2.getID();
 | 
			
		||||
                String s1 = node.getID();
 | 
			
		||||
                String s2 = nodeHandle.getID();
 | 
			
		||||
                int j = compareNumericString (s1, s2);
 | 
			
		||||
                if (j==0)
 | 
			
		||||
                if (j == 0)
 | 
			
		||||
                    continue;
 | 
			
		||||
                if (orderIsDesc[i])
 | 
			
		||||
                    j=j*-1;
 | 
			
		||||
                    j = j * -1;
 | 
			
		||||
                return j;
 | 
			
		||||
            }
 | 
			
		||||
            System.err.println("CHECKING PROPERTY: " + orderProperties[i] + " / " + orderIsDesc[i]);
 | 
			
		||||
            if (wnmgr == null)
 | 
			
		||||
                wnmgr = rel.otherType.getWrappedNodeManager();
 | 
			
		||||
            Property p1 = nh1.getNode(wnmgr).getProperty(orderProperties[i]);
 | 
			
		||||
            Property p2 = nh2.getNode(wnmgr).getProperty(orderProperties[i]);
 | 
			
		||||
            System.out.println ("*** Comparing " + p1 + " - " + p2);
 | 
			
		||||
            Property p1 = node.getProperty(orderProperties[i]);
 | 
			
		||||
            Property p2 = nodeHandle.getNode(nmgr).getProperty(orderProperties[i]);
 | 
			
		||||
            int j;
 | 
			
		||||
            if (p1==null && p2==null)
 | 
			
		||||
            if (p1 == null && p2 == null) {
 | 
			
		||||
                continue;
 | 
			
		||||
            else if (p1==null)
 | 
			
		||||
            } else if (p1 == null) {
 | 
			
		||||
                j = 1;
 | 
			
		||||
            } else if (p2 == null) {
 | 
			
		||||
                j = -1;
 | 
			
		||||
            else
 | 
			
		||||
            } else {
 | 
			
		||||
                j = p1.compareTo(p2);
 | 
			
		||||
            if (j == 0)
 | 
			
		||||
            }
 | 
			
		||||
            if (j == 0) {
 | 
			
		||||
                continue;
 | 
			
		||||
            if (orderIsDesc[i])
 | 
			
		||||
            }
 | 
			
		||||
            if (orderIsDesc[i]) {
 | 
			
		||||
                j = j * -1;
 | 
			
		||||
            }
 | 
			
		||||
            return j;
 | 
			
		||||
        }
 | 
			
		||||
        return -1;
 | 
			
		||||
| 
						 | 
				
			
			@ -451,21 +382,10 @@ public class OrderedSubnodeList extends SubnodeList {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    public List getOrderedView (String order) {
 | 
			
		||||
        if (origin != null)
 | 
			
		||||
        if (origin != null) {
 | 
			
		||||
            return origin.getOrderedView(order);
 | 
			
		||||
        String key = order.trim().toLowerCase();
 | 
			
		||||
        if (key.equalsIgnoreCase(rel.order))
 | 
			
		||||
            return this;
 | 
			
		||||
        long start = System.currentTimeMillis();
 | 
			
		||||
        if (views == null)
 | 
			
		||||
            views = new HashMap();
 | 
			
		||||
        OrderedSubnodeList osl = (OrderedSubnodeList) views.get(key);
 | 
			
		||||
        if (osl == null) {
 | 
			
		||||
            osl = new OrderedSubnodeList (this, order, rel);
 | 
			
		||||
            views.put(key, osl);
 | 
			
		||||
            System.out.println("getting view cost me " + (System.currentTimeMillis()-start) + " millis");
 | 
			
		||||
        } else
 | 
			
		||||
            System.out.println("getting cached view cost me " + (System.currentTimeMillis()-start) + " millis");
 | 
			
		||||
        return osl;
 | 
			
		||||
        } else {
 | 
			
		||||
            return super.getOrderedView(order);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -508,9 +508,9 @@ public final class Property implements IProperty, Serializable, Cloneable, Compa
 | 
			
		|||
        if (value==null && pvalue == null) {
 | 
			
		||||
            return 0;
 | 
			
		||||
        } else if (value == null) {
 | 
			
		||||
            return -1;
 | 
			
		||||
        } if (pvalue == null) {
 | 
			
		||||
            return 1;
 | 
			
		||||
        } if (pvalue == null) {
 | 
			
		||||
            return -1;
 | 
			
		||||
        }
 | 
			
		||||
        if (type != ptype) {
 | 
			
		||||
            throw new ClassCastException("uncomparable values " + this + "(" + type + ") : " + p + "(" + ptype + ")");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,12 +17,34 @@
 | 
			
		|||
package helma.objectmodel.db;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Iterator;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A subclass of ArrayList that adds an addSorted(Object) method to
 | 
			
		||||
 */
 | 
			
		||||
public class SubnodeList extends ArrayList {
 | 
			
		||||
 | 
			
		||||
    WrappedNodeManager nmgr;
 | 
			
		||||
 | 
			
		||||
    HashMap views = null;
 | 
			
		||||
    Relation rel;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Hide/disable zero argument constructor for subclasses
 | 
			
		||||
     */
 | 
			
		||||
    private SubnodeList()  {}
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates a new subnode list
 | 
			
		||||
     * @param nmgr
 | 
			
		||||
     */
 | 
			
		||||
    public SubnodeList(WrappedNodeManager nmgr, Relation rel) {
 | 
			
		||||
        this.nmgr = nmgr;
 | 
			
		||||
        this.rel = rel;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
   /**
 | 
			
		||||
    * Inserts the specified element at the specified position in this
 | 
			
		||||
    * list without performing custom ordering
 | 
			
		||||
| 
						 | 
				
			
			@ -33,4 +55,77 @@ public class SubnodeList extends ArrayList {
 | 
			
		|||
        return add(obj);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Adds the specified object to this list performing
 | 
			
		||||
     * custom ordering
 | 
			
		||||
     *
 | 
			
		||||
     * @param obj element to be inserted.
 | 
			
		||||
     */
 | 
			
		||||
    public boolean add(Object obj) {
 | 
			
		||||
        addToViews(obj);
 | 
			
		||||
        return super.add(obj);
 | 
			
		||||
    }
 | 
			
		||||
    /**
 | 
			
		||||
     * Adds the specified object to the list at the given position
 | 
			
		||||
     * @param idx the index to insert the element at
 | 
			
		||||
     * @param obj the object t add
 | 
			
		||||
     */
 | 
			
		||||
    public void add(int idx, Object obj) {
 | 
			
		||||
        addToViews(obj);
 | 
			
		||||
        super.add(idx, obj);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * remove the object specified by the given index-position
 | 
			
		||||
     * @param idx the index-position of the NodeHandle to remove
 | 
			
		||||
     */
 | 
			
		||||
    public Object remove (int idx) {
 | 
			
		||||
        Object obj = get(idx);
 | 
			
		||||
        if (obj != null) {
 | 
			
		||||
            removeFromViews(obj);
 | 
			
		||||
        }
 | 
			
		||||
        return super.remove(idx);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * remove the given Object from this List
 | 
			
		||||
     * @param obj the NodeHandle to remove
 | 
			
		||||
     */
 | 
			
		||||
    public boolean remove (Object obj) {
 | 
			
		||||
        removeFromViews(obj);
 | 
			
		||||
        return super.remove(obj);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected void removeFromViews(Object obj) {
 | 
			
		||||
        if (views == null || views.isEmpty())
 | 
			
		||||
            return;
 | 
			
		||||
        for (Iterator i = views.values().iterator(); i.hasNext(); ) {
 | 
			
		||||
            OrderedSubnodeList osl = (OrderedSubnodeList) i.next();
 | 
			
		||||
            osl.remove(obj);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public List getOrderedView (String order) {
 | 
			
		||||
        String key = order.trim().toLowerCase();
 | 
			
		||||
        // long start = System.currentTimeMillis();
 | 
			
		||||
        if (views == null) {
 | 
			
		||||
            views = new HashMap();
 | 
			
		||||
        }
 | 
			
		||||
        OrderedSubnodeList osl = (OrderedSubnodeList) views.get(key);
 | 
			
		||||
        if (osl == null) {
 | 
			
		||||
            osl = new OrderedSubnodeList (nmgr, rel, this, order);
 | 
			
		||||
            views.put(key, osl);
 | 
			
		||||
        }
 | 
			
		||||
        return osl;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    protected void addToViews (Object obj) {
 | 
			
		||||
        if (views == null || views.isEmpty())
 | 
			
		||||
            return;
 | 
			
		||||
        for (Iterator i = views.values().iterator(); i.hasNext(); ) {
 | 
			
		||||
            OrderedSubnodeList osl = (OrderedSubnodeList) i.next();
 | 
			
		||||
            osl.sortIn(obj);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,8 +38,8 @@ public class UpdateableSubnodeList extends OrderedSubnodeList {
 | 
			
		|||
     * Construct a new UpdateableSubnodeList. The Relation is needed
 | 
			
		||||
     * to get the information about the ORDERING and the UPDATECriteriaS
 | 
			
		||||
     */
 | 
			
		||||
    public UpdateableSubnodeList (Relation rel) {
 | 
			
		||||
        super(rel);
 | 
			
		||||
    public UpdateableSubnodeList (WrappedNodeManager nmgr, Relation rel) {
 | 
			
		||||
        super(nmgr, rel);
 | 
			
		||||
        // check the update-criterias for updating this collection
 | 
			
		||||
        if (rel.updateCriteria == null) {
 | 
			
		||||
            // criteria-field muss vom criteria-operant getrennt werden
 | 
			
		||||
| 
						 | 
				
			
			@ -391,7 +391,7 @@ public class UpdateableSubnodeList extends OrderedSubnodeList {
 | 
			
		|||
 | 
			
		||||
    /**
 | 
			
		||||
     * if the wrapped List is an instance of OrderedSubnodeList,
 | 
			
		||||
     * the sortIn-method will be used.
 | 
			
		||||
     * the sortIn() method will be used.
 | 
			
		||||
     */
 | 
			
		||||
    public boolean addAll(Collection col) {
 | 
			
		||||
        return sortIn(col, true) > 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,16 +35,6 @@ import java.io.IOException;
 | 
			
		|||
 *
 | 
			
		||||
 */
 | 
			
		||||
public class HopObject extends ScriptableObject implements Wrapper, PropertyRecorder {
 | 
			
		||||
    static Method hopObjCtor;
 | 
			
		||||
 | 
			
		||||
    static {
 | 
			
		||||
        try {
 | 
			
		||||
            hopObjCtor = HopObject.class.getMethod("jsConstructor", new Class[] {
 | 
			
		||||
                Context.class, Object[].class, Function.class, Boolean.TYPE });
 | 
			
		||||
        } catch (NoSuchMethodException e) {
 | 
			
		||||
            throw new RuntimeException("Error getting HopObject.jsConstructor()");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    String className;
 | 
			
		||||
    INode node;
 | 
			
		||||
| 
						 | 
				
			
			@ -54,40 +44,46 @@ public class HopObject extends ScriptableObject implements Wrapper, PropertyReco
 | 
			
		|||
    private boolean isRecording = false;
 | 
			
		||||
    private HashSet changedProperties;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates a new HopObject object.
 | 
			
		||||
     */
 | 
			
		||||
    public HopObject() {
 | 
			
		||||
        className = "HopObject";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates a new HopObject prototype.
 | 
			
		||||
     *
 | 
			
		||||
     * @param cname ...
 | 
			
		||||
     * @param className the prototype name
 | 
			
		||||
     * @param core the RhinoCore
 | 
			
		||||
     */
 | 
			
		||||
    protected HopObject(String cname) {
 | 
			
		||||
        className = cname;
 | 
			
		||||
    protected HopObject(String className, RhinoCore core) {
 | 
			
		||||
        this.className = className;
 | 
			
		||||
        this.core = core;
 | 
			
		||||
        setParentScope(core.global);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Creates a new HopObject prototype.
 | 
			
		||||
     * Creates a new HopObject.
 | 
			
		||||
     *
 | 
			
		||||
     * @param cname ...
 | 
			
		||||
     * @param className the className
 | 
			
		||||
     * @param proto the object's prototype
 | 
			
		||||
     */
 | 
			
		||||
    protected HopObject(String cname, Scriptable proto) {
 | 
			
		||||
        className = cname;
 | 
			
		||||
    protected HopObject(String className, RhinoCore core,
 | 
			
		||||
                        INode node, Scriptable proto) {
 | 
			
		||||
        this(className, core);
 | 
			
		||||
        this.node = node;
 | 
			
		||||
        setPrototype(proto);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static HopObject init(Scriptable scope)
 | 
			
		||||
    /**
 | 
			
		||||
     * Initialize HopObject prototype for Rhino scope.
 | 
			
		||||
     *
 | 
			
		||||
     * @param core the RhinoCore
 | 
			
		||||
     * @return the HopObject prototype
 | 
			
		||||
     * @throws PropertyException
 | 
			
		||||
     */
 | 
			
		||||
    public static HopObject init(RhinoCore core)
 | 
			
		||||
            throws PropertyException {
 | 
			
		||||
        int attributes = READONLY | DONTENUM | PERMANENT;
 | 
			
		||||
 | 
			
		||||
        // create prototype object
 | 
			
		||||
        HopObject proto = new HopObject();
 | 
			
		||||
        proto.setPrototype(getObjectPrototype(scope));
 | 
			
		||||
        HopObject proto = new HopObject("HopObject", core);
 | 
			
		||||
        proto.setPrototype(getObjectPrototype(core.global));
 | 
			
		||||
 | 
			
		||||
        // install JavaScript methods and properties
 | 
			
		||||
        Method[] methods = HopObject.class.getDeclaredMethods();
 | 
			
		||||
| 
						 | 
				
			
			@ -109,54 +105,6 @@ public class HopObject extends ScriptableObject implements Wrapper, PropertyReco
 | 
			
		|||
        return proto;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     *  This method is used as HopObject constructor from JavaScript.
 | 
			
		||||
     */
 | 
			
		||||
    public static Object jsConstructor(Context cx, Object[] args,
 | 
			
		||||
                                              Function ctorObj, boolean inNewExpr)
 | 
			
		||||
                         throws EvaluatorException, ScriptingException {
 | 
			
		||||
        RhinoEngine engine = (RhinoEngine) cx.getThreadLocal("engine");
 | 
			
		||||
        RhinoCore core = engine.core;
 | 
			
		||||
        String protoname = ((FunctionObject) ctorObj).getFunctionName();
 | 
			
		||||
 | 
			
		||||
        // if this is a java object prototype, create a new java object
 | 
			
		||||
        // of the given class instead of a HopObject.
 | 
			
		||||
        if (core.app.isJavaPrototype(protoname)) {
 | 
			
		||||
            String classname = core.app.getJavaClassForPrototype(protoname);
 | 
			
		||||
            try {
 | 
			
		||||
                Class clazz = Class.forName(classname);
 | 
			
		||||
                // try to get the constructor matching our arguments
 | 
			
		||||
                Class[] argsTypes = new Class[args.length];
 | 
			
		||||
                for (int i=0; i<argsTypes.length; i++) {
 | 
			
		||||
                    argsTypes[i] = args[i] == null ? null : args[i].getClass();
 | 
			
		||||
                }
 | 
			
		||||
                Constructor cnst = clazz.getConstructor(argsTypes);
 | 
			
		||||
                // crate a new instance using the constructor
 | 
			
		||||
                Object obj = cnst.newInstance(args);
 | 
			
		||||
                return Context.toObject(obj, engine.global);
 | 
			
		||||
            } catch (Exception x) {
 | 
			
		||||
                System.err.println("Error in Java constructor: "+x);
 | 
			
		||||
                throw new EvaluatorException(x.toString());
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            INode node = new helma.objectmodel.db.Node(protoname, protoname,
 | 
			
		||||
                                                    core.app.getWrappedNodeManager());
 | 
			
		||||
            Scriptable proto = core.getPrototype(protoname);
 | 
			
		||||
            HopObject hobj = new HopObject(protoname, proto);
 | 
			
		||||
 | 
			
		||||
            hobj.init(core, node);
 | 
			
		||||
            if (proto != null) {
 | 
			
		||||
                engine.invoke(hobj,
 | 
			
		||||
                        "__constructor__",
 | 
			
		||||
                        args, ScriptingEngine.ARGS_WRAP_NONE,
 | 
			
		||||
                        false);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return hobj;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     *
 | 
			
		||||
     *
 | 
			
		||||
| 
						 | 
				
			
			@ -177,17 +125,6 @@ public class HopObject extends ScriptableObject implements Wrapper, PropertyReco
 | 
			
		|||
        return toString();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     *
 | 
			
		||||
     *
 | 
			
		||||
     * @param c ...
 | 
			
		||||
     * @param n ...
 | 
			
		||||
     */
 | 
			
		||||
    public void init(RhinoCore c, INode n) {
 | 
			
		||||
        core = c;
 | 
			
		||||
        node = n;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     *  Return the INode wrapped by this HopObject.
 | 
			
		||||
     *
 | 
			
		||||
| 
						 | 
				
			
			@ -217,7 +154,7 @@ public class HopObject extends ScriptableObject implements Wrapper, PropertyReco
 | 
			
		|||
     * Check if the node has been invalidated. If so, it has to be re-fetched
 | 
			
		||||
     * from the db via the app's node manager.
 | 
			
		||||
     */
 | 
			
		||||
    private final void checkNode() {
 | 
			
		||||
    private void checkNode() {
 | 
			
		||||
        if (node != null && node.getState() == INode.INVALID) {
 | 
			
		||||
            if (node instanceof helma.objectmodel.db.Node) {
 | 
			
		||||
                NodeHandle handle = ((helma.objectmodel.db.Node) node).getHandle();
 | 
			
		||||
| 
						 | 
				
			
			@ -425,7 +362,7 @@ public class HopObject extends ScriptableObject implements Wrapper, PropertyReco
 | 
			
		|||
 | 
			
		||||
        if (id instanceof Number) {
 | 
			
		||||
            n = node.getSubnodeAt(((Number) id).intValue());
 | 
			
		||||
        } else if (id != null) {
 | 
			
		||||
        } else {
 | 
			
		||||
            n = node.getChildElement(id.toString());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1132,16 +1069,12 @@ public class HopObject extends ScriptableObject implements Wrapper, PropertyReco
 | 
			
		|||
        }
 | 
			
		||||
        helma.objectmodel.db.Node n = (helma.objectmodel.db.Node) node;
 | 
			
		||||
        n.loadNodes();
 | 
			
		||||
        List subnodes = n.getSubnodeList();
 | 
			
		||||
        SubnodeList subnodes = n.getSubnodeList();
 | 
			
		||||
        if (subnodes == null) {
 | 
			
		||||
            throw new RuntimeException (
 | 
			
		||||
                    "getOrderedView only callable on already existing subnode-collections");
 | 
			
		||||
        }
 | 
			
		||||
        if (subnodes instanceof OrderedSubnodeList) {
 | 
			
		||||
            return new ListViewWrapper ((((OrderedSubnodeList) subnodes).getOrderedView(expr)),
 | 
			
		||||
        return new ListViewWrapper (subnodes.getOrderedView(expr),
 | 
			
		||||
                    core, n.getDbMapping().getWrappedNodeManager(), this);
 | 
			
		||||
        }
 | 
			
		||||
        throw new RuntimeException (
 | 
			
		||||
                "getOrderedView only callable on OrderedSubnodeList");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										149
									
								
								src/helma/scripting/rhino/HopObjectCtor.java
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										149
									
								
								src/helma/scripting/rhino/HopObjectCtor.java
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,149 @@
 | 
			
		|||
/*
 | 
			
		||||
 * Helma License Notice
 | 
			
		||||
 *
 | 
			
		||||
 * The contents of this file are subject to the Helma License
 | 
			
		||||
 * Version 2.0 (the "License"). You may not use this file except in
 | 
			
		||||
 * compliance with the License. A copy of the License is available at
 | 
			
		||||
 * http://adele.helma.org/download/helma/license.txt
 | 
			
		||||
 *
 | 
			
		||||
 * Copyright 1998-2003 Helma Software. All Rights Reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * $RCSfile$
 | 
			
		||||
 * $Author$
 | 
			
		||||
 * $Revision$
 | 
			
		||||
 * $Date$
 | 
			
		||||
 */
 | 
			
		||||
package helma.scripting.rhino;
 | 
			
		||||
 | 
			
		||||
import org.mozilla.javascript.*;
 | 
			
		||||
 | 
			
		||||
import java.lang.reflect.Constructor;
 | 
			
		||||
import java.lang.reflect.Method;
 | 
			
		||||
 | 
			
		||||
import helma.objectmodel.INode;
 | 
			
		||||
import helma.objectmodel.db.DbMapping;
 | 
			
		||||
import helma.objectmodel.db.DbKey;
 | 
			
		||||
 | 
			
		||||
public class HopObjectCtor extends FunctionObject {
 | 
			
		||||
 | 
			
		||||
    // init flag to trigger prototype compilation on
 | 
			
		||||
    // static constructor property access
 | 
			
		||||
    boolean initialized;
 | 
			
		||||
    RhinoCore core;
 | 
			
		||||
 | 
			
		||||
    static Method hopObjCtor;
 | 
			
		||||
 | 
			
		||||
    static {
 | 
			
		||||
        try {
 | 
			
		||||
            hopObjCtor = HopObjectCtor.class.getMethod("jsConstructor", new Class[] {
 | 
			
		||||
                Context.class, Object[].class, Function.class, Boolean.TYPE });
 | 
			
		||||
        } catch (NoSuchMethodException e) {
 | 
			
		||||
            throw new RuntimeException("Error getting HopObjectCtor.jsConstructor()");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    static final int attr = ScriptableObject.DONTENUM  |
 | 
			
		||||
                            ScriptableObject.PERMANENT |
 | 
			
		||||
                            ScriptableObject.READONLY;
 | 
			
		||||
    /**
 | 
			
		||||
     * Create and install a HopObject constructor.
 | 
			
		||||
     * Part of this is copied from o.m.j.FunctionObject.addAsConstructor().
 | 
			
		||||
     *
 | 
			
		||||
     * @param prototype
 | 
			
		||||
     */
 | 
			
		||||
    public HopObjectCtor(String protoName, RhinoCore core, Scriptable prototype) {
 | 
			
		||||
        super(protoName, hopObjCtor, core.global);
 | 
			
		||||
        this.core = core;
 | 
			
		||||
        // Scriptable ps = prototype.getParentScope();
 | 
			
		||||
        addAsConstructor(core.global, prototype);
 | 
			
		||||
        // prototype.setParentScope(ps);
 | 
			
		||||
        defineProperty("getById", new GetById(), attr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     *  This method is used as HopObject constructor from JavaScript.
 | 
			
		||||
     */
 | 
			
		||||
    public static Object jsConstructor(Context cx, Object[] args,
 | 
			
		||||
                                       Function ctorObj, boolean inNewExpr)
 | 
			
		||||
                         throws JavaScriptException {
 | 
			
		||||
        HopObjectCtor ctor = (HopObjectCtor) ctorObj;
 | 
			
		||||
        RhinoCore core = ctor.core;
 | 
			
		||||
        String protoname = ctor.getFunctionName();
 | 
			
		||||
 | 
			
		||||
        // if this is a java object prototype, create a new java object
 | 
			
		||||
        // of the given class instead of a HopObject.
 | 
			
		||||
        if (core.app.isJavaPrototype(protoname)) {
 | 
			
		||||
            String classname = core.app.getJavaClassForPrototype(protoname);
 | 
			
		||||
            try {
 | 
			
		||||
                Class clazz = Class.forName(classname);
 | 
			
		||||
                // try to get the constructor matching our arguments
 | 
			
		||||
                Class[] argsTypes = new Class[args.length];
 | 
			
		||||
                for (int i=0; i<argsTypes.length; i++) {
 | 
			
		||||
                    argsTypes[i] = args[i] == null ? null : args[i].getClass();
 | 
			
		||||
                }
 | 
			
		||||
                Constructor cnst = clazz.getConstructor(argsTypes);
 | 
			
		||||
                // crate a new instance using the constructor
 | 
			
		||||
                Object obj = cnst.newInstance(args);
 | 
			
		||||
                return Context.toObject(obj, core.global);
 | 
			
		||||
            } catch (Exception x) {
 | 
			
		||||
                System.err.println("Error in Java constructor: "+x);
 | 
			
		||||
                throw new EvaluatorException(x.toString());
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            INode node = new helma.objectmodel.db.Node(protoname, protoname,
 | 
			
		||||
                                                    core.app.getWrappedNodeManager());
 | 
			
		||||
            Scriptable proto = core.getPrototype(protoname);
 | 
			
		||||
            HopObject hobj = new HopObject(protoname, core, node, proto);
 | 
			
		||||
 | 
			
		||||
            if (proto != null) {
 | 
			
		||||
                Object f = ScriptableObject.getProperty(proto, "__constructor__");
 | 
			
		||||
                if (f instanceof Function) {
 | 
			
		||||
                    ((Function) f).call(cx, core.global, hobj, args);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return hobj;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public Object get(String name, Scriptable start) {
 | 
			
		||||
        if (!initialized  && !"prototype".equals(name)) {
 | 
			
		||||
            // trigger prototype compilation on static
 | 
			
		||||
            // constructor property access
 | 
			
		||||
            initialized = true;
 | 
			
		||||
            core.getPrototype(functionName);
 | 
			
		||||
        }
 | 
			
		||||
        return super.get(name, start);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    class GetById extends BaseFunction {
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Retrieve any persistent HopObject by type name and id.
 | 
			
		||||
         *
 | 
			
		||||
         * @return the HopObject or null if it doesn't exist
 | 
			
		||||
         */
 | 
			
		||||
        public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
 | 
			
		||||
            if (args.length < 1 || args.length > 2)
 | 
			
		||||
                throw new IllegalArgumentException("Wrong number of arguments in getById()");
 | 
			
		||||
            // If second argument is provided, use it as type name.
 | 
			
		||||
            // Otherwise, use our own type name.
 | 
			
		||||
            String type = args.length == 1 ?
 | 
			
		||||
                    HopObjectCtor.this.getFunctionName() :
 | 
			
		||||
                    Context.toString(args[1]);
 | 
			
		||||
 | 
			
		||||
            DbMapping dbmap = core.app.getDbMapping(type);
 | 
			
		||||
            if (dbmap == null)
 | 
			
		||||
                return null;
 | 
			
		||||
            Object node = null;
 | 
			
		||||
            try {
 | 
			
		||||
                DbKey key = new DbKey(dbmap, Context.toString(args[0]));
 | 
			
		||||
                node = core.app.getNodeManager().getNode(key);
 | 
			
		||||
            } catch (Exception x) {
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
            return node == null ? null : Context.toObject(node, this);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -46,6 +46,26 @@ public class ListViewWrapper extends ScriptableObject implements Wrapper, Script
 | 
			
		|||
    final HopObject hObj;
 | 
			
		||||
    INode node;
 | 
			
		||||
 | 
			
		||||
    static ListViewWrapper listViewProto;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Private constructor used to create the object prototype.
 | 
			
		||||
     */
 | 
			
		||||
    private ListViewWrapper() {
 | 
			
		||||
        list = null;
 | 
			
		||||
        core = null;
 | 
			
		||||
        wnm = null;
 | 
			
		||||
        node = null;
 | 
			
		||||
        hObj = null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a JS wrapper around a subnode list.
 | 
			
		||||
     * @param list
 | 
			
		||||
     * @param core
 | 
			
		||||
     * @param wnm
 | 
			
		||||
     * @param hObj
 | 
			
		||||
     */
 | 
			
		||||
    ListViewWrapper (List list, RhinoCore core, WrappedNodeManager wnm, HopObject hObj) {
 | 
			
		||||
        if (list == null) {
 | 
			
		||||
            throw new IllegalArgumentException ("ListWrapper unable to wrap null list.");
 | 
			
		||||
| 
						 | 
				
			
			@ -55,13 +75,20 @@ public class ListViewWrapper extends ScriptableObject implements Wrapper, Script
 | 
			
		|||
        this.wnm = wnm;
 | 
			
		||||
        this.hObj = hObj;
 | 
			
		||||
        this.node = hObj.node;
 | 
			
		||||
        init();
 | 
			
		||||
        if (listViewProto == null) {
 | 
			
		||||
            listViewProto = new ListViewWrapper();
 | 
			
		||||
            listViewProto.init();
 | 
			
		||||
        }
 | 
			
		||||
        setPrototype(listViewProto);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void init() {
 | 
			
		||||
    /**
 | 
			
		||||
     * Init JS functions from methods.
 | 
			
		||||
     */
 | 
			
		||||
    void init() {
 | 
			
		||||
        int attributes = READONLY | DONTENUM | PERMANENT;
 | 
			
		||||
        
 | 
			
		||||
        Method[] methods = this.getClass().getDeclaredMethods();
 | 
			
		||||
        Method[] methods = getClass().getDeclaredMethods();
 | 
			
		||||
        for (int i=0; i<methods.length; i++) {
 | 
			
		||||
            String methodName = methods[i].getName();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -70,7 +97,6 @@ public class ListViewWrapper extends ScriptableObject implements Wrapper, Script
 | 
			
		|||
                FunctionObject func = new FunctionObject(methodName,
 | 
			
		||||
                                                         methods[i], this);
 | 
			
		||||
                this.defineProperty(methodName, func, attributes);
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -98,9 +124,7 @@ public class ListViewWrapper extends ScriptableObject implements Wrapper, Script
 | 
			
		|||
        
 | 
			
		||||
        // return HopObject in case of a NodeHandle
 | 
			
		||||
        if (obj instanceof NodeHandle) {
 | 
			
		||||
            HopObject hObj = new HopObject();
 | 
			
		||||
            hObj.init(core, ((NodeHandle) obj).getNode(wnm));
 | 
			
		||||
            return hObj;
 | 
			
		||||
            return Context.toObject(((NodeHandle) obj).getNode(wnm), core.global);
 | 
			
		||||
        } else if (!(obj instanceof Scriptable)) {
 | 
			
		||||
            // do NOT wrap primitives - otherwise they'll be wrapped as Objects,
 | 
			
		||||
            // which makes them unusable for many purposes (e.g. ==)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -113,7 +113,7 @@ public final class RhinoCore implements ScopeProvider {
 | 
			
		|||
 | 
			
		||||
            pathProto = new PathWrapper(this);
 | 
			
		||||
 | 
			
		||||
            hopObjectProto =  HopObject.init(global);
 | 
			
		||||
            hopObjectProto =  HopObject.init(this);
 | 
			
		||||
            // use lazy loaded constructors for all extension objects that
 | 
			
		||||
            // adhere to the ScriptableObject.defineClass() protocol
 | 
			
		||||
            new LazilyLoadedCtor(global, "File",
 | 
			
		||||
| 
						 | 
				
			
			@ -207,10 +207,9 @@ public final class RhinoCore implements ScopeProvider {
 | 
			
		|||
            } else if ("hopobject".equals(lowerCaseName)) {
 | 
			
		||||
                op = hopObjectProto;
 | 
			
		||||
            } else {
 | 
			
		||||
                op = new HopObject(name);
 | 
			
		||||
                op.setParentScope(global);
 | 
			
		||||
                op = new HopObject(name, this);
 | 
			
		||||
            }
 | 
			
		||||
            type = registerPrototype(prototype, op);
 | 
			
		||||
            registerPrototype(prototype, op);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Register a constructor for all types except global.
 | 
			
		||||
| 
						 | 
				
			
			@ -218,13 +217,10 @@ public final class RhinoCore implements ScopeProvider {
 | 
			
		|||
        // the actual (scripted) constructor on it.
 | 
			
		||||
        if (!"global".equals(lowerCaseName)) {
 | 
			
		||||
            try {
 | 
			
		||||
                FunctionObject fo = new FunctionObject(name, HopObject.hopObjCtor, global);
 | 
			
		||||
                fo.addAsConstructor(global, op);
 | 
			
		||||
                // add static getById() function
 | 
			
		||||
                fo.defineProperty("getById", new GetById(name), GetById.ATTRIBUTES);
 | 
			
		||||
            } catch (Exception ignore) {
 | 
			
		||||
                System.err.println("Error adding ctor for " + name + ": " + ignore);
 | 
			
		||||
                ignore.printStackTrace();
 | 
			
		||||
                new HopObjectCtor(name, this, op);
 | 
			
		||||
                op.setParentScope(global);
 | 
			
		||||
            } catch (Exception x) {
 | 
			
		||||
                app.logError("Error adding ctor for " + name,  x);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -294,58 +290,52 @@ public final class RhinoCore implements ScopeProvider {
 | 
			
		|||
     *  here is to check for update those prototypes which already have been compiled
 | 
			
		||||
     *  before. Others will be updated/compiled on demand.
 | 
			
		||||
     */
 | 
			
		||||
    public void updatePrototypes() throws IOException {
 | 
			
		||||
    public synchronized void updatePrototypes() throws IOException {
 | 
			
		||||
        if ((System.currentTimeMillis() - lastUpdate) < 1000L + updateSnooze) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        synchronized(this) {
 | 
			
		||||
            if ((System.currentTimeMillis() - lastUpdate) < 1000L + updateSnooze) {
 | 
			
		||||
                return;
 | 
			
		||||
        // init prototypes and/or update prototype checksums
 | 
			
		||||
        app.typemgr.checkPrototypes();
 | 
			
		||||
 | 
			
		||||
        // get a collection of all prototypes (code directories)
 | 
			
		||||
        Collection protos = app.getPrototypes();
 | 
			
		||||
 | 
			
		||||
        // in order to respect inter-prototype dependencies, we try to update
 | 
			
		||||
        // the global prototype before all other prototypes, and parent
 | 
			
		||||
        // prototypes before their descendants.
 | 
			
		||||
 | 
			
		||||
        HashSet checked = new HashSet(protos.size() * 2);
 | 
			
		||||
 | 
			
		||||
        TypeInfo type = (TypeInfo) prototypes.get("global");
 | 
			
		||||
 | 
			
		||||
        if (type != null) {
 | 
			
		||||
            updatePrototype(type, checked);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (Iterator i = protos.iterator(); i.hasNext();) {
 | 
			
		||||
            Prototype proto = (Prototype) i.next();
 | 
			
		||||
 | 
			
		||||
            if (checked.contains(proto)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // init prototypes and/or update prototype checksums
 | 
			
		||||
            app.typemgr.checkPrototypes();
 | 
			
		||||
            type = (TypeInfo) prototypes.get(proto.getLowerCaseName());
 | 
			
		||||
 | 
			
		||||
            // get a collection of all prototypes (code directories)
 | 
			
		||||
            Collection protos = app.getPrototypes();
 | 
			
		||||
 | 
			
		||||
            // in order to respect inter-prototype dependencies, we try to update
 | 
			
		||||
            // the global prototype before all other prototypes, and parent
 | 
			
		||||
            // prototypes before their descendants.
 | 
			
		||||
 | 
			
		||||
            HashSet checked = new HashSet(protos.size() * 2);
 | 
			
		||||
 | 
			
		||||
            TypeInfo type = (TypeInfo) prototypes.get("global");
 | 
			
		||||
 | 
			
		||||
            if (type != null) {
 | 
			
		||||
            if (type == null) {
 | 
			
		||||
                // a prototype we don't know anything about yet. Init local update info.
 | 
			
		||||
                initPrototype(proto);
 | 
			
		||||
            } else if (type.lastUpdate > -1) {
 | 
			
		||||
                // only need to update prototype if it has already been initialized.
 | 
			
		||||
                // otherwise, this will be done on demand.
 | 
			
		||||
                updatePrototype(type, checked);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            for (Iterator i = protos.iterator(); i.hasNext();) {
 | 
			
		||||
                Prototype proto = (Prototype) i.next();
 | 
			
		||||
 | 
			
		||||
                if (checked.contains(proto)) {
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                type = (TypeInfo) prototypes.get(proto.getLowerCaseName());
 | 
			
		||||
 | 
			
		||||
                if (type == null) {
 | 
			
		||||
                    // a prototype we don't know anything about yet. Init local update info.
 | 
			
		||||
                    initPrototype(proto);
 | 
			
		||||
                } else if (type.lastUpdate > -1) {
 | 
			
		||||
                    // only need to update prototype if it has already been initialized.
 | 
			
		||||
                    // otherwise, this will be done on demand.
 | 
			
		||||
                    updatePrototype(type, checked);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            lastUpdate = System.currentTimeMillis();
 | 
			
		||||
            // max updateSnooze is 4 seconds, reached after 66.6 idle minutes
 | 
			
		||||
            long newSnooze = (lastUpdate - app.typemgr.getLastCodeUpdate()) / 1000;
 | 
			
		||||
            updateSnooze = Math.min(4000, Math.max(0, newSnooze));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        lastUpdate = System.currentTimeMillis();
 | 
			
		||||
        // max updateSnooze is 4 seconds, reached after 66.6 idle minutes
 | 
			
		||||
        long newSnooze = (lastUpdate - app.typemgr.getLastCodeUpdate()) / 1000;
 | 
			
		||||
        updateSnooze = Math.min(4000, Math.max(0, newSnooze));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			@ -638,8 +628,7 @@ public final class RhinoCore implements ScopeProvider {
 | 
			
		|||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            esn = new HopObject(protoname, op);
 | 
			
		||||
            esn.init(this, n);
 | 
			
		||||
            esn = new HopObject(protoname, this, n, op);
 | 
			
		||||
 | 
			
		||||
            wrappercache.put(n, esn);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -1077,41 +1066,7 @@ public final class RhinoCore implements ScopeProvider {
 | 
			
		|||
            } else {
 | 
			
		||||
                df = new DecimalFormat("#,##0.00");
 | 
			
		||||
            }
 | 
			
		||||
            return df.format(ScriptRuntime.toNumber(thisObj)).toString();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    class GetById extends BaseFunction {
 | 
			
		||||
        static final int ATTRIBUTES = DONTENUM | PERMANENT | READONLY;
 | 
			
		||||
        String typeName;
 | 
			
		||||
 | 
			
		||||
        public GetById(String typeName) {
 | 
			
		||||
            this.typeName = typeName;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Retrieve any persistent HopObject by type name and id.
 | 
			
		||||
         *
 | 
			
		||||
         * @return the HopObject or null if it doesn't exist
 | 
			
		||||
         */
 | 
			
		||||
        public Object call(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) {
 | 
			
		||||
            if (args.length < 1 || args.length > 2)
 | 
			
		||||
                throw new IllegalArgumentException("Wrong number of arguments in getById()");
 | 
			
		||||
            // If second argument is provided, use it as type name.
 | 
			
		||||
            // Otherwise, use our own type name.
 | 
			
		||||
            String type = args.length == 1 ? typeName: Context.toString(args[1]); 
 | 
			
		||||
 | 
			
		||||
            DbMapping dbmap = app.getDbMapping(type);
 | 
			
		||||
            if (dbmap == null)
 | 
			
		||||
                return null;
 | 
			
		||||
            Object node = null;
 | 
			
		||||
            try {
 | 
			
		||||
                DbKey key = new DbKey(dbmap, Context.toString(args[0]));
 | 
			
		||||
                node = app.getNodeManager().getNode(key);
 | 
			
		||||
            } catch (Exception x) {
 | 
			
		||||
                return null;
 | 
			
		||||
            }
 | 
			
		||||
            return node == null ? null : Context.toObject(node, this);
 | 
			
		||||
            return df.format(ScriptRuntime.toNumber(thisObj));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue