Author: michiel
Date: 2009-11-18 22:36:52 +0100 (Wed, 18 Nov 2009)
New Revision: 39788

Added:
   
mmbase/trunk/core/src/main/java/org/mmbase/module/core/MMObjectNodeFunction.java
Modified:
   mmbase/trunk/core/src/main/java/org/mmbase/module/core/MMObjectBuilder.java
Log:
  MMB-1896

Modified: 
mmbase/trunk/core/src/main/java/org/mmbase/module/core/MMObjectBuilder.java
===================================================================
--- mmbase/trunk/core/src/main/java/org/mmbase/module/core/MMObjectBuilder.java 
2009-11-18 20:47:11 UTC (rev 39787)
+++ mmbase/trunk/core/src/main/java/org/mmbase/module/core/MMObjectBuilder.java 
2009-11-18 21:36:52 UTC (rev 39788)
@@ -274,15 +274,24 @@
         };
     {
         addFunction(wrapFunction);
+
+        addFunction(new AbstractFunction<Integer>("defaultSearchAge", 
Parameter.emptyArray(), ReturnType.INTEGER) {
+                @Override
+                public Integer getFunctionValue(Parameters params) {
+                    return 
Integer.parseInt(MMObjectBuilder.this.getSearchAge());
+                }
+            });
     }
 
+
+
     private static final ReturnType<Collection<? extends Function>> 
RETURNTYPE_COLLECTION = new ReturnType<Collection<? extends 
Function>>(Collection.class, "Collection");
     /**
      * Every Function Provider provides least the 'getFunctions' function, 
which returns a Set of all functions which it provides.
      * This is overridden from FunctionProvider, because this one needs to be 
(also) a NodeFunction
      * @since MMBase-1.8
      */
-    protected Function<Collection<? extends Function>> getFunctions = new 
NodeFunction<Collection<? extends Function>>("getFunctions",
+    protected Function<Collection<? extends Function>> getFunctions = new 
MMObjectNodeFunction<Collection<? extends Function>>("getFunctions",
                                                                                
                                        Parameter.emptyArray(), 
RETURNTYPE_COLLECTION) {
 
             {
@@ -309,7 +318,7 @@
      * The info-function is a node-function and a builder-function. Therefore 
it is defined as a node-function, but also overidesd 
getFunctionValue(Parameters).
      * @since MMBase-1.8
      */
-    protected Function<Object> infoFunction = new NodeFunction<Object>("info", 
INFO_FUNCTION_ARGS, ReturnType.UNKNOWN) {
+    protected Function<Object> infoFunction = new 
MMObjectNodeFunction<Object>("info", INFO_FUNCTION_ARGS, ReturnType.UNKNOWN) {
             {
                 setDescription("Returns information about available 
functions");
             }
@@ -1785,7 +1794,7 @@
     protected Function<?> getFunction(MMObjectNode node, String functionName) {
         Function<?> function = getFunction(functionName);
         if (function instanceof NodeFunction) {
-            return ((NodeFunction<?>) function).newInstance(node);
+            return MMObjectNodeFunction.newInstance((NodeFunction<?>) 
function, node);
         } else {
             return null;
         }
@@ -1799,7 +1808,7 @@
         Collection<Function<?>> nodeFunctions = new HashSet<Function<?>>();
         for (Function<?> function : getFunctions()) {
             if (function instanceof NodeFunction) {
-                nodeFunctions.add(((NodeFunction<?>) 
function).newInstance(node));
+                
nodeFunctions.add(MMObjectNodeFunction.newInstance((NodeFunction<?>) function, 
node));
             }
         }
         return nodeFunctions;
@@ -1811,7 +1820,7 @@
      * @since MMBase-1.8
      */
     protected Function newFunctionInstance(String name, Parameter[] 
parameters, ReturnType returnType) {
-        return new NodeFunction<Object>(name, parameters, returnType) {
+        return new MMObjectNodeFunction<Object>(name, parameters, returnType) {
             @Override public Object getFunctionValue(Node node, Parameters 
parameters) {
                 return 
MMObjectBuilder.this.executeFunction(getCoreNode(MMObjectBuilder.this, node),
                                                             name,

Added: 
mmbase/trunk/core/src/main/java/org/mmbase/module/core/MMObjectNodeFunction.java
===================================================================
--- 
mmbase/trunk/core/src/main/java/org/mmbase/module/core/MMObjectNodeFunction.java
                            (rev 0)
+++ 
mmbase/trunk/core/src/main/java/org/mmbase/module/core/MMObjectNodeFunction.java
    2009-11-18 21:36:52 UTC (rev 39788)
@@ -0,0 +1,193 @@
+/*
+
+This software is OSI Certified Open Source Software.
+OSI Certified is a certification mark of the Open Source Initiative.
+
+The license (Mozilla version 1.0) can be read at the MMBase site.
+See http://www.MMBase.org/license
+
+*/
+package org.mmbase.module.core;
+
+import java.util.*;
+import org.mmbase.bridge.*;
+
+import org.mmbase.util.functions.*;
+import org.mmbase.util.logging.Logger;
+import org.mmbase.util.logging.Logging;
+
+/**
+ * Sometimes you may want to implement a function on a node based on an 
{...@link MMObjectNode} instance.
+ * This provides {...@link #getCoreNode}, which can be used to produce an 
instance of that.
+ *
+ * @author Michiel Meeuwissen
+ * @version $Id: NodeFunction.java 38475 2009-09-07 14:10:55Z michiel $
+ * @see org.mmbase.module.core.MMObjectBuilder#executeFunction
+ * @see org.mmbase.bridge.Node#getFunctionValue
+ * @see org.mmbase.util.functions.BeanFunction
+ * @since MMBase-1.9.2
+ */
+
+public abstract class MMObjectNodeFunction<R> extends NodeFunction<R> {
+
+    private static final Logger log = 
Logging.getLoggerInstance(MMObjectNodeFunction.class);
+
+
+    public static <Q> Function<Q> newInstance(NodeFunction<Q> function, 
MMObjectNode node) {
+        return new MMObjectNodeInstanceFunction(function, node);
+    }
+
+    public MMObjectNodeFunction(String name, Parameter<?>[] def, ReturnType<R> 
returnType) {
+        super(name, getNodeParameterDef(def), returnType);
+    }
+    /**
+     * @since MMBase-1.9
+     */
+    public MMObjectNodeFunction(String name, Parameter... def) {
+        super(name, getNodeParameterDef(def));
+    }
+
+    /**
+     * Returns a new instance of NodeInstanceFunction, which represents an 
actual Function.
+     */
+    final public Function<R> newInstance(MMObjectNode node) {
+        return new MMObjectNodeInstanceFunction(this, node);
+    }
+
+
+    protected static Parameter[] getNodeParameterDef(Parameter... def) {
+        List<Parameter> defList = new ArrayList(Arrays.asList(def));
+        if (! defList.contains(Parameter.NODE)) defList.add(Parameter.NODE);
+        if (! defList.contains(Parameter.CLOUD)) defList.add(Parameter.CLOUD);
+        if (! defList.contains(Parameter.CORENODE)) 
defList.add(Parameter.CORENODE);
+        return defList.toArray(Parameter.emptyArray());
+    }
+
+
+    protected static Node getNode(final MMObjectNode coreNode, final 
Parameters parameters) {
+        if (coreNode == null) throw new RuntimeException("No node argument 
given for (" + parameters + ")!");
+        Node node = parameters.get(Parameter.NODE);
+        if (node == null) {
+            Cloud cloud   = parameters.get(Parameter.CLOUD);
+            if (cloud == null) {
+                // lets try this
+                try {
+                    cloud = 
org.mmbase.bridge.ContextProvider.getDefaultCloudContext().getCloud("mmbase", 
"class", null);
+                } catch (org.mmbase.security.SecurityException se) {
+                    // perhaps class-security not implemented by security 
implementation.
+                    log.warn("" + se.getMessage());
+                    cloud = 
org.mmbase.bridge.ContextProvider.getDefaultCloudContext().getCloud("mmbase");
+                }
+                if (cloud == null) {
+                    throw new RuntimeException("No cloud argument given (" + 
parameters + ")!" + Logging.stackTrace());
+                }
+            }
+            if (coreNode instanceof org.mmbase.module.core.VirtualNode) {
+                node = new 
org.mmbase.bridge.implementation.VirtualNode((org.mmbase.module.core.VirtualNode)
 coreNode, cloud);
+                log.debug("Core node is virtual, taking bridge node " + node);
+            } else {
+                int number = coreNode.getNumber();
+                if (number == -1) {
+                    // must be in transaction or uncommited node
+                    String tmpNumber = 
coreNode.getStringValue(MMObjectBuilder.TMP_FIELD_NUMBER);
+                    if (cloud.hasNode(tmpNumber)) {
+                        node = cloud.getNode(tmpNumber);
+                        log.debug("Found transactional (?) node " + node + " 
from "  + cloud);
+                    } else {
+                        // last resort..., we're really desperate now.
+                        // This happens when calling gui() in transaction.
+                        // Perhaps we need something like a public new 
BasicNode(MMobjectNode, Cloud). Abusing VirtualNode for similar purpose now.
+                        org.mmbase.module.core.VirtualNode virtual = new 
org.mmbase.module.core.VirtualNode(coreNode.getBuilder());
+                        for (Map.Entry<String, Object> entry : 
coreNode.getValues().entrySet()) {
+                            virtual.storeValue(entry.getKey(), 
entry.getValue());
+                        }
+                        node = new 
org.mmbase.bridge.implementation.VirtualNode(virtual, cloud);
+                        log.debug("Found transaction (?) node " + node + ". 
Not in cloud " + cloud + " taking"  + node);
+                    }
+                } else {
+                    if (cloud.mayRead(number)) {
+                        node = cloud.getNode(number);
+                        log.debug("Node exists, taking " + node + " from " + 
cloud);
+                    } else {
+                        log.warn("Could not produce Bridge Node for '" + 
number + "', cannot execute node function.");
+                        return null;
+                    }
+                }
+            }
+            parameters.set(Parameter.NODE, node);
+        } else {
+            log.debug("node as param: " + node);
+        }
+        return node;
+    }
+
+
+    /**
+     * Implements the function on a certain node. Override this method 
<em>or</em> it's bridge
+     * counter-part {...@link #getFunctionValue(org.mmbase.bridge.Node, 
Parameters)}.  Overriding the
+     * bridge version has two advantages. It's easier, and mmbase security 
will be honoured. That
+     * last thing is of course not necesary if you are not going to use other 
nodes.
+     *
+     * XXX: made final because it does not work well if you don't implement a 
bridge version
+     */
+    protected final R getFunctionValue(final MMObjectNode coreNode, final 
Parameters parameters) {
+        Node node = getNode(coreNode, parameters);
+        return getFunctionValue(node, parameters);
+    }
+
+
+
+    /**
+     * Utility method to convert a {...@link org.mmbase.bridge.Node} to a 
{...@link org.mmbase.module.core.MMObjectNode}.
+     */
+    protected final  MMObjectNode getCoreNode(final MMObjectBuilder builder, 
final Node node) {
+        if (node instanceof org.mmbase.bridge.implementation.VirtualNode) {
+            MMObjectNode n = ((org.mmbase.bridge.implementation.VirtualNode) 
node).getNodeRef();
+            if (log.isDebugEnabled()) {
+                log.debug("" + node + " -> " + n);
+            }
+            return n;
+        } else {
+            MMObjectNode n = builder.getNode(node.getNumber());
+            if (log.isDebugEnabled()) {
+                log.debug("" + node + " -> " + n);
+            }
+            return n;
+        }
+
+    }
+
+    /**
+     * This represents the function on one specific Node. This is instantiated 
when new Istance
+     * if called on a NodeFunction.
+     */
+    private static class MMObjectNodeInstanceFunction<Q> extends 
WrappedFunction<Q> {
+
+        protected MMObjectNode node;
+
+
+        public MMObjectNodeInstanceFunction(NodeFunction<Q> function, 
MMObjectNode node) {
+            super(function);
+            this.node = node;
+        }
+        @Override
+        public final Q getFunctionValue(Parameters parameters) {
+            if (wrappedFunction instanceof MMObjectNodeFunction) {
+                parameters.set(Parameter.CORENODE, node);
+                return ((MMObjectNodeFunction<Q>) 
wrappedFunction).getFunctionValue(node, parameters);
+            } else {
+                Node n = MMObjectNodeFunction.getNode(node, parameters);
+                return ((NodeFunction<Q>) 
wrappedFunction).getFunctionValue(parameters);
+            }
+
+        }
+
+        @Override
+        public String toString() {
+            return wrappedFunction.toString() + " for node " + 
node.getNumber();
+        }
+    }
+
+}
+
+

_______________________________________________
Cvs mailing list
[email protected]
http://lists.mmbase.org/mailman/listinfo/cvs

Reply via email to