Object v = reval.invokeDirectFunction (handlerObject, name+"_macro", arguments);
Object v = null; if (reval.hasFunction (handlerObject, name+"_macro")) {  v = reval.invokeDirectFunction (handlerObject, name+"_macro", arguments); } else {  v = reval.getProperty (handlerObject, name); }
	public void render (RequestEvaluator reval, Object thisObject, HashMap paramObject) throws RedirectException {	    if (sandbox != null && !sandbox.contains (getFullName ())) {	        String h = handler == null ? "global" : handler;	        reval.res.write ("[Macro "+getFullName()+" not allowed in sandbox]");	        return;	    } else if ("response".equalsIgnoreCase (handler)) {	        renderFromResponse (reval);	        return;	    } else if ("request".equalsIgnoreCase (handler)) {	        renderFromRequest (reval);	        return;	    } else if ("param".equalsIgnoreCase (handler)) {	        renderFromParam (reval, paramObject);	        return;	    }	    try {	        Object handlerObject = null;	        Object[] arguments = new Object[1];	        arguments[0] = parameters;		        // flag to tell whether we found our invocation target object	        boolean objectFound = true;	        if (handler != null) {	            if ("currentuser".equalsIgnoreCase (handler)) {	                // as a special convention, we use "currentuser" to access macros in the current user object	                handlerObject = reval.user.getNode ();	            } else if (thisObject != null) {	                // not a global macro - need to find handler object	                // was called with this object - check it or its parents for matching prototype	                if (!handler.equalsIgnoreCase ("this") && !handler.equalsIgnoreCase (app.getPrototypeName (thisObject))) {	                    // the handler object is not what we want	                    Object n = thisObject;	                    // walk down parent chain to find handler object	                    while (n != null) {	                        if (handler.equalsIgnoreCase (app.getPrototypeName (n))) {	                            handlerObject = n;	                            break;	                        }	                        n = app.getParentElement (n);	                    }	                } else {	                    // we already have the right handler object	                    handlerObject = thisObject;	                }	            }	            if (handlerObject == null) {	                // eiter because thisObject == null or the right object wasn't found in the object's parent path	                // go check request path for an object with matching prototype	                int l = reval.reqPath.size();	                for (int i=l-1; i>=0; i--) {	                    Object pathelem = reval.reqPath.getProperty (i).toJavaObject ();	                    if (handler.equalsIgnoreCase (app.getPrototypeName (pathelem))) {	                         handlerObject = pathelem;	                         break;	                    }	                }	            }		            // the macro handler object couldn't be found	            if (handlerObject == null)	                objectFound = false;	        } else {	            // this is a global macro with no handler specified	            handlerObject = null;	        }	        if (objectFound) {	            Object v = reval.invokeDirectFunction (handlerObject, name+"_macro", arguments);	            // ESValue v = handlerObject.doIndirectCall (reval.evaluator, handlerObject, name+"_macro", arguments);	            if (v != null)	                reval.res.write (v);	        } else {	            String msg = "[HopMacro unhandled: "+getFullName()+"]";	            reval.res.write (" "+msg+" ");	            app.logEvent (msg);	        }	    } catch (RedirectException redir) {	        throw redir;	    } catch (ConcurrencyException concur) {	        throw concur;	    } catch (Exception x) {	        x.printStackTrace();	        String msg = "[HopMacro error: "+x+"]";	        reval.res.write (" "+msg+" ");	        app.logEvent (msg);	    }	}