001: package org.mmbase.util.functions;
002:
003: import java.util.*;
004:
005: import org.mmbase.bridge.*;
006: import org.mmbase.storage.search.*;
007: import org.mmbase.module.core.*;
008: import org.mmbase.storage.search.SortOrder;
009: import org.mmbase.util.logging.*;
010:
011: /**
012: * Example builder implementation implementing functions. Lots of people are sooner or earlier
013: * trying to make their own builder implementation. Especially whith the advent the 'function' tags in
014: * 1.7 it would be nice that people could seen an example of how that could be done.
015: *
016: * To try it out, take a builder xml and add
017: * <code><classfile>org.mmbase.util.functions.ExampleBuilder</classfile> </code>
018: * and e.g. a jsp like this:
019: * <code>
020: * <pre>
021: * <mm:listnodes type="pools" max="1">
022: * < mm:import id="max">100</mm:import>
023: * <mm:nodelistfunction referids="max" name="latest">
024: * -- <mm:field name="number" /><br />
025: * </mm:nodelistfunction>
026: * </mm:listnodes>
027: * </pre>
028: * </code>
029: *
030: * This is done in the MyNews examples (on the news builder), and example JSP's can be found on /mmexamples/taglib/functions.jsp.
031: *
032: * @author Michiel Meeuwissen
033: * @version $Id: ExampleBuilder.java,v 1.18 2007/07/02 14:28:29 michiel Exp $
034: * @see ExampleBean For examples on hot to add functions to a builder without extending it.
035: * @since MMBase-1.7
036: */
037: public class ExampleBuilder extends MMObjectBuilder {
038: private static final Logger log = Logging
039: .getLoggerInstance(ExampleBuilder.class);
040:
041: /**
042: * Parameter constant for use bij the 'latest' function. This constant must be protected,
043: * otherwise it is pickup up by the automatich function detection.
044: */
045: protected final static Parameter[] LISTLATEST_PARAMETERS = {
046: new Parameter<Integer>("max", Integer.class, 10), /* name, type, default value */
047: new Parameter<Cloud>(Parameter.CLOUD, true) /* true: required! */
048: };
049:
050: protected final static Parameter[] SUMFIELDS_PARAMETERS = { new Parameter(
051: "fields", List.class, Arrays.asList(new String[] { "otype",
052: "number" })) /* name, type, default value */
053: };
054:
055: /**
056: * Implementation of 'builder function', which can be compared with a static method in java.
057: */
058: protected final Function<NodeList> listLatestFunction = new AbstractFunction<NodeList>(
059: "latest", LISTLATEST_PARAMETERS) {
060: {
061: setDescription("This (rather silly) function returns the latest instances of this builder.");
062: }
063:
064: public NodeList getFunctionValue(Parameters parameters) {
065: Integer max = (Integer) parameters.get("max");
066: Cloud cloud = parameters.get(Parameter.CLOUD);
067: NodeManager this Manager = cloud
068: .getNodeManager(getTableName());
069: NodeQuery q = this Manager.createQuery();
070: q.setMaxNumber(max.intValue());
071: q.addSortOrder(q.getStepField(this Manager
072: .getField("number")), SortOrder.ORDER_DESCENDING);
073: return this Manager.getList(q);
074: }
075: };
076: {
077: // functions must be registered.
078: addFunction(listLatestFunction);
079: }
080:
081: /**
082: * Implementation of 'node function', which can be compared with a instance method in java.
083: */
084: protected final Function<Integer> sumFieldsFunction = new NodeFunction<Integer>(
085: "sumfields", SUMFIELDS_PARAMETERS) {
086: {
087: setDescription("This (rather silly) function returns the sum of the given fields of a certain node");
088: }
089:
090: public Integer getFunctionValue(Node node, Parameters parameters) {
091: List fields = (List) parameters.get("fields");
092: int result = 0;
093: Iterator i = fields.iterator();
094: while (i.hasNext()) {
095: result += node.getIntValue((String) i.next());
096: }
097: return result;
098: }
099: };
100: {
101: // node-function are registered in the same way.
102: addFunction(sumFieldsFunction);
103: }
104:
105: {
106:
107: // you can of course even implement it anonymously.
108: addFunction(new AbstractFunction<List<String>>("showparameter",
109: new Parameter<Collection>("collectionparam",
110: Collection.class), new Parameter<Map>(
111: "mapparam", Map.class), new Parameter<Integer>(
112: "integerparam", Integer.class),
113: new Parameter<Number>("numberparam", Number.class)) {
114: {
115: setDescription("With this function one can demonstrate how to create parameters of several types, and in what excactly that results");
116: }
117:
118: public List<String> getFunctionValue(Parameters parameters) {
119: List<String> result = new ArrayList<String>();
120: Parameter[] def = parameters.getDefinition();
121: for (int i = 0; i < def.length; i++) {
122: Object value = parameters.get(i);
123: if (value != null) {
124: result.add(def[i].toString() + " ->"
125: + value.getClass().getName() + " "
126: + value);
127: }
128: }
129: return result;
130: }
131: });
132: }
133:
134: {
135: // an example of a function which is both node-function and builder-function
136: // it also demonstrate that you may use bridge to implement a node-function.
137:
138: addFunction(new NodeFunction<Node>("predecessor",
139: Parameter.CLOUD // makes it possible to implement by bridge.
140: ) {
141: {
142: setDescription("Returns the node older then the current node, or null if this node is the oldest (if called on node), or the newest node of this type, or null of there are no nodes of this type (if called on builder)");
143: }
144:
145: protected Node getFunctionValue(Node node,
146: Parameters parameters) {
147: NodeManager nm = node.getNodeManager();
148: NodeQuery q = nm.createQuery();
149: StepField field = q.getStepField(nm.getField("number"));
150: q.setConstraint(q.createConstraint(field,
151: FieldCompareConstraint.LESS, Integer
152: .valueOf(node.getNumber())));
153: q.addSortOrder(field, SortOrder.ORDER_DESCENDING);
154: q.setMaxNumber(1);
155: NodeIterator i = nm.getList(q).nodeIterator();
156: return i.hasNext() ? i.nextNode() : null;
157: }
158:
159: public Node getFunctionValue(Parameters parameters) {
160: Cloud cloud = parameters.get(Parameter.CLOUD);
161: NodeManager nm = cloud
162: .getNodeManager(ExampleBuilder.this
163: .getTableName());
164: NodeQuery q = nm.createQuery();
165: StepField field = q.getStepField(nm.getField("number"));
166: q.addSortOrder(field, SortOrder.ORDER_DESCENDING);
167: q.setMaxNumber(1);
168: NodeIterator i = nm.getList(q).nodeIterator();
169: return i.hasNext() ? i.nextNode() : null;
170: }
171: });
172: }
173:
174: }
|