KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mmbase > bridge > util > GrowingTreeList


1 /*
2
3 This software is OSI Certified Open Source Software.
4 OSI Certified is a certification mark of the Open Source Initiative.
5
6 The license (Mozilla version 1.0) can be read at the MMBase site.
7 See http://www.MMBase.org/license
8
9 */

10
11 package org.mmbase.bridge.util;
12
13 import java.util.Iterator JavaDoc;
14
15 import org.mmbase.bridge.*;
16 import org.mmbase.storage.search.*;
17 import org.mmbase.util.logging.*;
18
19 /**
20  *
21  * This version of {@link TreeList} is automaticly growing with the same 'branch' every time when that is possible. For that
22  * it needs a kind of template query for every branch, which is defined by the constructor.
23  *
24  *
25  * @author Michiel Meeuwissen
26  * @version $Id: GrowingTreeList.java,v 1.17 2006/07/25 18:56:24 michiel Exp $
27  * @since MMBase-1.7
28  */

29
30 public class GrowingTreeList extends TreeList {
31     private static final Logger log = Logging.getLoggerInstance(GrowingTreeList.class);
32     protected Constraint cleanConstraint;
33     protected NodeQuery pathElementTemplate;
34     protected Constraint cleanLeafConstraint = null;
35     protected NodeQuery leafElementTemplate = null;
36     protected int maxNumberOfSteps;
37
38     /**
39      * @param q The 'base' query defining the minimal depth of the tree elements. The trunk of the tree.
40      * @param maxDepth You must supply a maximal depth of the nodes, because MMBase is basicly a network rather then a tree, so
41      * tree representations could be infinitely deep.
42      * @param nodeManager Destination Nodemanager in the tree
43      * @param role Role of the relations in the tree
44      * @param searchDir Direction of the relations in the tree
45      * @since MMBase-1.7.1
46      */

47     public GrowingTreeList(NodeQuery q, int maxDepth, NodeManager nodeManager, String JavaDoc role, String JavaDoc searchDir) {
48         super(q);
49         if (log.isDebugEnabled()) {
50             log.debug("Making growering tree-list with " + q.toSql());
51         }
52         if (nodeManager == null) nodeManager = cloud.getNodeManager("object");
53         pathElementTemplate = cloud.createNodeQuery();
54         //shiftElementTemplate = cloud.createNodeQuery();
55
Step step = pathElementTemplate.addStep(cloud.getNodeManager("object"));
56         pathElementTemplate.setAlias(step, "object0");
57         pathElementTemplate.setNodeStep(pathElementTemplate.addRelationStep(nodeManager, role, searchDir).getNext());
58
59         setMaxDepth(maxDepth);
60     }
61
62     /**
63      * This may be used in combination with
64      * <code>Queries.addPath(tree.getTemplate(), (String) path.getValue(this), (String) searchDirs.getValue(this));</code>
65      * So you add a template constisting of a bunch of elements.
66      */

67     public GrowingTreeList(NodeQuery q, int maxDepth) {
68         super(q);
69         pathElementTemplate = cloud.createNodeQuery();
70         Step step = pathElementTemplate.addStep(cloud.getNodeManager("object"));
71         pathElementTemplate.setAlias(step, "object0");
72
73         setMaxDepth(maxDepth);
74     }
75
76     public GrowingTreeList(TreeList tl, int maxDepth) {
77         super(tl);
78         pathElementTemplate = cloud.createNodeQuery();
79         Step step = pathElementTemplate.addStep(cloud.getNodeManager("object"));
80         pathElementTemplate.setAlias(step, "object0");
81
82         setMaxDepth(maxDepth);
83     }
84
85     /**
86      * As long as the tree is not 'started' yet, max depth can still be changed.
87      * @param maxDepth max number of Steps
88      * @since MMBase-1.7.1
89      */

90
91     public void setMaxDepth(int maxDepth) {
92         maxNumberOfSteps = 2 * maxDepth - 1; // dont consider relation steps.
93

94         if (maxNumberOfSteps < numberOfSteps) {
95             throw new IllegalArgumentException JavaDoc("Query is already deeper than maxdepth");
96         }
97     }
98
99     /**
100      * Returns the Query which is used as a template for the leaves to 'grow' the query. You can change it, add
101      * sort-orders and add constraints before the tree is 'started'. All but the first step of this
102      * query are added. This query itself is never executed, though marked used, to avoid changes on
103      * it after the list has started.
104      *
105      * @return Query which is used as a template
106      * @since MMBase-1.7.1
107      */

108
109     public NodeQuery getTemplate() {
110         return pathElementTemplate;
111     }
112
113     /**
114      * The leave template is the 'last' template. This is the same as getTemplate, only, the
115      * constraints set on this, are only used if the template is used 'on the end'.
116      *
117      * It boils down to the fact that constraints set on the query don't change the tree itself, but
118      * only constraint the 'leaves', so it makes for a kind of tree-search.
119      * @since MMBase-1.8
120      */

121     public NodeQuery getLeafTemplate() {
122         if (leafElementTemplate == null) {
123             leafElementTemplate = (NodeQuery) pathElementTemplate.clone();
124         }
125         return leafElementTemplate;
126     }
127
128
129     public int size() {
130         while (! foundEnd) {
131             addPathElement();
132         }
133         return super.size();
134     }
135
136     protected NodeList getList(int queryNumber) {
137         while (queryNumber >= branches.size() && (!foundEnd)) {
138             addPathElement();
139         }
140         return super.getList(queryNumber);
141     }
142     protected NodeList getLeafList(int queryNumber) {
143         while (queryNumber >= branches.size() && (!foundEnd)) {
144             addPathElement();
145         }
146         return super.getLeafList(queryNumber);
147     }
148
149
150     /**
151      * Grows the branches of the tree, with the leave.
152      *
153      */

154     protected void addPathElement() {
155         if (numberOfSteps + 2 > maxNumberOfSteps) {
156             foundEnd = true;
157         } else {
158             if (! pathElementTemplate.isUsed()) {
159                 pathElementTemplate.markUsed();
160                 cleanConstraint = pathElementTemplate.getCleanConstraint();
161             }
162             if (leafElementTemplate != null && ! leafElementTemplate.isUsed()) {
163                 leafElementTemplate.markUsed();
164                 cleanLeafConstraint = leafElementTemplate.getCleanConstraint();
165             }
166
167             Iterator JavaDoc steps = pathElementTemplate.getSteps().iterator();;
168             steps.next(); // ignore first step
169
if (! steps.hasNext()) {
170                 foundEnd = true;
171                 return;
172             }
173             while (steps.hasNext()) {
174                 RelationStep relationStepTemplate = (RelationStep) steps.next();
175                 Step stepTemplate = (Step) steps.next();
176                 String JavaDoc role;
177                 { // it's a pity but role cannot be requested directly from RelationStep
178
// some hackery
179
Integer JavaDoc reldef = relationStepTemplate.getRole();
180                     if (reldef == null) {
181                         role = null;
182                     } else {
183                         role = cloud.getNode(reldef.intValue()).getStringValue("sname");
184                     }
185                 }
186
187                 RelationStep newStep = grow(cloud.getNodeManager(stepTemplate.getTableName()),
188                                             role,
189                                             RelationStep.DIRECTIONALITY_DESCRIPTIONS[relationStepTemplate.getDirectionality()]);
190                 if (newStep == null) {
191                     foundEnd = true;
192                     break;
193                 }
194                 // Step doesn't have a .getQuery() method, so we'll have to fall back to this:
195
Branch branch = (Branch) branches.get(branches.size() - 1);
196                 Query newQuery = branch.getQuery();
197
198                 // add sortorder to the query
199
Step nextStep = newStep.getNext();
200
201                 if (cleanConstraint != null) {
202                     Constraint newStepConstraint = Queries.copyConstraint(cleanConstraint, stepTemplate, newQuery, nextStep);
203                     Constraint newRelationStepConstraint = Queries.copyConstraint(cleanConstraint, relationStepTemplate, newQuery, newStep);
204                     Queries.addConstraint(newQuery, newStepConstraint);
205                     Queries.addConstraint(newQuery, newRelationStepConstraint);
206                 }
207
208
209                 Queries.copySortOrders(pathElementTemplate.getSortOrders(), stepTemplate, newQuery, nextStep);
210                 Queries.copySortOrders(pathElementTemplate.getSortOrders(), relationStepTemplate, newQuery, newStep);
211
212                 if (cleanLeafConstraint != null) {
213                     Constraint newLeafStepConstraint = Queries.copyConstraint(cleanLeafConstraint, stepTemplate, newQuery, nextStep);
214                     Constraint newLeafRelationStepConstraint = Queries.copyConstraint(cleanLeafConstraint, relationStepTemplate, newQuery, newStep);
215                     if (newLeafStepConstraint != null && newLeafRelationStepConstraint != null) {
216                         CompositeConstraint comp = newQuery.createConstraint(newLeafStepConstraint, CompositeConstraint.LOGICAL_AND, newLeafRelationStepConstraint);
217                         setLeafConstraint(comp);
218                     } else if (newLeafStepConstraint != null) {
219                         setLeafConstraint(newLeafStepConstraint);
220                     } else if (newLeafRelationStepConstraint != null) {
221                         setLeafConstraint(newLeafRelationStepConstraint);
222                     } else {
223                         // both null, ignore
224
}
225                 }
226
227
228                 if (numberOfSteps + 2 > maxNumberOfSteps) {
229                     foundEnd = true;
230                     break;
231                 }
232             }
233         }
234     }
235
236
237     public static void main(String JavaDoc[] args) {
238         Cloud cloud = ContextProvider.getDefaultCloudContext().getCloud("mmbase");
239         //NodeQuery q = getQuery(args);
240
NodeQuery q = Queries.createNodeQuery(cloud.getNode(args[0]));
241
242         NodeManager object = cloud.getNodeManager("segments");
243
244         GrowingTreeList tree = new GrowingTreeList(q, 40, object, "index", "destination");
245
246         String JavaDoc text = "Exodus 20, vers 7";
247         NodeQuery temp = tree.getTemplate();
248         Queries.addSortOrders(temp, "index.pos", "up");
249         NodeQuery template = tree.getLeafTemplate();
250         Constraint cons1 = Queries.createConstraint(template, "title", FieldCompareConstraint.LIKE, "%" + text + "%");
251         Constraint cons2 = Queries.createConstraint(template, "body", FieldCompareConstraint.LIKE, "%" + text + "%");
252         Constraint compConstraint = template.createConstraint(cons1, CompositeConstraint.LOGICAL_OR, cons2);
253         template.setConstraint(compConstraint);
254
255         //System.out.println("size " + tree.size());
256
System.out.println("template " + tree.getTemplate());
257         System.out.println("leaf template " + tree.getLeafTemplate());
258
259         int k = 0;
260         TreeIterator i = tree.treeIterator();
261         while (i.hasNext()) {
262             Node n = i.nextNode();
263             k++;
264             System.out.println(k + " " + i.currentDepth() + " " + n.toString());
265         }
266     }
267 }
268
Popular Tags