KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mmbase > cache > ReleaseStrategyTest


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

10 package org.mmbase.cache;
11
12 import java.util.HashMap JavaDoc;
13 import java.util.Map JavaDoc;
14
15 import org.mmbase.bridge.*;
16 import org.mmbase.bridge.util.Queries;
17 import org.mmbase.core.event.NodeEvent;
18 import org.mmbase.core.event.Event;
19 import org.mmbase.core.event.NodeEventHelper;
20 import org.mmbase.core.event.RelationEvent;
21 import org.mmbase.module.core.*;
22 import org.mmbase.storage.search.AggregatedField;
23 import org.mmbase.storage.search.Step;
24 import org.mmbase.storage.search.implementation.BasicFieldValueConstraint;
25 import org.mmbase.storage.search.implementation.BasicLegacyConstraint;
26 import org.mmbase.tests.BridgeTest;
27 import org.mmbase.util.logging.Logger;
28 import org.mmbase.util.logging.Logging;
29
30 /**
31  * Test class for {@link org.mmbase.cache.BetterStrategy}.
32  * TODO: the way the NodeEvent now works makes it core dependant. i can not do the tests
33  * without using the core. this does not mean it won't work without the core (rmmci) but i think it
34  * must be changed.
35  * @author Ernst Bunders
36  *
37  */

38 public class ReleaseStrategyTest extends BridgeTest {
39
40     static protected Cloud cloud = null;
41
42     static protected RelationManager posrelManager;
43     static protected NodeManager relDefManager;
44     static protected NodeManager typeRelManager;
45     static protected NodeManager insRelManager;
46     static protected NodeManager newsManager;
47     static protected NodeManager urlsManager;
48     static protected NodeManager peopelManager;
49     static protected NodeList createdNodes;
50
51     static protected ReleaseStrategy strategy;
52
53     protected Query twooStepQuery;
54     protected Query oneStepQuery;
55
56
57     private static final Logger log = Logging.getLoggerInstance(ReleaseStrategyTest.class);
58
59     protected final static String JavaDoc TEST_RELATION_ROLE = "test";
60     protected final static String JavaDoc NEWS_TITLE = "title";
61     protected final static String JavaDoc URLS_NAME = "name";
62
63     protected static final int POSREL_POS = 0;
64
65     static protected Node newsNode;
66
67     static protected Node urlsNode;
68
69     static protected Relation posrelNode;
70
71     public ReleaseStrategyTest(String JavaDoc name){
72         super(name);
73     }
74
75
76     /* (non-Javadoc)
77      * @see junit.framework.TestCase#setUp()
78      */

79     public void setUp() throws Exception JavaDoc {
80         if (cloud == null) {
81             startMMBase();
82             cloud = getCloud();
83
84             try {
85                 newsManager = cloud.getNodeManager("news");
86                 urlsManager = cloud.getNodeManager("urls");
87                 posrelManager = cloud.getRelationManager("posrel");
88                 relDefManager = cloud.getNodeManager("reldef");
89                 typeRelManager = cloud.getNodeManager("typerel");
90                 insRelManager = cloud.getNodeManager("insrel");
91                 peopelManager = cloud.getNodeManager("people");
92             } catch(NotFoundException e){
93                 throw new Exception JavaDoc("Test cases cannot be performed because " + e.getMessage() + " Please arrange this in your cloud before running this TestCase.");
94             }
95             strategy = new BetterStrategy();
96             createdNodes = cloud.createNodeList();
97
98
99             //create an alternative typerel: people > posrel > urls
100
Node typerel = typeRelManager.createNode();
101             typerel.setNodeValue("snumber", peopelManager);
102             typerel.setNodeValue("dnumber", urlsManager);
103             typerel.setNodeValue("rnumber", posrelManager);
104             typerel.commit();
105             createdNodes.add(typerel);
106
107             //create some basic nodes
108

109             newsNode = newsManager.createNode();
110             newsNode.setStringValue("title", NEWS_TITLE);
111             newsNode.commit();
112             createdNodes.add(newsNode);
113
114             urlsNode = urlsManager.createNode();
115             urlsNode.setStringValue("name", URLS_NAME);
116             urlsNode.commit();
117             createdNodes.add(urlsNode);
118
119             posrelNode = newsNode.createRelation(urlsNode, posrelManager);
120             posrelNode.setIntValue("pos", POSREL_POS);
121             posrelNode.commit();
122             createdNodes.add(posrelNode);
123
124         }
125     }
126
127     /**
128      * here go all the tests for checks that are done for every type of node event
129      */

130     public void testNodeEvent(){
131         //a node event that has a type that is not part of the query path should not flush the query
132

133         NodeEvent event = NodeEventHelper.createNodeEventInstance(newsNode, Event.TYPE_NEW, null);
134         Query q1 = Queries.createQuery(cloud, null, "people,posrel,urls", "urls.name", null, null, null, null, false);
135
136         assertFalse("a node event should not flush a query if it's type is not in the path",
137                     strategy.evaluate(event, q1, null).shouldRelease());
138     }
139
140
141
142
143
144     /**
145      * here go all the tests for checks that are done for every type of relation event
146      */

147     public void testRelationEvent(){
148
149         //type: posrel, sourceType: news, destinationType: urls
150
RelationEvent relEvent = NodeEventHelper.createRelationEventInstance(posrelNode, Event.TYPE_NEW, null);
151
152         //if the query has one step, a relaion event should not flush the query
153
Query q1 = Queries.createQuery(cloud, null, "urls", "urls.name", null, null, null, null, false);
154
155         assertFalse("relation event should not flush query with one step",
156                     strategy.evaluate(relEvent, q1, null).shouldRelease());
157
158         //if either source, destination or role does not match, a relation event should not flush the query
159
Query q2 = Queries.createQuery(cloud, null, "people,posrel,urls", "urls.name", null, null, null, null, false);
160         Query q3 = Queries.createQuery(cloud, null, "news,sorted,urls", "news.title", null, null, null, null, false);
161         Query q4 = Queries.createQuery(cloud, null, "news,posrel,attachments", "news.title", null, null, null, null, false);
162
163         assertFalse("relation event of new relation between nodes in multi step query (where source does not match) should not be flushed",
164                     strategy.evaluate(relEvent, q2, null).shouldRelease());
165         assertFalse("relation event of new relation between nodes in multi step query (where role does not match) should not be flushed",
166                     strategy.evaluate(relEvent, q3, null).shouldRelease());
167         assertFalse("relation event of new relation between nodes in multi step query (where destinantion does not match) should not be flushed",
168                     strategy.evaluate(relEvent, q4, null).shouldRelease());
169
170         //but when they do it should be flushed, allso if source and destination are the other way around
171

172         Query q4a = Queries.createQuery(cloud, null, "news,posrel,urls", "news.title", null, null, null, null, false);
173         Query q4b = Queries.createQuery(cloud, null, "urls,posrel,news", "news.title", null, null, null, null, false);
174
175         Query q4c = Queries.createQuery(cloud, null, "news,posrel,object", "news.title", null, null, null, null, false);
176         Query q4d = Queries.createQuery(cloud, null, "object,posrel,news", "news.title", null, null, null, null, false);
177
178         assertTrue("when path of query matches relation event, query should be flushed",
179                    strategy.evaluate(relEvent, q4a, null).shouldRelease());
180         assertTrue("when path of query matches relation event, query should be flushed, allso when source and relation are swapped",
181                    strategy.evaluate(relEvent, q4b, null).shouldRelease());
182         assertTrue("when path of query matches relation event, query should be flushed",
183                    strategy.evaluate(relEvent, q4c, null).shouldRelease());
184         assertTrue("when path of query matches relation event, query should be flushed, allso when source and relation are swapped",
185                    strategy.evaluate(relEvent, q4d, null).shouldRelease());
186
187
188         //but if the role is not specified the query should be flushed
189
Query q5 = Queries.createQuery(cloud, null, "news,urls", "urls.name", null, null, null, null, false);
190         assertTrue("relation event of new relation between nodes in multi step query (where role is not specified and source and destination match) should be flushed",
191                    strategy.evaluate(relEvent, q5, null).shouldRelease());
192         Query q51 = Queries.createQuery(cloud, null, "news,object", "object.number", null, null, null, null, false);
193         assertTrue("relation event of new relation between nodes in multi step query (where role is not specified and source and destination match) should be flushed",
194                    strategy.evaluate(relEvent, q51, null).shouldRelease());
195
196         //unless source or destination do not match
197
Query q6 = Queries.createQuery(cloud, null, "people,urls", "urls.name", null, null, null, null, false);
198         Query q7 = Queries.createQuery(cloud, null, "news,attachments", "news.title", null, null, null, null, false);
199
200         assertFalse("relation event of new relation between nodes in multi step query where is not specified (and source does not match) should not be flushed",
201                     strategy.evaluate(relEvent, q6, null).shouldRelease());
202         assertFalse("relation event of new relation between nodes in multi step query where is not specified (and destination does not match) should not be flushed",
203                     strategy.evaluate(relEvent, q7, null).shouldRelease());
204
205     }
206
207
208
209
210
211
212     public void testNewNode(){
213         log.debug("method: testMultiStepQueryNewNode()");
214         Query q1 = Queries.createQuery(cloud, null, "news,posrel,urls", "news.title,urls.name",null, null, null, null, false);
215         Query q2 = Queries.createQuery(cloud, null, "object,posrel,urls", "object.otype,urls.name",null, null, null, null, false);
216         Query q3 = Queries.createQuery(cloud, null, "news,posrel,object", "news.title,object.owner",null, null, null, null, false);
217         Query q4 = Queries.createQuery(cloud, null, "news,urls", "news.title,urls.name",null, null, null, null, false);
218         Query q5 = Queries.createQuery(cloud, null, "object,object2", "object.otype,object2.otype",null, null, null, null, false);
219
220         //a new node should not flush a multistep query frome the cache
221
NodeEvent event = NodeEventHelper.createNodeEventInstance(newsNode, Event.TYPE_NEW, null);
222         assertFalse("node event of new node on multi step query should not release the query", strategy.evaluate(event, q1, null).shouldRelease());
223         assertFalse("node event of new node on multi step query should not release the query", strategy.evaluate(event, q2, null).shouldRelease());
224         assertFalse("node event of new node on multi step query should not release the query", strategy.evaluate(event, q3, null).shouldRelease());
225         assertFalse("node event of new node on multi step query should not release the query", strategy.evaluate(event, q4, null).shouldRelease());
226         assertFalse("node event of new node on multi step query should not release the query", strategy.evaluate(event, q5, null).shouldRelease());
227
228     }
229
230
231     public void testNewRelation(){
232         log.debug("method: testMultiStepQueryNewRelation()");
233         Query q1 = Queries.createQuery(cloud, null, "news,posrel,urls", "news.title,urls.name",null, null, null, null, false);
234         Query q2 = Queries.createQuery(cloud, null, "object,posrel,urls", "object.otype,urls.name",null, null, null, null, false);
235         Query q3 = Queries.createQuery(cloud, null, "news,posrel,object", "news.title,object.owner",null, null, null, null, false);
236         Query q4 = Queries.createQuery(cloud, null, "news,urls", "news.title,urls.name",null, null, null, null, false);
237         Query q5 = Queries.createQuery(cloud, null, "object,object2", "object.otype,object2.otype",null, null, null, null, false);
238
239         //a new relation node should not flush cache the cache
240
NodeEvent event = NodeEventHelper.createNodeEventInstance(posrelNode, Event.TYPE_NEW, null);
241         assertFalse("node event of new relation node on multi step query should not release the query", strategy.evaluate(event, q1, null).shouldRelease());
242         assertFalse("node event of new relation node on multi step query should not release the query", strategy.evaluate(event, q2, null).shouldRelease());
243         assertFalse("node event of new relation node on multi step query should not release the query", strategy.evaluate(event, q3, null).shouldRelease());
244         assertFalse("node event of new relation node on multi step query should not release the query", strategy.evaluate(event, q4, null).shouldRelease());
245         assertFalse("node event of new relation node on multi step query should not release the query", strategy.evaluate(event, q5, null).shouldRelease());
246
247         //but the subsequent relation event should
248
RelationEvent relEvent = NodeEventHelper.createRelationEventInstance(posrelNode, Event.TYPE_NEW, null);
249         assertTrue("relation event of new relation between nodes in multi step query should flush the cache", strategy.evaluate(relEvent, q1, null).shouldRelease());
250         assertTrue("relation event of new relation between nodes in multi step query should flush the cache", strategy.evaluate(relEvent, q2, null).shouldRelease());
251         assertTrue("relation event of new relation between nodes in multi step query should flush the cache", strategy.evaluate(relEvent, q3, null).shouldRelease());
252         assertTrue("relation event of new relation between nodes in multi step query should flush the cache", strategy.evaluate(relEvent, q4, null).shouldRelease());
253         assertTrue("relation event of new relation between nodes in multi step query should flush the cache", strategy.evaluate(relEvent, q5, null).shouldRelease());
254
255     }
256
257
258
259
260     public void testChangedNode(){
261         log.debug("method: testMultiStepQueryChangedNode()");
262
263         //if none of the fields that have changed are part of the select or the constraint part of the query it should not be flushed
264

265         //MMObjectNode testNode = MMBase.getMMBase().getBuilder("object").getNode(newsNode.getNumber());
266
//testNode.setValue("title", "another title");
267

268         NodeEvent event = new NodeEvent(null, "news", 0, getMap("title", "oldTitle"), getMap("title", "newtitle"), Event.TYPE_CHANGE);
269         NodeEvent event2 = new NodeEvent(null, "news", 0, getMap("owner", "oldOwner"), getMap("owner", "newowner"), Event.TYPE_CHANGE);
270         {
271             Query q1 = Queries.createQuery(cloud, null, "news,posrel,urls" ,"news.subtitle", "news.number < 1000", null, null, null, false);
272             Query q2 = Queries.createQuery(cloud, null, "news,posrel,urls" ,"news.subtitle", "news.title = 'hallo'", null, null, null, false);
273             Query q3 = Queries.createQuery(cloud, null, "news,posrel,urls" ,"news.title", "news.number < 1000", null, null, null, false);
274
275             assertFalse("changed field is not used by query: it should not be flushed",
276                         strategy.evaluate(event, q1, null).shouldRelease());
277             assertTrue("changed field is in constraints section of query: it should be flushed",
278                        strategy.evaluate(event, q2, null).shouldRelease());
279             assertTrue("changed field is in select section of query: it should be flushed",
280                        strategy.evaluate(event, q3, null).shouldRelease());
281         }
282         {// same thing, but now with inheritance
283
Query q1 = Queries.createQuery(cloud, null, "object,posrel,urls" ,"object.otype", "object.number < 1000", null, null, null, false);
284             Query q2 = Queries.createQuery(cloud, null, "object,posrel,urls" ,"object.otype", "object.owner = 'hallo'", null, null, null, false);
285             Query q3 = Queries.createQuery(cloud, null, "object,posrel,urls" ,"object.owner", "news.number < 1000", null, null, null, false);
286
287             assertFalse("changed field is not used by query: it should not be flushed",
288                         strategy.evaluate(event2, q1, null).shouldRelease());
289             assertTrue("changed field is in constraints section of query: it should be flushed",
290                        strategy.evaluate(event2, q2, null).shouldRelease());
291             assertTrue("changed field is in select section of query: it should be flushed",
292                        strategy.evaluate(event2, q3, null).shouldRelease());
293         }
294         //also test composite constraints
295
Query q4 = Queries.createQuery(cloud, null, "news,posrel,urls" ,"news.subtitle", "news.number < 1000 AND urls.name = 'hi'", null, null, null, false);
296         Query q5 = Queries.createQuery(cloud, null, "news,posrel,urls" ,"news.subtitle", "news.title='something' AND urls.name = 'hi'", null, null, null, false);
297
298         assertFalse("changed field is not used by (composite) constraint: it should not be flushed",
299                     strategy.evaluate(event, q4, null).shouldRelease());
300         assertTrue("changed field is used by (composite) constraint: it should be flushed",
301                    strategy.evaluate(event, q5, null).shouldRelease());
302
303         //also test legacy constraints
304
Query q6 = Queries.createQuery(cloud, null, "news,posrel,urls" ,"news.subtitle", null, null, null, null, false);
305         q6.setConstraint(new BasicLegacyConstraint("news.number < 1000 AND urls.name = 'hi'"));
306
307         assertFalse("changed field is not used by (legacy) constraint: it should not be flushed",
308                     strategy.evaluate(event, q6, null).shouldRelease());
309
310         q6.setConstraint(new BasicLegacyConstraint("news.title='something' AND urls.name = 'hi'"));
311
312         assertTrue("changed field is used by (legacy) constraint: it should be flushed",
313                    strategy.evaluate(event, q6, null).shouldRelease());
314
315         //*************************
316
//if the step(s) of the changed field(s) are (all) aggregate fields of type count, and this field is not used
317
//in the constraint as well, the query shouldn't be flushed.
318

319         Query q7;
320         Step newsStep;
321         q7 = cloud.createAggregatedQuery();
322         newsStep = q7.addStep(newsManager);
323         AggregatedField titleField = q7.addAggregatedField(newsStep, newsManager.getField("title"), 2);
324
325         assertFalse("aggregate queries (type count) where the changed field(s) match the step(s) should not be flushed",
326                     strategy.evaluate(event, q7, null).shouldRelease());
327
328         //but whit this field in the constraint it should be flushed
329
q7.setConstraint(new BasicFieldValueConstraint(titleField, "disco"));
330         assertTrue("aggregate queries (type count) where the changed field(s) match the step(s) but there are constraints on the step(s) should be flushed",
331                    strategy.evaluate(event, q7, null).shouldRelease());
332
333         //but other types of aggregation should flush (they deal with the contents of the field
334
int[] aggregations = new int[] {
335             AggregatedField.AGGREGATION_TYPE_COUNT_DISTINCT,
336             AggregatedField.AGGREGATION_TYPE_GROUP_BY,
337             AggregatedField.AGGREGATION_TYPE_MAX,
338             AggregatedField.AGGREGATION_TYPE_MIN};
339         for(int i = 0; i < aggregations.length; i++){
340             q7 = cloud.createAggregatedQuery();
341             newsStep = q7.addStep(newsManager);
342             q7.addAggregatedField(newsStep, newsManager.getField("title"),aggregations[i]);
343
344             assertTrue ("aggregate queries (type " + AggregatedField.AGGREGATION_TYPE_DESCRIPTIONS[i] + ") where the changed field(s) match the step(s) should be flushed",
345                         strategy.evaluate(event, q7, null).shouldRelease());
346         }
347     }
348
349
350     public void testChangedRelation(){
351         //if a none of the fields that have changed are part of the select or the constraint part of the query it should not be flushed
352

353         //stupid hack to create a changed field for the event. for some reason settin the field on an Node does not alter the
354
//changedField collection on MMObjectNode
355
MMObjectNode pos = MMBase.getMMBase().getBuilder( posrelNode.getNodeManager().getName() ).getNode(posrelNode.getNumber());
356         pos.setValue("pos", new Integer JavaDoc(100));
357         //now create a relation event
358
RelationEvent relEvent = NodeEventHelper.createRelationEventInstance(posrelNode, Event.TYPE_CHANGE, null);
359
360         Query q1 = Queries.createQuery(cloud, null, "news,posrel,urls" ,"news.subtitle", "news.number < 10 ", null, null, null, false);
361         Query q2 = Queries.createQuery(cloud, null, "news,posrel,urls" ,"news.subtitle", "posrel.pos < 10 ", null, null, null, false);
362         Query q3 = Queries.createQuery(cloud, null, "news,posrel,urls" ,"news.subtitle,posrel.pos", "news.number < 10 ", null, null, null, false);
363
364         assertFalse("changed relation field is not used by query: it should not be flushed",
365                     strategy.evaluate(relEvent, q1, null).shouldRelease());
366         assertTrue("changed relation field is in constraints section of query: it should be flushed",
367                    strategy.evaluate(relEvent, q2, null).shouldRelease());
368         assertTrue("changed relation field is in select section of query: it should be flushed",
369                    strategy.evaluate(relEvent, q3, null).shouldRelease());
370
371         //also test composite constraints
372
Query q4 = Queries.createQuery(cloud, null, "news,posrel,urls" ,"news.subtitle", "news.number < 1000 AND urls.name = 'hi'", null, null, null, false);
373         Query q5 = Queries.createQuery(cloud, null, "news,posrel,urls" ,"news.subtitle", "posrel.pos < 1 AND urls.name = 'hi'", null, null, null, false);
374
375         assertFalse("changed relation field is not used by (composite) constraint: it should not be flushed",
376                     strategy.evaluate(relEvent, q4, null).shouldRelease());
377         assertTrue("changed relation field is used by (composite) constraint: it should be flushed",
378                    strategy.evaluate(relEvent, q5, null).shouldRelease());
379
380         //also test legacy constraints
381
Query q6 = Queries.createQuery(cloud, null, "news,posrel,urls" ,"news.subtitle", null, null, null, null, false);
382         q6.setConstraint(new BasicLegacyConstraint("news.number < 1000 AND urls.name = 'hi'"));
383
384         assertFalse("changed relation field is not used by (legacy) constraint: it should not be flushed",
385                     strategy.evaluate(relEvent, q6, null).shouldRelease());
386
387         q6.setConstraint(new BasicLegacyConstraint("news.title='something' AND posrel.pos < 1"));
388
389         assertTrue("changed relation field is used by (legacy) constraint: it should be flushed",
390                    strategy.evaluate(relEvent, q6, null).shouldRelease());
391
392     }
393
394     public void testGetConstraintsforField(){
395         Query q1 = Queries.createQuery(cloud, null, "news,posrel,urls", "news.number", "news.title = 'hallo'", null, null, null, false);
396         Query q2 = Queries.createQuery(cloud, null, "news,posrel,urls", "news.number", "news.subtitle = 'hallo'", null, null, null, false);
397         Query q3 = Queries.createQuery(cloud, null, "news,posrel,urls", "news.number", "news.title = 'hallo' AND news.subtitle='hi'", null, null, null, false);
398         Query q4 = Queries.createQuery(cloud, null, "news,posrel,urls", "news.number", null, null, null, null, false);
399
400         MMBase mmb = MMBase.getMMBase();
401         MMObjectBuilder news = mmb.getBuilder("news");
402         assertTrue("title field of news builder is in constraints",
403                    ReleaseStrategy.getConstraintsForField("title", news, null, q1).size() == 1);
404         assertTrue("title field of news builder is not in constraints",
405                    ReleaseStrategy.getConstraintsForField("title", news, null, q2).size() == 0);
406         assertTrue("title field of news builder is one of the constraints.",
407                    ReleaseStrategy.getConstraintsForField("title", news, null, q3).size() == 1);
408         assertTrue("there are no constraints.",
409                    ReleaseStrategy.getConstraintsForField("title", news, null, q4).size() == 0);
410     }
411
412
413     protected Node createRelDefNode(String JavaDoc role, int dir) {
414         // create a new relation-definition
415
Node reldef = relDefManager.createNode();
416         reldef.setValue("sname", role);
417         reldef.setValue("dname", "d" + role );
418         reldef.setValue("sguiname", role);
419         reldef.setValue("dguiname", "d" + role);
420         reldef.setIntValue("dir", dir);
421         reldef.setNodeValue("builder", insRelManager);
422         reldef.commit();
423         createdNodes.add(reldef);
424         return reldef;
425     }
426
427     public void testSpeed() {
428         NodeEvent event = new NodeEvent(null, "news", 0, getMap("title", "oldTitle"), getMap("title", "newtitle"), Event.TYPE_CHANGE);
429
430         Query q1 = Queries.createQuery(cloud, null, "news,posrel,urls" ,"news.subtitle", "news.number < 1000", null, null, null, false);
431         Query q2 = Queries.createQuery(cloud, null, "news,posrel,urls" ,"news.subtitle", "news.title = 'hallo'", null, null, null, false);
432         Query q3 = Queries.createQuery(cloud, null, "news,posrel,urls" ,"news.title", "news.number < 1000", null, null, null, false);
433
434
435         ChainedReleaseStrategy chain = new ChainedReleaseStrategy(); // in reality always a chain is used;
436
chain.addReleaseStrategy(strategy);
437         System.out.println("Simple performance.");
438         long startTime = System.currentTimeMillis();
439         for (int i = 0; i < 50000; i++) {
440             chain.evaluate(event, q1, null).shouldRelease();
441             chain.evaluate(event, q2, null).shouldRelease();
442             chain.evaluate(event, q3, null).shouldRelease();
443         }
444         System.out.println("Simple performance test result: " + (System.currentTimeMillis() - startTime) + " ms");
445
446
447     }
448
449     private Map JavaDoc getMap(Object JavaDoc key, Object JavaDoc value){
450         Map JavaDoc m = new HashMap JavaDoc();
451         m.put(key, value);
452         return m;
453     }
454
455 }
456
Popular Tags