aboutsummaryrefslogtreecommitdiff
path: root/contexts/data/lib/closure-library/closure/goog/structs
diff options
context:
space:
mode:
authorGravatar Rogan Creswick <creswick@galois.com>2012-03-30 17:07:02 -0700
committerGravatar Rogan Creswick <creswick@galois.com>2012-03-30 17:07:02 -0700
commitf6ab6622aab00fe7c2f4c3dc41f786ebbe0f0d73 (patch)
tree870111038542cd27153e1396ebdc063573249689 /contexts/data/lib/closure-library/closure/goog/structs
initial revision
Diffstat (limited to 'contexts/data/lib/closure-library/closure/goog/structs')
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/all-wcprops227
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/entries1286
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/avltree.js.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/avltree_test.html.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/circularbuffer.js.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/circularbuffer_test.html.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/collection.js.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/collection_test.html.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/heap.js.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/heap_test.html.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/inversionmap.js.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/inversionmap_test.html.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/linkedmap.js.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/linkedmap_test.html.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/map.js.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/map_test.html.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/node.js.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/pool.js.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/pool_test.html.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/prioritypool.js.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/prioritypool_test.html.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/priorityqueue.js.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/priorityqueue_test.html.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/quadtree.js.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/quadtree_test.html.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/queue.js.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/queue_test.html.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/set.js.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/set_perf.html.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/set_test.html.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/simplepool.js.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/stringset.js.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/stringset_test.html.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/structs.js.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/structs_test.html.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/treenode.js.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/treenode_test.html.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/trie.js.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/trie_test.html.svn-base5
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/avltree.js.svn-base772
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/avltree_test.html.svn-base251
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/circularbuffer.js.svn-base219
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/circularbuffer_test.html.svn-base105
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/collection.js.svn-base54
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/collection_test.html.svn-base57
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/heap.js.svn-base333
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/heap_test.html.svn-base220
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/inversionmap.js.svn-base159
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/inversionmap_test.html.svn-base157
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/linkedmap.js.svn-base472
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/linkedmap_test.html.svn-base300
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/map.js.svn-base448
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/map_test.html.svn-base430
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/node.js.svn-base74
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/pool.js.svn-base381
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/pool_test.html.svn-base291
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/prioritypool.js.svn-base179
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/prioritypool_test.html.svn-base562
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/priorityqueue.js.svn-base64
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/priorityqueue_test.html.svn-base179
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/quadtree.js.svn-base571
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/quadtree_test.html.svn-base179
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/queue.js.svn-base157
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/queue_test.html.svn-base140
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/set.js.svn-base255
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/set_perf.html.svn-base237
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/set_test.html.svn-base551
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/simplepool.js.svn-base205
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/stringset.js.svn-base404
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/stringset_test.html.svn-base251
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/structs.js.svn-base342
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/structs_test.html.svn-base1050
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/treenode.js.svn-base427
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/treenode_test.html.svn-base370
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/trie.js.svn-base368
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/trie_test.html.svn-base378
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/avltree.js772
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/avltree_test.html251
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/circularbuffer.js219
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/circularbuffer_test.html105
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/collection.js54
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/collection_test.html57
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/heap.js333
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/heap_test.html220
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/inversionmap.js159
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/inversionmap_test.html157
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/linkedmap.js472
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/linkedmap_test.html300
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/map.js448
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/map_test.html430
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/node.js74
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/pool.js381
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/pool_test.html291
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/prioritypool.js179
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/prioritypool_test.html562
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/priorityqueue.js64
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/priorityqueue_test.html179
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/quadtree.js571
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/quadtree_test.html179
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/queue.js157
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/queue_test.html140
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/set.js255
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/set_perf.html237
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/set_test.html551
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/simplepool.js205
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/stringset.js404
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/stringset_test.html251
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/structs.js342
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/structs_test.html1050
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/treenode.js427
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/treenode_test.html370
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/trie.js368
-rw-r--r--contexts/data/lib/closure-library/closure/goog/structs/trie_test.html378
113 files changed, 24882 insertions, 0 deletions
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/all-wcprops b/contexts/data/lib/closure-library/closure/goog/structs/.svn/all-wcprops
new file mode 100644
index 0000000..b2c333f
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/all-wcprops
@@ -0,0 +1,227 @@
+K 25
+svn:wc:ra_dav:version-url
+V 45
+/svn/!svn/ver/1472/trunk/closure/goog/structs
+END
+linkedmap.js
+K 25
+svn:wc:ra_dav:version-url
+V 57
+/svn/!svn/ver/850/trunk/closure/goog/structs/linkedmap.js
+END
+map_test.html
+K 25
+svn:wc:ra_dav:version-url
+V 59
+/svn/!svn/ver/1464/trunk/closure/goog/structs/map_test.html
+END
+treenode.js
+K 25
+svn:wc:ra_dav:version-url
+V 57
+/svn/!svn/ver/1273/trunk/closure/goog/structs/treenode.js
+END
+structs.js
+K 25
+svn:wc:ra_dav:version-url
+V 56
+/svn/!svn/ver/1472/trunk/closure/goog/structs/structs.js
+END
+prioritypool.js
+K 25
+svn:wc:ra_dav:version-url
+V 61
+/svn/!svn/ver/1302/trunk/closure/goog/structs/prioritypool.js
+END
+queue_test.html
+K 25
+svn:wc:ra_dav:version-url
+V 60
+/svn/!svn/ver/850/trunk/closure/goog/structs/queue_test.html
+END
+heap.js
+K 25
+svn:wc:ra_dav:version-url
+V 53
+/svn/!svn/ver/1089/trunk/closure/goog/structs/heap.js
+END
+set_test.html
+K 25
+svn:wc:ra_dav:version-url
+V 58
+/svn/!svn/ver/850/trunk/closure/goog/structs/set_test.html
+END
+queue.js
+K 25
+svn:wc:ra_dav:version-url
+V 53
+/svn/!svn/ver/850/trunk/closure/goog/structs/queue.js
+END
+collection.js
+K 25
+svn:wc:ra_dav:version-url
+V 58
+/svn/!svn/ver/894/trunk/closure/goog/structs/collection.js
+END
+treenode_test.html
+K 25
+svn:wc:ra_dav:version-url
+V 64
+/svn/!svn/ver/1273/trunk/closure/goog/structs/treenode_test.html
+END
+structs_test.html
+K 25
+svn:wc:ra_dav:version-url
+V 62
+/svn/!svn/ver/850/trunk/closure/goog/structs/structs_test.html
+END
+inversionmap_test.html
+K 25
+svn:wc:ra_dav:version-url
+V 67
+/svn/!svn/ver/850/trunk/closure/goog/structs/inversionmap_test.html
+END
+quadtree_test.html
+K 25
+svn:wc:ra_dav:version-url
+V 63
+/svn/!svn/ver/850/trunk/closure/goog/structs/quadtree_test.html
+END
+prioritypool_test.html
+K 25
+svn:wc:ra_dav:version-url
+V 67
+/svn/!svn/ver/850/trunk/closure/goog/structs/prioritypool_test.html
+END
+trie.js
+K 25
+svn:wc:ra_dav:version-url
+V 52
+/svn/!svn/ver/850/trunk/closure/goog/structs/trie.js
+END
+heap_test.html
+K 25
+svn:wc:ra_dav:version-url
+V 59
+/svn/!svn/ver/850/trunk/closure/goog/structs/heap_test.html
+END
+stringset_test.html
+K 25
+svn:wc:ra_dav:version-url
+V 64
+/svn/!svn/ver/850/trunk/closure/goog/structs/stringset_test.html
+END
+pool.js
+K 25
+svn:wc:ra_dav:version-url
+V 53
+/svn/!svn/ver/1024/trunk/closure/goog/structs/pool.js
+END
+quadtree.js
+K 25
+svn:wc:ra_dav:version-url
+V 56
+/svn/!svn/ver/850/trunk/closure/goog/structs/quadtree.js
+END
+inversionmap.js
+K 25
+svn:wc:ra_dav:version-url
+V 60
+/svn/!svn/ver/850/trunk/closure/goog/structs/inversionmap.js
+END
+priorityqueue_test.html
+K 25
+svn:wc:ra_dav:version-url
+V 68
+/svn/!svn/ver/850/trunk/closure/goog/structs/priorityqueue_test.html
+END
+map.js
+K 25
+svn:wc:ra_dav:version-url
+V 52
+/svn/!svn/ver/1472/trunk/closure/goog/structs/map.js
+END
+collection_test.html
+K 25
+svn:wc:ra_dav:version-url
+V 65
+/svn/!svn/ver/894/trunk/closure/goog/structs/collection_test.html
+END
+stringset.js
+K 25
+svn:wc:ra_dav:version-url
+V 57
+/svn/!svn/ver/850/trunk/closure/goog/structs/stringset.js
+END
+simplepool.js
+K 25
+svn:wc:ra_dav:version-url
+V 59
+/svn/!svn/ver/1024/trunk/closure/goog/structs/simplepool.js
+END
+node.js
+K 25
+svn:wc:ra_dav:version-url
+V 52
+/svn/!svn/ver/850/trunk/closure/goog/structs/node.js
+END
+circularbuffer_test.html
+K 25
+svn:wc:ra_dav:version-url
+V 69
+/svn/!svn/ver/850/trunk/closure/goog/structs/circularbuffer_test.html
+END
+priorityqueue.js
+K 25
+svn:wc:ra_dav:version-url
+V 61
+/svn/!svn/ver/850/trunk/closure/goog/structs/priorityqueue.js
+END
+avltree_test.html
+K 25
+svn:wc:ra_dav:version-url
+V 62
+/svn/!svn/ver/893/trunk/closure/goog/structs/avltree_test.html
+END
+trie_test.html
+K 25
+svn:wc:ra_dav:version-url
+V 59
+/svn/!svn/ver/850/trunk/closure/goog/structs/trie_test.html
+END
+set.js
+K 25
+svn:wc:ra_dav:version-url
+V 52
+/svn/!svn/ver/1472/trunk/closure/goog/structs/set.js
+END
+linkedmap_test.html
+K 25
+svn:wc:ra_dav:version-url
+V 64
+/svn/!svn/ver/850/trunk/closure/goog/structs/linkedmap_test.html
+END
+circularbuffer.js
+K 25
+svn:wc:ra_dav:version-url
+V 62
+/svn/!svn/ver/850/trunk/closure/goog/structs/circularbuffer.js
+END
+set_perf.html
+K 25
+svn:wc:ra_dav:version-url
+V 58
+/svn/!svn/ver/850/trunk/closure/goog/structs/set_perf.html
+END
+pool_test.html
+K 25
+svn:wc:ra_dav:version-url
+V 59
+/svn/!svn/ver/850/trunk/closure/goog/structs/pool_test.html
+END
+avltree.js
+K 25
+svn:wc:ra_dav:version-url
+V 55
+/svn/!svn/ver/894/trunk/closure/goog/structs/avltree.js
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/entries b/contexts/data/lib/closure-library/closure/goog/structs/.svn/entries
new file mode 100644
index 0000000..9c736c5
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/entries
@@ -0,0 +1,1286 @@
+10
+
+dir
+1494
+http://closure-library.googlecode.com/svn/trunk/closure/goog/structs
+http://closure-library.googlecode.com/svn
+
+
+
+2011-12-13T22:20:28.000000Z
+1472
+ccalabro@google.com
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+0b95b8e8-c90f-11de-9d4f-f947ee5921c8
+
+linkedmap.js
+file
+
+
+
+
+2011-12-23T22:42:32.866385Z
+1d1a4d93f5410375e2d67ea6864d8fde
+2011-04-12T20:35:47.000000Z
+850
+diegosalas@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13230
+
+map_test.html
+file
+
+
+
+
+2011-12-23T22:42:32.866385Z
+58bff88f087dce09b4ddd23243c9902c
+2011-12-09T02:22:04.000000Z
+1464
+terryok@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+10508
+
+treenode.js
+file
+
+
+
+
+2011-12-23T22:42:32.866385Z
+69486be5e3128cb262846961fe3c25db
+2011-09-08T08:46:43.000000Z
+1273
+pallosp@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+12017
+
+structs.js
+file
+
+
+
+
+2011-12-23T22:42:32.867385Z
+74176fd655eb69cc7cf5d789e4d4d255
+2011-12-13T22:20:28.000000Z
+1472
+ccalabro@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+11116
+
+prioritypool.js
+file
+
+
+
+
+2011-12-23T22:42:32.867385Z
+4434761ca03dda42a4b58f39590f0fb1
+2011-09-27T00:20:47.000000Z
+1302
+bmccann@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5498
+
+queue_test.html
+file
+
+
+
+
+2011-12-23T22:42:32.867385Z
+283a41a7fc978a9234c707e05487ff30
+2011-04-12T20:35:47.000000Z
+850
+diegosalas@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4266
+
+heap.js
+file
+
+
+
+
+2011-12-23T22:42:32.867385Z
+33b081d2c902ef579718205559db4b8e
+2011-07-01T12:47:03.000000Z
+1089
+pallosp@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+8671
+
+set_test.html
+file
+
+
+
+
+2011-12-23T22:42:32.868385Z
+52f46f8e2162d784f30f6f5a3696e92b
+2011-04-12T20:35:47.000000Z
+850
+diegosalas@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+15377
+
+queue.js
+file
+
+
+
+
+2011-12-23T22:42:32.868385Z
+93ebf7c7da9e02a050fdc73a98540a89
+2011-04-12T20:35:47.000000Z
+850
+diegosalas@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3774
+
+collection.js
+file
+
+
+
+
+2011-12-23T22:42:32.869385Z
+f22e5fb1e4f3962080d0208d69965797
+2011-04-28T00:46:08.000000Z
+894
+nnaze@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1349
+
+treenode_test.html
+file
+
+
+
+
+2011-12-23T22:42:32.869385Z
+d7b29eb10be5c97bc31eb4cd48b11bd7
+2011-09-08T08:46:43.000000Z
+1273
+pallosp@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13124
+
+structs_test.html
+file
+
+
+
+
+2011-12-23T22:42:32.869385Z
+5c85580c58ff3df030a53e1240e8c5e1
+2011-04-12T20:35:47.000000Z
+850
+diegosalas@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+26975
+
+inversionmap_test.html
+file
+
+
+
+
+2011-12-23T22:42:32.869385Z
+e0af3883e2267d2f9e8389619c382f08
+2011-04-12T20:35:47.000000Z
+850
+diegosalas@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5279
+
+quadtree_test.html
+file
+
+
+
+
+2011-12-23T22:42:32.870385Z
+8c01f1655e71a64b04b04ce5ca953346
+2011-04-12T20:35:47.000000Z
+850
+diegosalas@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5579
+
+prioritypool_test.html
+file
+
+
+
+
+2011-12-23T22:42:32.870385Z
+e588d717c28ec29bf8bbb3accf5d4d3b
+2011-04-12T20:35:47.000000Z
+850
+diegosalas@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+11241
+
+trie.js
+file
+
+
+
+
+2011-12-23T22:42:32.870385Z
+a1da7893ceec2444f1e3f4fef7eea595
+2011-04-12T20:35:47.000000Z
+850
+diegosalas@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+11094
+
+heap_test.html
+file
+
+
+
+
+2011-12-23T22:42:32.870385Z
+25631c554e406eed02a1a2bf83aa7b74
+2011-04-12T20:35:47.000000Z
+850
+diegosalas@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5233
+
+stringset_test.html
+file
+
+
+
+
+2011-12-23T22:42:32.871385Z
+4e5a13e15ad12535269f9dbfed74d69f
+2011-04-12T20:35:47.000000Z
+850
+diegosalas@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+8518
+
+pool.js
+file
+
+
+
+
+2011-12-23T22:42:32.871385Z
+1d6f600dfd8a6945b9c55c93507e8224
+2011-06-10T12:08:17.000000Z
+1024
+pallosp@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+10544
+
+quadtree.js
+file
+
+
+
+
+2011-12-23T22:42:32.871385Z
+93516469e492bce6a8cec09407636a98
+2011-04-12T20:35:47.000000Z
+850
+diegosalas@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+15959
+
+inversionmap.js
+file
+
+
+
+
+2011-12-23T22:42:32.871385Z
+81b590e2ba1b157504cebf25c756ffcf
+2011-04-12T20:35:47.000000Z
+850
+diegosalas@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5048
+
+priorityqueue_test.html
+file
+
+
+
+
+2011-12-23T22:42:32.872385Z
+c071bd55dd0ddc9cca59b466e473583d
+2011-04-12T20:35:47.000000Z
+850
+diegosalas@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4346
+
+map.js
+file
+
+
+
+
+2011-12-23T22:42:32.872385Z
+8edd6885e649260b336ef4f2d0f8fd05
+2011-12-13T22:20:28.000000Z
+1472
+ccalabro@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+12321
+
+collection_test.html
+file
+
+
+
+
+2011-12-23T22:42:32.873385Z
+9250c055315ad0d9824981d0900da956
+2011-04-28T00:46:08.000000Z
+894
+nnaze@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1361
+
+stringset.js
+file
+
+
+
+
+2011-12-23T22:42:32.872385Z
+270b9ebd91b05bedc57bbea65f0c788a
+2011-04-12T20:35:47.000000Z
+850
+diegosalas@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+11599
+
+simplepool.js
+file
+
+
+
+
+2011-12-23T22:42:32.873385Z
+e54248964695a611a5f5c5cbabb1ef55
+2011-06-10T12:08:17.000000Z
+1024
+pallosp@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5876
+
+node.js
+file
+
+
+
+
+2011-12-23T22:42:32.874385Z
+3dc510de90c9751b771412a6d4675d37
+2011-04-12T20:35:47.000000Z
+850
+diegosalas@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1664
+
+circularbuffer_test.html
+file
+
+
+
+
+2011-12-23T22:42:32.874385Z
+1370cc8894fe3487d5be3d1df175b180
+2011-04-12T20:35:47.000000Z
+850
+diegosalas@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2756
+
+priorityqueue.js
+file
+
+
+
+
+2011-12-23T22:42:32.874385Z
+827ef3c1ad0dae638c1a7a1ca391debc
+2011-04-12T20:35:47.000000Z
+850
+diegosalas@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1856
+
+avltree_test.html
+file
+
+
+
+
+2011-12-23T22:42:32.874385Z
+48601942752ffd00f4496783f218ae86
+2011-04-27T21:45:37.000000Z
+893
+nnaze@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+6932
+
+trie_test.html
+file
+
+
+
+
+2011-12-23T22:42:32.875385Z
+652a0fda0df46b6eaa7387069d3c86e2
+2011-04-12T20:35:47.000000Z
+850
+diegosalas@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13684
+
+set.js
+file
+
+
+
+
+2011-12-23T22:42:32.875385Z
+d80fdbaf09feedebfcb7e5fbf6d9d4c4
+2011-12-13T22:20:28.000000Z
+1472
+ccalabro@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+8142
+
+linkedmap_test.html
+file
+
+
+
+
+2011-12-23T22:42:32.875385Z
+dbd767c587a6dc85c05050f89133ab2c
+2011-04-12T20:35:47.000000Z
+850
+diegosalas@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+7703
+
+circularbuffer.js
+file
+
+
+
+
+2011-12-23T22:42:32.875385Z
+efbd3a5428640405306996c8f0d11c9b
+2011-04-12T20:35:47.000000Z
+850
+diegosalas@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5626
+
+set_perf.html
+file
+
+
+
+
+2011-12-23T22:42:32.876385Z
+17541e672e7d704bb8da04b03ebbba6f
+2011-04-12T20:35:47.000000Z
+850
+diegosalas@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+7002
+
+pool_test.html
+file
+
+
+
+
+2011-12-23T22:42:32.876385Z
+7ee93b27afb05e29c396822a07e9e476
+2011-04-12T20:35:47.000000Z
+850
+diegosalas@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+6782
+
+avltree.js
+file
+
+
+
+
+2011-12-23T22:42:32.876385Z
+514e3a8a68668c89fb661140a7a950c7
+2011-04-28T00:46:08.000000Z
+894
+nnaze@google.com
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+22646
+
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/avltree.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/avltree.js.svn-base
new file mode 100644
index 0000000..530636b
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/avltree.js.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 15
+text/javascript
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/avltree_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/avltree_test.html.svn-base
new file mode 100644
index 0000000..d356868
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/avltree_test.html.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 9
+text/html
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/circularbuffer.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/circularbuffer.js.svn-base
new file mode 100644
index 0000000..530636b
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/circularbuffer.js.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 15
+text/javascript
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/circularbuffer_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/circularbuffer_test.html.svn-base
new file mode 100644
index 0000000..d356868
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/circularbuffer_test.html.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 9
+text/html
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/collection.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/collection.js.svn-base
new file mode 100644
index 0000000..530636b
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/collection.js.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 15
+text/javascript
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/collection_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/collection_test.html.svn-base
new file mode 100644
index 0000000..d356868
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/collection_test.html.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 9
+text/html
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/heap.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/heap.js.svn-base
new file mode 100644
index 0000000..530636b
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/heap.js.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 15
+text/javascript
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/heap_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/heap_test.html.svn-base
new file mode 100644
index 0000000..d356868
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/heap_test.html.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 9
+text/html
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/inversionmap.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/inversionmap.js.svn-base
new file mode 100644
index 0000000..530636b
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/inversionmap.js.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 15
+text/javascript
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/inversionmap_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/inversionmap_test.html.svn-base
new file mode 100644
index 0000000..d356868
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/inversionmap_test.html.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 9
+text/html
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/linkedmap.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/linkedmap.js.svn-base
new file mode 100644
index 0000000..530636b
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/linkedmap.js.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 15
+text/javascript
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/linkedmap_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/linkedmap_test.html.svn-base
new file mode 100644
index 0000000..d356868
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/linkedmap_test.html.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 9
+text/html
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/map.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/map.js.svn-base
new file mode 100644
index 0000000..530636b
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/map.js.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 15
+text/javascript
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/map_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/map_test.html.svn-base
new file mode 100644
index 0000000..d356868
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/map_test.html.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 9
+text/html
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/node.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/node.js.svn-base
new file mode 100644
index 0000000..530636b
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/node.js.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 15
+text/javascript
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/pool.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/pool.js.svn-base
new file mode 100644
index 0000000..530636b
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/pool.js.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 15
+text/javascript
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/pool_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/pool_test.html.svn-base
new file mode 100644
index 0000000..d356868
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/pool_test.html.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 9
+text/html
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/prioritypool.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/prioritypool.js.svn-base
new file mode 100644
index 0000000..530636b
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/prioritypool.js.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 15
+text/javascript
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/prioritypool_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/prioritypool_test.html.svn-base
new file mode 100644
index 0000000..d356868
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/prioritypool_test.html.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 9
+text/html
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/priorityqueue.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/priorityqueue.js.svn-base
new file mode 100644
index 0000000..530636b
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/priorityqueue.js.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 15
+text/javascript
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/priorityqueue_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/priorityqueue_test.html.svn-base
new file mode 100644
index 0000000..d356868
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/priorityqueue_test.html.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 9
+text/html
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/quadtree.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/quadtree.js.svn-base
new file mode 100644
index 0000000..530636b
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/quadtree.js.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 15
+text/javascript
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/quadtree_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/quadtree_test.html.svn-base
new file mode 100644
index 0000000..d356868
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/quadtree_test.html.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 9
+text/html
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/queue.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/queue.js.svn-base
new file mode 100644
index 0000000..530636b
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/queue.js.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 15
+text/javascript
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/queue_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/queue_test.html.svn-base
new file mode 100644
index 0000000..d356868
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/queue_test.html.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 9
+text/html
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/set.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/set.js.svn-base
new file mode 100644
index 0000000..530636b
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/set.js.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 15
+text/javascript
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/set_perf.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/set_perf.html.svn-base
new file mode 100644
index 0000000..d356868
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/set_perf.html.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 9
+text/html
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/set_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/set_test.html.svn-base
new file mode 100644
index 0000000..d356868
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/set_test.html.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 9
+text/html
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/simplepool.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/simplepool.js.svn-base
new file mode 100644
index 0000000..530636b
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/simplepool.js.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 15
+text/javascript
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/stringset.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/stringset.js.svn-base
new file mode 100644
index 0000000..530636b
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/stringset.js.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 15
+text/javascript
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/stringset_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/stringset_test.html.svn-base
new file mode 100644
index 0000000..d356868
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/stringset_test.html.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 9
+text/html
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/structs.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/structs.js.svn-base
new file mode 100644
index 0000000..530636b
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/structs.js.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 15
+text/javascript
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/structs_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/structs_test.html.svn-base
new file mode 100644
index 0000000..d356868
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/structs_test.html.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 9
+text/html
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/treenode.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/treenode.js.svn-base
new file mode 100644
index 0000000..530636b
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/treenode.js.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 15
+text/javascript
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/treenode_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/treenode_test.html.svn-base
new file mode 100644
index 0000000..d356868
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/treenode_test.html.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 9
+text/html
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/trie.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/trie.js.svn-base
new file mode 100644
index 0000000..530636b
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/trie.js.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 15
+text/javascript
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/trie_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/trie_test.html.svn-base
new file mode 100644
index 0000000..d356868
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/prop-base/trie_test.html.svn-base
@@ -0,0 +1,5 @@
+K 13
+svn:mime-type
+V 9
+text/html
+END
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/avltree.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/avltree.js.svn-base
new file mode 100644
index 0000000..306ab2a
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/avltree.js.svn-base
@@ -0,0 +1,772 @@
+// Copyright 2007 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Datastructure: AvlTree.
+ *
+ *
+ * This file provides the implementation of an AVL-Tree datastructure. The tree
+ * maintains a set of unique values in a sorted order. The values can be
+ * accessed efficiently in their sorted order since the tree enforces an O(logn)
+ * maximum height. See http://en.wikipedia.org/wiki/Avl_tree for more detail.
+ *
+ * The big-O notation for all operations are below:
+ * <pre>
+ * Method big-O
+ * ----------------------------------------------------------------------------
+ * - add O(logn)
+ * - remove O(logn)
+ * - clear O(1)
+ * - contains O(logn)
+ * - getCount O(1)
+ * - getMinimum O(1), or O(logn) when optional root is specified
+ * - getMaximum O(1), or O(logn) when optional root is specified
+ * - getHeight O(1)
+ * - getValues O(n)
+ * - inOrderTraverse O(logn + k), where k is number of traversed nodes
+ * - reverseOrderTraverse O(logn + k), where k is number of traversed nodes
+ * </pre>
+ */
+
+
+goog.provide('goog.structs.AvlTree');
+goog.provide('goog.structs.AvlTree.Node');
+
+goog.require('goog.structs');
+goog.require('goog.structs.Collection');
+
+
+
+/**
+ * Constructs an AVL-Tree, which uses the specified comparator to order its
+ * values. The values can be accessed efficiently in their sorted order since
+ * the tree enforces a O(logn) maximum height.
+ *
+ * @param {Function=} opt_comparator Function used to order the tree's nodes.
+ * @constructor
+ * @implements {goog.structs.Collection}
+ */
+goog.structs.AvlTree = function(opt_comparator) {
+ this.comparator_ = opt_comparator ||
+ goog.structs.AvlTree.DEFAULT_COMPARATOR_;
+};
+
+
+/**
+ * String comparison function used to compare values in the tree. This function
+ * is used by default if no comparator is specified in the tree's constructor.
+ *
+ * @param {string} a The first string.
+ * @param {string} b The second string.
+ * @return {number} -1 if a < b, 1 if a > b, 0 if a = b.
+ * @private
+ */
+goog.structs.AvlTree.DEFAULT_COMPARATOR_ = function(a, b) {
+ if (String(a) < String(b)) {
+ return -1;
+ } else if (String(a) > String(b)) {
+ return 1;
+ }
+ return 0;
+};
+
+
+/**
+ * Pointer to the root node of the tree.
+ *
+ * @type {goog.structs.AvlTree.Node}
+ * @private
+ */
+goog.structs.AvlTree.prototype.root_ = null;
+
+
+/**
+ * Comparison function used to compare values in the tree. This function should
+ * take two values, a and b, and return x where:
+ * <pre>
+ * x < 0 if a < b,
+ * x > 0 if a > b,
+ * x = 0 otherwise
+ * </pre>
+ *
+ * @type {Function}
+ * @private
+ */
+goog.structs.AvlTree.prototype.comparator_ = null;
+
+
+/**
+ * Pointer to the node with the smallest value in the tree.
+ *
+ * @type {goog.structs.AvlTree.Node}
+ * @private
+ */
+goog.structs.AvlTree.prototype.minNode_ = null;
+
+
+/**
+ * Pointer to the node with the largest value in the tree.
+ *
+ * @type {goog.structs.AvlTree.Node}
+ * @private
+ */
+goog.structs.AvlTree.prototype.maxNode_ = null;
+
+
+/**
+ * Keeps track of the number of nodes in the tree.
+ *
+ * @type {number}
+ * @private
+ */
+goog.structs.AvlTree.prototype.count_ = 0;
+
+
+/**
+ * Inserts a node into the tree with the specified value if the tree does
+ * not already contain a node with the specified value. If the value is
+ * inserted, the tree is balanced to enforce the AVL-Tree height property.
+ *
+ * @param {*} value Value to insert into the tree.
+ * @return {boolean} Whether value was inserted into the tree.
+ */
+goog.structs.AvlTree.prototype.add = function(value) {
+ // If the tree is empty, create a root node with the specified value
+ if (this.root_ == null) {
+ this.root_ = new goog.structs.AvlTree.Node(value);
+ this.minNode_ = this.root_;
+ this.maxNode_ = this.root_;
+ this.count_ = 1;
+ return true;
+ }
+
+ // Assume a node is not added and change status when one is
+ var retStatus = false;
+
+ // Depth traverse the tree and insert the value if we reach a null node
+ this.traverse_(function(node) {
+ var retNode = null;
+ if (this.comparator_(node.value, value) > 0) {
+ retNode = node.left;
+ if (node.left == null) {
+ var newNode = new goog.structs.AvlTree.Node(value, node);
+ node.left = newNode;
+ if (node == this.minNode_) {
+ this.minNode_ = newNode;
+ }
+ retStatus = true; // Value was added to tree
+ this.balance_(node); // Maintain the AVL-tree balance
+ }
+ } else if (this.comparator_(node.value, value) < 0) {
+ retNode = node.right;
+ if (node.right == null) {
+ var newNode = new goog.structs.AvlTree.Node(value, node);
+ node.right = newNode;
+ if (node == this.maxNode_) {
+ this.maxNode_ = newNode;
+ }
+ retStatus = true; // Value was added to tree
+ this.balance_(node); // Maintain the AVL-tree balance
+ }
+ }
+ return retNode; // If null, we'll stop traversing the tree
+ });
+
+ // If a node was added, increment count
+ if (retStatus) {
+ this.count_ += 1;
+ }
+
+ // Return true if a node was added, false otherwise
+ return retStatus;
+};
+
+
+/**
+ * Removes a node from the tree with the specified value if the tree contains a
+ * node with this value. If a node is removed the tree is balanced to enforce
+ * the AVL-Tree height property. The value of the removed node is returned.
+ *
+ * @param {*} value Value to find and remove from the tree.
+ * @return {*} The value of the removed node or null if the value was not in
+ * the tree.
+ */
+goog.structs.AvlTree.prototype.remove = function(value) {
+ // Assume the value is not removed and set the value when it is removed
+ var retValue = null;
+
+ // Depth traverse the tree and remove the value if we find it
+ this.traverse_(function(node) {
+ var retNode = null;
+ if (this.comparator_(node.value, value) > 0) {
+ retNode = node.left;
+ } else if (this.comparator_(node.value, value) < 0) {
+ retNode = node.right;
+ } else {
+ retValue = node.value;
+ this.removeNode_(node);
+ }
+ return retNode; // If null, we'll stop traversing the tree
+ });
+
+ // If a node was removed, decrement count.
+ if (retValue) {
+ // Had traverse_() cleared the tree, set to 0.
+ this.count_ = this.root_ ? this.count_ - 1 : 0;
+ }
+
+ // Return the value that was removed, null if the value was not in the tree
+ return retValue;
+};
+
+
+/**
+ * Removes all nodes from the tree.
+ */
+goog.structs.AvlTree.prototype.clear = function() {
+ this.root_ = null;
+ this.minNode_ = null;
+ this.maxNode_ = null;
+ this.count_ = 0;
+};
+
+
+/**
+ * Returns true if the tree contains a node with the specified value, false
+ * otherwise.
+ *
+ * @param {*} value Value to find in the tree.
+ * @return {boolean} Whether the tree contains a node with the specified value.
+ */
+goog.structs.AvlTree.prototype.contains = function(value) {
+ // Assume the value is not in the tree and set this value if it is found
+ var isContained = false;
+
+ // Depth traverse the tree and set isContained if we find the node
+ this.traverse_(function(node) {
+ var retNode = null;
+ if (this.comparator_(node.value, value) > 0) {
+ retNode = node.left;
+ } else if (this.comparator_(node.value, value) < 0) {
+ retNode = node.right;
+ } else {
+ isContained = true;
+ }
+ return retNode; // If null, we'll stop traversing the tree
+ });
+
+ // Return true if the value is contained in the tree, false otherwise
+ return isContained;
+};
+
+
+/**
+ * Returns the number of values stored in the tree.
+ *
+ * @return {number} The number of values stored in the tree.
+ */
+goog.structs.AvlTree.prototype.getCount = function() {
+ return this.count_;
+};
+
+
+/**
+ * Returns the value u, such that u is contained in the tree and u < v, for all
+ * values v in the tree where v != u.
+ *
+ * @return {*} The minimum value contained in the tree.
+ */
+goog.structs.AvlTree.prototype.getMinimum = function() {
+ return this.getMinNode_().value;
+};
+
+
+/**
+ * Returns the value u, such that u is contained in the tree and u > v, for all
+ * values v in the tree where v != u.
+ *
+ * @return {*} The maximum value contained in the tree.
+ */
+goog.structs.AvlTree.prototype.getMaximum = function() {
+ return this.getMaxNode_().value;
+};
+
+
+/**
+ * Returns the height of the tree (the maximum depth). This height should
+ * always be <= 1.4405*(Math.log(n+2)/Math.log(2))-1.3277, where n is the
+ * number of nodes in the tree.
+ *
+ * @return {number} The height of the tree.
+ */
+goog.structs.AvlTree.prototype.getHeight = function() {
+ return this.root_ ? this.root_.height : 0;
+};
+
+
+/**
+ * Inserts the values stored in the tree into a new Array and returns the Array.
+ *
+ * @return {Array} An array containing all of the trees values in sorted order.
+ */
+goog.structs.AvlTree.prototype.getValues = function() {
+ var ret = [];
+ this.inOrderTraverse(function(value) {
+ ret.push(value);
+ });
+ return ret;
+};
+
+
+/**
+ * Performs an in-order traversal of the tree and calls {@code func} with each
+ * traversed node, optionally starting from the smallest node with a value >= to
+ * the specified start value. The traversal ends after traversing the tree's
+ * maximum node or when {@code func} returns a value that evaluates to true.
+ *
+ * @param {Function} func Function to call on each traversed node.
+ * @param {Object=} opt_startValue If specified, traversal will begin on the
+ * node with the smallest value >= opt_startValue.
+ */
+goog.structs.AvlTree.prototype.inOrderTraverse =
+ function(func, opt_startValue) {
+ // If our tree is empty, return immediately
+ if (!this.root_) {
+ return;
+ }
+
+ // Depth traverse the tree to find node to begin in-order traversal from
+ var startNode;
+ if (opt_startValue) {
+ this.traverse_(function(node) {
+ var retNode = null;
+ if (this.comparator_(node.value, opt_startValue) > 0) {
+ retNode = node.left;
+ startNode = node;
+ } else if (this.comparator_(node.value, opt_startValue) < 0) {
+ retNode = node.right;
+ } else {
+ startNode = node;
+ }
+ return retNode; // If null, we'll stop traversing the tree
+ });
+ } else {
+ startNode = this.getMinNode_();
+ }
+
+ // Traverse the tree and call func on each traversed node's value
+ var node = startNode, prev = startNode.left ? startNode.left : startNode;
+ while (node != null) {
+ if (node.left != null && node.left != prev && node.right != prev) {
+ node = node.left;
+ } else {
+ if (node.right != prev) {
+ if (func(node.value)) {
+ return;
+ }
+ }
+ var temp = node;
+ node = node.right != null && node.right != prev ?
+ node.right :
+ node.parent;
+ prev = temp;
+ }
+ }
+};
+
+
+/**
+ * Performs a reverse-order traversal of the tree and calls {@code func} with
+ * each traversed node, optionally starting from the largest node with a value
+ * <= to the specified start value. The traversal ends after traversing the
+ * tree's minimum node or when func returns a value that evaluates to true.
+ *
+ * @param {Function} func Function to call on each traversed node.
+ * @param {Object=} opt_startValue If specified, traversal will begin on the
+ * node with the largest value <= opt_startValue.
+ */
+goog.structs.AvlTree.prototype.reverseOrderTraverse =
+ function(func, opt_startValue) {
+ // If our tree is empty, return immediately
+ if (!this.root_) {
+ return;
+ }
+
+ // Depth traverse the tree to find node to begin reverse-order traversal from
+ var startNode;
+ if (opt_startValue) {
+ this.traverse_(goog.bind(function(node) {
+ var retNode = null;
+ if (this.comparator_(node.value, opt_startValue) > 0) {
+ retNode = node.left;
+ } else if (this.comparator_(node.value, opt_startValue) < 0) {
+ retNode = node.right;
+ startNode = node;
+ } else {
+ startNode = node;
+ }
+ return retNode; // If null, we'll stop traversing the tree
+ }, this));
+ } else {
+ startNode = this.getMaxNode_();
+ }
+
+ // Traverse the tree and call func on each traversed node's value
+ var node = startNode, prev = startNode.right ? startNode.right : startNode;
+ while (node != null) {
+ if (node.right != null && node.right != prev && node.left != prev) {
+ node = node.right;
+ } else {
+ if (node.left != prev) {
+ if (func(node.value)) {
+ return;
+ }
+ }
+ var temp = node;
+ node = node.left != null && node.left != prev ?
+ node.left :
+ node.parent;
+ prev = temp;
+ }
+ }
+};
+
+
+/**
+ * Performs a traversal defined by the supplied {@code traversalFunc}. The first
+ * call to {@code traversalFunc} is passed the root or the optionally specified
+ * startNode. After that, calls {@code traversalFunc} with the node returned
+ * by the previous call to {@code traversalFunc} until {@code traversalFunc}
+ * returns null or the optionally specified endNode. The first call to
+ * traversalFunc is passed the root or the optionally specified startNode.
+ *
+ * @param {Function} traversalFunc Function used to traverse the tree. Takes a
+ * node as a parameter and returns a node.
+ * @param {goog.structs.AvlTree.Node=} opt_startNode The node at which the
+ * traversal begins.
+ * @param {goog.structs.AvlTree.Node=} opt_endNode The node at which the
+ * traversal ends.
+ * @private
+ */
+goog.structs.AvlTree.prototype.traverse_ =
+ function(traversalFunc, opt_startNode, opt_endNode) {
+ var node = opt_startNode ? opt_startNode : this.root_;
+ var endNode = opt_endNode ? opt_endNode : null;
+ while (node && node != endNode) {
+ node = traversalFunc.call(this, node);
+ }
+};
+
+
+/**
+ * Ensures that the specified node and all its ancestors are balanced. If they
+ * are not, performs left and right tree rotations to achieve a balanced
+ * tree. This method assumes that at most 2 rotations are necessary to balance
+ * the tree (which is true for AVL-trees that are balanced after each node is
+ * added or removed).
+ *
+ * @param {goog.structs.AvlTree.Node} node Node to begin balance from.
+ * @private
+ */
+goog.structs.AvlTree.prototype.balance_ = function(node) {
+
+ this.traverse_(function(node) {
+ // Calculate the left and right node's heights
+ var lh = node.left ? node.left.height : 0;
+ var rh = node.right ? node.right.height : 0;
+
+ // Rotate tree rooted at this node if it is not AVL-tree balanced
+ if (lh - rh > 1) {
+ if (node.left.right && (!node.left.left ||
+ node.left.left.height < node.left.right.height)) {
+ this.leftRotate_(node.left);
+ }
+ this.rightRotate_(node);
+ } else if (rh - lh > 1) {
+ if (node.right.left && (!node.right.right ||
+ node.right.right.height < node.right.left.height)) {
+ this.rightRotate_(node.right);
+ }
+ this.leftRotate_(node);
+ }
+
+ // Recalculate the left and right node's heights
+ lh = node.left ? node.left.height : 0;
+ rh = node.right ? node.right.height : 0;
+
+ // Set this node's height
+ node.height = Math.max(lh, rh) + 1;
+
+ // Traverse up tree and balance parent
+ return node.parent;
+ }, node);
+
+};
+
+
+/**
+ * Performs a left tree rotation on the specified node.
+ *
+ * @param {goog.structs.AvlTree.Node} node Pivot node to rotate from.
+ * @private
+ */
+goog.structs.AvlTree.prototype.leftRotate_ = function(node) {
+ // Re-assign parent-child references for the parent of the node being removed
+ if (node.isLeftChild()) {
+ node.parent.left = node.right;
+ node.right.parent = node.parent;
+ } else if (node.isRightChild()) {
+ node.parent.right = node.right;
+ node.right.parent = node.parent;
+ } else {
+ this.root_ = node.right;
+ this.root_.parent = null;
+ }
+
+ // Re-assign parent-child references for the child of the node being removed
+ var temp = node.right;
+ node.right = node.right.left;
+ if (node.right != null) node.right.parent = node;
+ temp.left = node;
+ node.parent = temp;
+};
+
+
+/**
+ * Performs a right tree rotation on the specified node.
+ *
+ * @param {goog.structs.AvlTree.Node} node Pivot node to rotate from.
+ * @private
+ */
+goog.structs.AvlTree.prototype.rightRotate_ = function(node) {
+ // Re-assign parent-child references for the parent of the node being removed
+ if (node.isLeftChild()) {
+ node.parent.left = node.left;
+ node.left.parent = node.parent;
+ } else if (node.isRightChild()) {
+ node.parent.right = node.left;
+ node.left.parent = node.parent;
+ } else {
+ this.root_ = node.left;
+ this.root_.parent = null;
+ }
+
+ // Re-assign parent-child references for the child of the node being removed
+ var temp = node.left;
+ node.left = node.left.right;
+ if (node.left != null) node.left.parent = node;
+ temp.right = node;
+ node.parent = temp;
+};
+
+
+/**
+ * Removes the specified node from the tree and ensures the tree still
+ * maintains the AVL-tree balance.
+ *
+ * @param {goog.structs.AvlTree.Node} node The node to be removed.
+ * @private
+ */
+goog.structs.AvlTree.prototype.removeNode_ = function(node) {
+ // Perform normal binary tree node removal, but balance the tree, starting
+ // from where we removed the node
+ if (node.left != null || node.right != null) {
+ var b = null; // Node to begin balance from
+ var r; // Node to replace the node being removed
+ if (node.left != null) {
+ r = this.getMaxNode_(node.left);
+ if (r != node.left) {
+ r.parent.right = r.left;
+ if (r.left) r.left.parent = r.parent;
+ r.left = node.left;
+ r.left.parent = r;
+ b = r.parent;
+ }
+ r.parent = node.parent;
+ r.right = node.right;
+ if (r.right) r.right.parent = r;
+ if (node == this.maxNode_) this.maxNode_ = r;
+ } else {
+ r = this.getMinNode_(node.right);
+ if (r != node.right) {
+ r.parent.left = r.right;
+ if (r.right) r.right.parent = r.parent;
+ r.right = node.right;
+ r.right.parent = r;
+ b = r.parent;
+ }
+ r.parent = node.parent;
+ r.left = node.left;
+ if (r.left) r.left.parent = r;
+ if (node == this.minNode_) this.minNode_ = r;
+ }
+
+ // Update the parent of the node being removed to point to its replace
+ if (node.isLeftChild()) {
+ node.parent.left = r;
+ } else if (node.isRightChild()) {
+ node.parent.right = r;
+ } else {
+ this.root_ = r;
+ }
+
+ // Balance the tree
+ this.balance_(b ? b : r);
+ } else {
+ // If the node is a leaf, remove it and balance starting from its parent
+ if (node.isLeftChild()) {
+ this.special = 1;
+ node.parent.left = null;
+ if (node == this.minNode_) this.minNode_ = node.parent;
+ this.balance_(node.parent);
+ } else if (node.isRightChild()) {
+ node.parent.right = null;
+ if (node == this.maxNode_) this.maxNode_ = node.parent;
+ this.balance_(node.parent);
+ } else {
+ this.clear();
+ }
+ }
+};
+
+
+/**
+ * Returns the node with the smallest value in tree, optionally rooted at
+ * {@code opt_rootNode}.
+ *
+ * @param {goog.structs.AvlTree.Node=} opt_rootNode Optional root node.
+ * @return {goog.structs.AvlTree.Node} The node with the smallest value in
+ * the tree.
+ * @private
+ */
+goog.structs.AvlTree.prototype.getMinNode_ = function(opt_rootNode) {
+ if (!opt_rootNode) {
+ return this.minNode_;
+ }
+
+ var minNode = opt_rootNode;
+ this.traverse_(function(node) {
+ var retNode = null;
+ if (node.left) {
+ minNode = node.left;
+ retNode = node.left;
+ }
+ return retNode; // If null, we'll stop traversing the tree
+ }, opt_rootNode);
+
+ return minNode;
+};
+
+
+/**
+ * Returns the node with the largest value in tree, optionally rooted at
+ * opt_rootNode.
+ *
+ * @param {goog.structs.AvlTree.Node=} opt_rootNode Optional root node.
+ * @return {goog.structs.AvlTree.Node} The node with the largest value in
+ * the tree.
+ * @private
+ */
+goog.structs.AvlTree.prototype.getMaxNode_ = function(opt_rootNode) {
+ if (!opt_rootNode) {
+ return this.maxNode_;
+ }
+
+ var maxNode = opt_rootNode;
+ this.traverse_(function(node) {
+ var retNode = null;
+ if (node.right) {
+ maxNode = node.right;
+ retNode = node.right;
+ }
+ return retNode; // If null, we'll stop traversing the tree
+ }, opt_rootNode);
+
+ return maxNode;
+};
+
+
+
+/**
+ * Constructs an AVL-Tree node with the specified value. If no parent is
+ * specified, the node's parent is assumed to be null. The node's height
+ * defaults to 1 and its children default to null.
+ *
+ * @param {*} value Value to store in the node.
+ * @param {goog.structs.AvlTree.Node=} opt_parent Optional parent node.
+ * @constructor
+ */
+goog.structs.AvlTree.Node = function(value, opt_parent) {
+ /**
+ * The value stored by the node.
+ *
+ * @type {*}
+ */
+ this.value = value;
+
+ /**
+ * The node's parent. Null if the node is the root.
+ *
+ * @type {goog.structs.AvlTree.Node}
+ */
+ this.parent = opt_parent ? opt_parent : null;
+};
+
+
+/**
+ * The node's left child. Null if the node does not have a left child.
+ *
+ * @type {goog.structs.AvlTree.Node?}
+ */
+goog.structs.AvlTree.Node.prototype.left = null;
+
+
+/**
+ * The node's right child. Null if the node does not have a right child.
+ *
+ * @type {goog.structs.AvlTree.Node?}
+ */
+goog.structs.AvlTree.Node.prototype.right = null;
+
+
+/**
+ * The height of the tree rooted at this node.
+ *
+ * @type {number}
+ */
+goog.structs.AvlTree.Node.prototype.height = 1;
+
+
+/**
+ * Returns true iff the specified node has a parent and is the right child of
+ * its parent.
+ *
+ * @return {boolean} Whether the specified node has a parent and is the right
+ * child of its parent.
+ */
+goog.structs.AvlTree.Node.prototype.isRightChild = function() {
+ return !!this.parent && this.parent.right == this;
+};
+
+
+/**
+ * Returns true iff the specified node has a parent and is the left child of
+ * its parent.
+ *
+ * @return {boolean} Whether the specified node has a parent and is the left
+ * child of its parent.
+ */
+goog.structs.AvlTree.Node.prototype.isLeftChild = function() {
+ return !!this.parent && this.parent.left == this;
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/avltree_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/avltree_test.html.svn-base
new file mode 100644
index 0000000..144047d
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/avltree_test.html.svn-base
@@ -0,0 +1,251 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2007 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs.AvlTree</title>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.structs');
+ goog.require('goog.structs.AvlTree');
+ goog.require('goog.testing.jsunit');
+</script>
+</head>
+<body>
+<script>
+
+ /**
+ * This test verifies that we can insert strings into the AvlTree and have
+ * them be stored and sorted correctly by the default comparator.
+ */
+ function testInsertsWithDefaultComparator() {
+ var tree = new goog.structs.AvlTree();
+ var values = ['bill', 'blake', 'elliot', 'jacob', 'john', 'myles', 'ted'];
+
+ // Insert strings into tree out of order
+ tree.add(values[4]);
+ tree.add(values[3]);
+ tree.add(values[0]);
+ tree.add(values[6]);
+ tree.add(values[5]);
+ tree.add(values[1]);
+ tree.add(values[2]);
+
+ // Verify strings are stored in sorted order
+ var i = 0;
+ tree.inOrderTraverse(function(value) {
+ assertEquals(values[i], value);
+ i += 1;
+ });
+ assertEquals(i, values.length);
+ };
+
+ /**
+ * This test verifies that we can insert strings into and remove strings from
+ * the AvlTree and have the only the non-removed values be stored and sorted
+ * correctly by the default comparator.
+ */
+ function testRemovesWithDefaultComparator() {
+ var tree = new goog.structs.AvlTree();
+ var values = ['bill', 'blake', 'elliot', 'jacob', 'john', 'myles', 'ted'];
+
+ // Insert strings into tree out of order
+ tree.add('frodo');
+ tree.add(values[4]);
+ tree.add(values[3]);
+ tree.add(values[0]);
+ tree.add(values[6]);
+ tree.add('samwise');
+ tree.add(values[5]);
+ tree.add(values[1]);
+ tree.add(values[2]);
+ tree.add('pippin');
+
+ // Remove strings from tree
+ assertEquals(tree.remove('samwise'), 'samwise');
+ assertEquals(tree.remove('pippin'), 'pippin');
+ assertEquals(tree.remove('frodo'), 'frodo');
+ assertEquals(tree.remove('merry'), null);
+
+
+ // Verify strings are stored in sorted order
+ var i = 0;
+ tree.inOrderTraverse(function(value) {
+ assertEquals(values[i], value);
+ i += 1;
+ });
+ assertEquals(i, values.length);
+ };
+
+ /**
+ * This test verifies that we can insert values into and remove values from
+ * the AvlTree and have them be stored and sorted correctly by a custom
+ * comparator.
+ */
+ function testInsertsAndRemovesWithCustomComparator() {
+ var tree = new goog.structs.AvlTree(function(a, b) {
+ return a - b;
+ });
+
+ var NUM_TO_INSERT = 37;
+ var valuesToRemove = [1, 0, 6, 7, 36];
+
+ // Insert ints into tree out of order
+ var values = [];
+ for (var i = 0; i < NUM_TO_INSERT; i += 1) {
+ tree.add(i);
+ values.push(i);
+ }
+
+ for (var i = 0; i < valuesToRemove.length; i += 1) {
+ assertEquals(tree.remove(valuesToRemove[i]), valuesToRemove[i]);
+ goog.array.remove(values, valuesToRemove[i]);
+ }
+ assertEquals(tree.remove(-1), null);
+ assertEquals(tree.remove(37), null);
+
+ // Verify strings are stored in sorted order
+ var i = 0;
+ tree.inOrderTraverse(function(value) {
+ assertEquals(values[i], value);
+ i += 1;
+ });
+ assertEquals(i, values.length);
+ };
+
+ /**
+ * This test verifies that we can insert values into and remove values from
+ * the AvlTree and have it maintain the AVL-Tree upperbound on its height.
+ */
+ function testAvlTreeHeight() {
+ var tree = new goog.structs.AvlTree(function(a, b) {
+ return a - b;
+ });
+
+ var NUM_TO_INSERT = 2000;
+ var NUM_TO_REMOVE = 500;
+
+ // Insert ints into tree out of order
+ for (var i = 0; i < NUM_TO_INSERT; i += 1) {
+ tree.add(i);
+ }
+
+ // Remove valuse
+ for (var i = 0; i < NUM_TO_REMOVE; i += 1) {
+ tree.remove(i);
+ }
+
+ assertTrue(tree.getHeight() <= 1.4405 *
+ (Math.log(NUM_TO_INSERT - NUM_TO_REMOVE + 2) / Math.log(2)) - 1.3277);
+ };
+
+ /**
+ * This test verifies that we can insert values into and remove values from
+ * the AvlTree and have its contains method correctly determine the values it
+ * is contains.
+ */
+ function testAvlTreeContains() {
+ var tree = new goog.structs.AvlTree();
+ var values = ['bill', 'blake', 'elliot', 'jacob', 'john', 'myles', 'ted'];
+
+ // Insert strings into tree out of order
+ tree.add('frodo');
+ tree.add(values[4]);
+ tree.add(values[3]);
+ tree.add(values[0]);
+ tree.add(values[6]);
+ tree.add('samwise');
+ tree.add(values[5]);
+ tree.add(values[1]);
+ tree.add(values[2]);
+ tree.add('pippin');
+
+ // Remove strings from tree
+ assertEquals(tree.remove('samwise'), 'samwise');
+ assertEquals(tree.remove('pippin'), 'pippin');
+ assertEquals(tree.remove('frodo'), 'frodo');
+
+ for (var i = 0; i < values.length; i += 1) {
+ assertTrue(tree.contains(values[i]));
+ }
+ assertFalse(tree.contains('samwise'));
+ assertFalse(tree.contains('pippin'));
+ assertFalse(tree.contains('frodo'));
+ };
+
+ /**
+ * This test verifies that we can insert values into and remove values from
+ * the AvlTree and have its minValue and maxValue routines return the correct
+ * min and max values contained by the tree.
+ */
+ function testMinAndMaxValues() {
+ var tree = new goog.structs.AvlTree(function(a, b) {
+ return a - b;
+ });
+
+ var NUM_TO_INSERT = 2000;
+ var NUM_TO_REMOVE = 500;
+
+ // Insert ints into tree out of order
+ for (var i = 0; i < NUM_TO_INSERT; i += 1) {
+ tree.add(i);
+ }
+
+ // Remove valuse
+ for (var i = 0; i < NUM_TO_REMOVE; i += 1) {
+ tree.remove(i);
+ }
+
+ assertEquals(tree.getMinimum(), NUM_TO_REMOVE);
+ assertEquals(tree.getMaximum(), NUM_TO_INSERT - 1);
+ };
+
+ /**
+ * This test verifies that we can insert values into and remove values from
+ * the AvlTree and traverse the tree in reverse order using the
+ * reverseOrderTraverse routine.
+ */
+ function testReverseOrderTraverse() {
+ var tree = new goog.structs.AvlTree(function(a, b) {
+ return a - b;
+ });
+
+ var NUM_TO_INSERT = 2000;
+ var NUM_TO_REMOVE = 500;
+
+ // Insert ints into tree out of order
+ for (var i = 0; i < NUM_TO_INSERT; i += 1) {
+ tree.add(i);
+ }
+
+ // Remove valuse
+ for (var i = 0; i < NUM_TO_REMOVE; i += 1) {
+ tree.remove(i);
+ }
+
+ var i = NUM_TO_INSERT - 1;
+ tree.reverseOrderTraverse(function(value) {
+ assertEquals(value, i);
+ i -= 1;
+ });
+ assertEquals(i, NUM_TO_REMOVE - 1);
+ };
+
+ /**
+ * Verifies correct behavior of getCount(). See http://b/4347755
+ */
+ function testGetCountBehavior() {
+ var tree = new goog.structs.AvlTree();
+ tree.add(1);
+ tree.remove(1);
+ assertEquals(0, tree.getCount());
+ }
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/circularbuffer.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/circularbuffer.js.svn-base
new file mode 100644
index 0000000..2964559
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/circularbuffer.js.svn-base
@@ -0,0 +1,219 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+
+/**
+ * @fileoverview Datastructure: Circular Buffer.
+ *
+ * Implements a buffer with a maximum size. New entries override the oldest
+ * entries when the maximum size has been reached.
+ *
+ */
+
+
+goog.provide('goog.structs.CircularBuffer');
+
+
+
+/**
+ * Class for CircularBuffer.
+ * @param {number=} opt_maxSize The maximum size of the buffer.
+ * @constructor
+ */
+goog.structs.CircularBuffer = function(opt_maxSize) {
+ /**
+ * Maximum size of the the circular array structure.
+ * @type {number}
+ * @private
+ */
+ this.maxSize_ = opt_maxSize || 100;
+
+ /**
+ * Underlying array for the CircularBuffer.
+ * @type {Array}
+ * @private
+ */
+ this.buff_ = [];
+};
+
+
+/**
+ * Index of the next element in the circular array structure.
+ * @type {number}
+ * @private
+ */
+goog.structs.CircularBuffer.prototype.nextPtr_ = 0;
+
+
+/**
+ * Adds an item to the buffer. May remove the oldest item if the buffer is at
+ * max size.
+ * @param {*} item The item to add.
+ */
+goog.structs.CircularBuffer.prototype.add = function(item) {
+ this.buff_[this.nextPtr_] = item;
+ this.nextPtr_ = (this.nextPtr_ + 1) % this.maxSize_;
+};
+
+
+/**
+ * Returns the item at the specified index.
+ * @param {number} index The index of the item. The index of an item can change
+ * after calls to {@code add()} if the buffer is at maximum size.
+ * @return {*} The item at the specified index.
+ */
+goog.structs.CircularBuffer.prototype.get = function(index) {
+ index = this.normalizeIndex_(index);
+ return this.buff_[index];
+};
+
+
+/**
+ * Sets the item at the specified index.
+ * @param {number} index The index of the item. The index of an item can change
+ * after calls to {@code add()} if the buffer is at maximum size.
+ * @param {*} item The item to add.
+ */
+goog.structs.CircularBuffer.prototype.set = function(index, item) {
+ index = this.normalizeIndex_(index);
+ this.buff_[index] = item;
+};
+
+
+/**
+ * Returns the current number of items in the buffer.
+ * @return {number} The current number of items in the buffer.
+ */
+goog.structs.CircularBuffer.prototype.getCount = function() {
+ return this.buff_.length;
+};
+
+
+/**
+ * @return {boolean} Whether the buffer is empty.
+ */
+goog.structs.CircularBuffer.prototype.isEmpty = function() {
+ return this.buff_.length == 0;
+};
+
+
+/**
+ * Empties the current buffer.
+ */
+goog.structs.CircularBuffer.prototype.clear = function() {
+ this.buff_.length = 0;
+ this.nextPtr_ = 0;
+};
+
+
+/**
+ * @return {Array} The values in the buffer.
+ */
+goog.structs.CircularBuffer.prototype.getValues = function() {
+ // getNewestValues returns all the values if the maxCount parameter is the
+ // count
+ return this.getNewestValues(this.getCount());
+};
+
+
+/**
+ * Returns the newest values in the buffer up to {@code count}.
+ * @param {number} maxCount The maximum number of values to get. Should be a
+ * positive number.
+ * @return {Array} The newest values in the buffer up to {@code count}.
+ */
+goog.structs.CircularBuffer.prototype.getNewestValues = function(maxCount) {
+ var l = this.getCount();
+ var start = this.getCount() - maxCount;
+ var rv = [];
+ for (var i = start; i < l; i++) {
+ rv[i] = this.get(i);
+ }
+ return rv;
+};
+
+
+/**
+ * @return {Array} The indexes in the buffer.
+ */
+goog.structs.CircularBuffer.prototype.getKeys = function() {
+ var rv = [];
+ var l = this.getCount();
+ for (var i = 0; i < l; i++) {
+ rv[i] = i;
+ }
+ return rv;
+};
+
+
+/**
+ * Whether the buffer contains the key/index.
+ * @param {number} key The key/index to check for.
+ * @return {boolean} Whether the buffer contains the key/index.
+ */
+goog.structs.CircularBuffer.prototype.containsKey = function(key) {
+ return key < this.getCount();
+};
+
+
+/**
+ * Whether the buffer contains the given value.
+ * @param {*} value The value to check for.
+ * @return {boolean} Whether the buffer contains the given value.
+ */
+goog.structs.CircularBuffer.prototype.containsValue = function(value) {
+ var l = this.getCount();
+ for (var i = 0; i < l; i++) {
+ if (this.get(i) == value) {
+ return true;
+ }
+ }
+ return false;
+};
+
+
+/**
+ * Returns the last item inserted into the buffer.
+ * @return {*} The last item inserted into the buffer, or null if the buffer is
+ * empty.
+ */
+goog.structs.CircularBuffer.prototype.getLast = function() {
+ if (this.getCount() == 0) {
+ return null;
+ }
+ return this.get(this.getCount() - 1);
+};
+
+
+/**
+ * Helper function to convert an index in the number space of oldest to
+ * newest items in the array to the position that the element will be at in the
+ * underlying array.
+ * @param {number} index The index of the item in a list ordered from oldest to
+ * newest.
+ * @return {number} The index of the item in the CircularBuffer's underlying
+ * array.
+ * @private
+ */
+goog.structs.CircularBuffer.prototype.normalizeIndex_ = function(index) {
+ if (index >= this.buff_.length) {
+ throw Error('Out of bounds exception');
+ }
+
+ if (this.buff_.length < this.maxSize_) {
+ return index;
+ }
+
+ return (this.nextPtr_ + Number(index)) % this.maxSize_;
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/circularbuffer_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/circularbuffer_test.html.svn-base
new file mode 100644
index 0000000..8d891c8
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/circularbuffer_test.html.svn-base
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2006 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs</title>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.structs.CircularBuffer');
+ goog.require('goog.testing.jsunit');
+</script>
+</head>
+<body>
+<script>
+
+function testCircularBuffer() {
+ var buff = new goog.structs.CircularBuffer(2);
+ buff.add('first');
+ assertEquals(1, buff.getCount());
+ assertEquals('first', buff.get(0));
+ assertEquals('first', buff.getLast());
+ buff.add('second');
+ assertEquals(2, buff.getCount());
+ assertEquals('first', buff.get(0));
+ assertEquals('second', buff.get(1));
+ assertEquals('second', buff.getLast());
+ buff.add('third');
+ assertEquals(2, buff.getCount());
+ assertEquals('second', buff.get(0));
+ assertEquals('third', buff.get(1));
+ assertEquals('third', buff.getLast());
+}
+
+function testIsEmpty() {
+ var buff = new goog.structs.CircularBuffer(2);
+ assertTrue('initially empty', buff.isEmpty());
+ buff.add('first');
+ assertFalse('not empty after add empty', buff.isEmpty());
+}
+
+function testClear() {
+ var buff = new goog.structs.CircularBuffer(2);
+ buff.add('first');
+ buff.clear();
+ assertTrue('should be empty after clear', buff.isEmpty());
+
+}
+
+function testGetValues() {
+ var buff = new goog.structs.CircularBuffer(2);
+ buff.add('first');
+ buff.add('second');
+ assertEquals('firstsecond', buff.getValues().join(''));
+}
+
+function testGetNewestVtalues() {
+ var buff = new goog.structs.CircularBuffer(5);
+ buff.add('first');
+ buff.add('second');
+ buff.add('third');
+ buff.add('fourth');
+ buff.add('fifth');
+ assertEquals('fourthfifth', buff.getNewestValues(2).join(''));
+}
+
+
+function testGetKeys() {
+ var buff = new goog.structs.CircularBuffer(2);
+ buff.add('first');
+ buff.add('second');
+ assertEquals('01', buff.getKeys().join(''));
+}
+
+function testContainsValue() {
+ var buff = new goog.structs.CircularBuffer(2);
+ buff.add('first');
+ buff.add('second');
+ assertTrue(buff.containsValue('first'));
+ assertTrue(buff.containsValue('second'));
+ assertFalse(buff.containsValue('third'));
+}
+
+function testContainsKey() {
+ var buff = new goog.structs.CircularBuffer(3);
+ buff.add('first');
+ buff.add('second');
+ buff.add('third');
+ assertTrue(buff.containsKey(0));
+ assertTrue(buff.containsKey('0'));
+ assertTrue(buff.containsKey(1));
+ assertTrue(buff.containsKey('1'));
+ assertTrue(buff.containsKey(2));
+ assertTrue(buff.containsKey('2'));
+ assertFalse(buff.containsKey(3));
+ assertFalse(buff.containsKey('3'));
+}
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/collection.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/collection.js.svn-base
new file mode 100644
index 0000000..8ba8cb3
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/collection.js.svn-base
@@ -0,0 +1,54 @@
+// Copyright 2011 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Defines the collection interface.
+ *
+ */
+
+goog.provide('goog.structs.Collection');
+
+
+
+/**
+ * An interface for a collection of values.
+ * @interface
+ */
+goog.structs.Collection = function() {};
+
+
+/**
+ * @param {*} value Value to add to the collection.
+ */
+goog.structs.Collection.prototype.add;
+
+
+/**
+ * @param {*} value Value to remove from the collection.
+ */
+goog.structs.Collection.prototype.remove;
+
+
+/**
+ * @param {*} value Value to find in the tree.
+ * @return {boolean} Whether the collection contains the specified value.
+ */
+goog.structs.Collection.prototype.contains;
+
+
+/**
+ * @return {number} The number of values stored in the collection.
+ */
+goog.structs.Collection.prototype.getCount;
+
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/collection_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/collection_test.html.svn-base
new file mode 100644
index 0000000..1ce9932
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/collection_test.html.svn-base
@@ -0,0 +1,57 @@
+<!doctype html>
+<html>
+<!--
+Copyright 2011 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+ <head>
+ <title>Closure Unit Tests - goog.structs.Collection</title>
+ <script src="../base.js"></script>
+ <script>
+ goog.require('goog.structs.AvlTree');
+ goog.require('goog.structs.Collection');
+ goog.require('goog.structs.Set');
+ goog.require('goog.testing.jsunit');
+ </script>
+ </head>
+ <body>
+ <script>
+
+function testSet() {
+ var set = new goog.structs.Set();
+ exerciseCollection(set)
+}
+
+function testAvlTree() {
+ var tree = new goog.structs.AvlTree();
+ exerciseCollection(tree)
+}
+
+// Simple exercise of a collection object.
+function exerciseCollection(collection) {
+ assertEquals(0, collection.getCount());
+
+ for (var i = 1; i <= 10; i++) {
+ assertFalse(collection.contains(i));
+ collection.add(i);
+ assertTrue(collection.contains(i));
+ assertEquals(i, collection.getCount());
+ }
+
+ assertEquals(10, collection.getCount());
+
+ for (var i = 10; i > 0; i--) {
+ assertTrue(collection.contains(i));
+ collection.remove(i);
+ assertFalse(collection.contains(i));
+ assertEquals(i - 1, collection.getCount());
+ }
+
+ assertEquals(0, collection.getCount());
+}
+
+ </script>
+ </body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/heap.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/heap.js.svn-base
new file mode 100644
index 0000000..98c7695
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/heap.js.svn-base
@@ -0,0 +1,333 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Datastructure: Heap.
+ *
+ *
+ * This file provides the implementation of a Heap datastructure. Smaller keys
+ * rise to the top.
+ *
+ * The big-O notation for all operations are below:
+ * <pre>
+ * Method big-O
+ * ----------------------------------------------------------------------------
+ * - insert O(logn)
+ * - remove O(logn)
+ * - peek O(1)
+ * - contains O(n)
+ * </pre>
+ */
+// TODO(user): Should this rely on natural ordering via some Comparable
+// interface?
+
+
+goog.provide('goog.structs.Heap');
+
+goog.require('goog.array');
+goog.require('goog.object');
+goog.require('goog.structs.Node');
+
+
+
+/**
+ * Class for a Heap datastructure.
+ *
+ * @param {goog.structs.Heap|Object=} opt_heap Optional goog.structs.Heap or
+ * Object to initialize heap with.
+ * @constructor
+ */
+goog.structs.Heap = function(opt_heap) {
+ /**
+ * The nodes of the heap.
+ * @private
+ * @type {Array.<goog.structs.Node>}
+ */
+ this.nodes_ = [];
+
+ if (opt_heap) {
+ this.insertAll(opt_heap);
+ }
+};
+
+
+/**
+ * Insert the given value into the heap with the given key.
+ * @param {*} key The key.
+ * @param {*} value The value.
+ */
+goog.structs.Heap.prototype.insert = function(key, value) {
+ var node = new goog.structs.Node(key, value);
+ var nodes = this.nodes_;
+ nodes.push(node);
+ this.moveUp_(nodes.length - 1);
+};
+
+
+/**
+ * Adds multiple key-value pairs from another goog.structs.Heap or Object
+ * @param {goog.structs.Heap|Object} heap Object containing the data to add.
+ */
+goog.structs.Heap.prototype.insertAll = function(heap) {
+ var keys, values;
+ if (heap instanceof goog.structs.Heap) {
+ keys = heap.getKeys();
+ values = heap.getValues();
+
+ // If it is a heap and the current heap is empty, I can realy on the fact
+ // that the keys/values are in the correct order to put in the underlying
+ // structure.
+ if (heap.getCount() <= 0) {
+ var nodes = this.nodes_;
+ for (var i = 0; i < keys.length; i++) {
+ nodes.push(new goog.structs.Node(keys[i], values[i]));
+ }
+ return;
+ }
+ } else {
+ keys = goog.object.getKeys(heap);
+ values = goog.object.getValues(heap);
+ }
+
+ for (var i = 0; i < keys.length; i++) {
+ this.insert(keys[i], values[i]);
+ }
+};
+
+
+/**
+ * Retrieves and removes the root value of this heap.
+ * @return {*} The value removed from the root of the heap. Returns
+ * undefined if the heap is empty.
+ */
+goog.structs.Heap.prototype.remove = function() {
+ var nodes = this.nodes_;
+ var count = nodes.length;
+ var rootNode = nodes[0];
+ if (count <= 0) {
+ return undefined;
+ } else if (count == 1) {
+ goog.array.clear(nodes);
+ } else {
+ nodes[0] = nodes.pop();
+ this.moveDown_(0);
+ }
+ return rootNode.getValue();
+};
+
+
+/**
+ * Retrieves but does not remove the root value of this heap.
+ * @return {*} The value at the root of the heap. Returns
+ * undefined if the heap is empty.
+ */
+goog.structs.Heap.prototype.peek = function() {
+ var nodes = this.nodes_;
+ if (nodes.length == 0) {
+ return undefined;
+ }
+ return nodes[0].getValue();
+};
+
+
+/**
+ * Retrieves but does not remove the key of the root node of this heap.
+ * @return {*} The key at the root of the heap. Returns undefined if the
+ * heap is empty.
+ */
+goog.structs.Heap.prototype.peekKey = function() {
+ return this.nodes_[0] && this.nodes_[0].getKey();
+};
+
+
+/**
+ * Moves the node at the given index down to its proper place in the heap.
+ * @param {number} index The index of the node to move down.
+ * @private
+ */
+goog.structs.Heap.prototype.moveDown_ = function(index) {
+ var nodes = this.nodes_;
+ var count = nodes.length;
+
+ // Save the node being moved down.
+ var node = nodes[index];
+ // While the current node has a child.
+ while (index < (count >> 1)) {
+ var leftChildIndex = this.getLeftChildIndex_(index);
+ var rightChildIndex = this.getRightChildIndex_(index);
+
+ // Determine the index of the smaller child.
+ var smallerChildIndex = rightChildIndex < count &&
+ nodes[rightChildIndex].getKey() < nodes[leftChildIndex].getKey() ?
+ rightChildIndex : leftChildIndex;
+
+ // If the node being moved down is smaller than its children, the node
+ // has found the correct index it should be at.
+ if (nodes[smallerChildIndex].getKey() > node.getKey()) {
+ break;
+ }
+
+ // If not, then take the smaller child as the current node.
+ nodes[index] = nodes[smallerChildIndex];
+ index = smallerChildIndex;
+ }
+ nodes[index] = node;
+};
+
+
+/**
+ * Moves the node at the given index up to its proper place in the heap.
+ * @param {number} index The index of the node to move up.
+ * @private
+ */
+goog.structs.Heap.prototype.moveUp_ = function(index) {
+ var nodes = this.nodes_;
+ var node = nodes[index];
+
+ // While the node being moved up is not at the root.
+ while (index > 0) {
+ // If the parent is less than the node being moved up, move the parent down.
+ var parentIndex = this.getParentIndex_(index);
+ if (nodes[parentIndex].getKey() > node.getKey()) {
+ nodes[index] = nodes[parentIndex];
+ index = parentIndex;
+ } else {
+ break;
+ }
+ }
+ nodes[index] = node;
+};
+
+
+/**
+ * Gets the index of the left child of the node at the given index.
+ * @param {number} index The index of the node to get the left child for.
+ * @return {number} The index of the left child.
+ * @private
+ */
+goog.structs.Heap.prototype.getLeftChildIndex_ = function(index) {
+ return index * 2 + 1;
+};
+
+
+/**
+ * Gets the index of the right child of the node at the given index.
+ * @param {number} index The index of the node to get the right child for.
+ * @return {number} The index of the right child.
+ * @private
+ */
+goog.structs.Heap.prototype.getRightChildIndex_ = function(index) {
+ return index * 2 + 2;
+};
+
+
+/**
+ * Gets the index of the parent of the node at the given index.
+ * @param {number} index The index of the node to get the parent for.
+ * @return {number} The index of the parent.
+ * @private
+ */
+goog.structs.Heap.prototype.getParentIndex_ = function(index) {
+ return (index - 1) >> 1;
+};
+
+
+/**
+ * Gets the values of the heap.
+ * @return {Array} The values in the heap.
+ */
+goog.structs.Heap.prototype.getValues = function() {
+ var nodes = this.nodes_;
+ var rv = [];
+ var l = nodes.length;
+ for (var i = 0; i < l; i++) {
+ rv.push(nodes[i].getValue());
+ }
+ return rv;
+};
+
+
+/**
+ * Gets the keys of the heap.
+ * @return {Array} The keys in the heap.
+ */
+goog.structs.Heap.prototype.getKeys = function() {
+ var nodes = this.nodes_;
+ var rv = [];
+ var l = nodes.length;
+ for (var i = 0; i < l; i++) {
+ rv.push(nodes[i].getKey());
+ }
+ return rv;
+};
+
+
+/**
+ * Whether the heap contains the given value.
+ * @param {Object} val The value to check for.
+ * @return {boolean} Whether the heap contains the value.
+ */
+goog.structs.Heap.prototype.containsValue = function(val) {
+ return goog.array.some(this.nodes_, function(node) {
+ return node.getValue() == val;
+ });
+};
+
+
+/**
+ * Whether the heap contains the given key.
+ * @param {Object} key The key to check for.
+ * @return {boolean} Whether the heap contains the key.
+ */
+goog.structs.Heap.prototype.containsKey = function(key) {
+ return goog.array.some(this.nodes_, function(node) {
+ return node.getKey() == key;
+ });
+};
+
+
+/**
+ * Clones a heap and returns a new heap
+ * @return {goog.structs.Heap} A new goog.structs.Heap with the same key-value
+ * pairs.
+ */
+goog.structs.Heap.prototype.clone = function() {
+ return new goog.structs.Heap(this);
+};
+
+
+/**
+ * The number of key-value pairs in the map
+ * @return {number} The number of pairs.
+ */
+goog.structs.Heap.prototype.getCount = function() {
+ return this.nodes_.length;
+};
+
+
+/**
+ * Returns true if this heap contains no elements.
+ * @return {boolean} Whether this heap contains no elements.
+ */
+goog.structs.Heap.prototype.isEmpty = function() {
+ return goog.array.isEmpty(this.nodes_);
+};
+
+
+/**
+ * Removes all elements from the heap.
+ */
+goog.structs.Heap.prototype.clear = function() {
+ goog.array.clear(this.nodes_);
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/heap_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/heap_test.html.svn-base
new file mode 100644
index 0000000..de7e093
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/heap_test.html.svn-base
@@ -0,0 +1,220 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2006 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs.Heap</title>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.structs');
+ goog.require('goog.structs.Heap');
+ goog.require('goog.testing.jsunit');
+</script>
+</head>
+<body>
+<script>
+
+function getHeap() {
+ var h = new goog.structs.Heap();
+ h.insert(0, 'a');
+ h.insert(1, 'b');
+ h.insert(2, 'c');
+ h.insert(3, 'd');
+ return h;
+}
+
+
+function getHeap2() {
+ var h = new goog.structs.Heap();
+ h.insert(1, 'b');
+ h.insert(3, 'd');
+ h.insert(0, 'a');
+ h.insert(2, 'c');
+ return h;
+}
+
+
+function testGetCount1() {
+ var h = getHeap();
+ assertEquals('count, should be 4', h.getCount(), 4);
+ h.remove();
+ assertEquals('count, should be 3', h.getCount(), 3);
+}
+
+function testGetCount2() {
+ var h = getHeap();
+ h.remove();
+ h.remove();
+ h.remove();
+ h.remove();
+ assertEquals('count, should be 0', h.getCount(), 0);
+}
+
+
+function testKeys() {
+ var h = getHeap();
+ var keys = h.getKeys();
+ for (var i = 0; i < 4; i++) {
+ assertTrue('getKeys, key ' + i + ' found', goog.structs.contains(keys, i));
+ }
+ assertEquals('getKeys, Should be 4 keys', goog.structs.getCount(keys), 4);
+}
+
+
+function testValues() {
+ var h = getHeap();
+ var values = h.getValues();
+
+ assertTrue('getKeys, value "a" found', goog.structs.contains(values, 'a'));
+ assertTrue('getKeys, value "b" found', goog.structs.contains(values, 'b'));
+ assertTrue('getKeys, value "c" found', goog.structs.contains(values, 'c'));
+ assertTrue('getKeys, value "d" found', goog.structs.contains(values, 'd'));
+ assertEquals('getKeys, Should be 4 keys', goog.structs.getCount(values), 4);
+}
+
+
+function testContainsKey() {
+ var h = getHeap();
+
+ for (var i = 0; i < 4; i++) {
+ assertTrue('containsKey, key ' + i + ' found', h.containsKey(i));
+ }
+ assertFalse('containsKey, value 4 not found', h.containsKey(4));
+}
+
+
+function testContainsValue() {
+ var h = getHeap();
+
+ assertTrue('containsValue, value "a" found', h.containsValue('a'));
+ assertTrue('containsValue, value "b" found', h.containsValue('b'));
+ assertTrue('containsValue, value "c" found', h.containsValue('c'));
+ assertTrue('containsValue, value "d" found', h.containsValue('d'));
+ assertFalse('containsValue, value "e" not found', h.containsValue('e'));
+}
+
+
+function testClone() {
+ var h = getHeap();
+ var h2 = h.clone();
+ assertTrue('clone so it should not be empty', !h2.isEmpty());
+ assertTrue('clone so it should contain key 0', h2.containsKey(0));
+ assertTrue('clone so it should contain value "a"', h2.containsValue('a'));
+}
+
+
+function testClear() {
+ var h = getHeap();
+ h.clear();
+ assertTrue('cleared so it should be empty', h.isEmpty());
+}
+
+
+function testIsEmpty() {
+ var h = getHeap();
+ assertFalse('4 values so should not be empty', h.isEmpty());
+
+ h.remove();
+ h.remove();
+ h.remove();
+ assertFalse('1 values so should not be empty', h.isEmpty());
+
+ h.remove();
+ assertTrue('0 values so should be empty', h.isEmpty());
+}
+
+
+function testPeek1() {
+ var h = getHeap();
+ assertEquals('peek, Should be "a"', h.peek(), 'a');
+}
+
+
+function testPeek2() {
+ var h = getHeap2();
+ assertEquals('peek, Should be "a"', h.peek(), 'a');
+}
+
+
+function testPeek3() {
+ var h = getHeap();
+ h.clear();
+ assertEquals('peek, Should be "undefined"', h.peek(), undefined);
+}
+
+
+function testPeekKey1() {
+ var h = getHeap();
+ assertEquals('peekKey, Should be "0"', h.peekKey(), 0);
+}
+
+
+function testPeekKey2() {
+ var h = getHeap2();
+ assertEquals('peekKey, Should be "0"', h.peekKey(), 0);
+}
+
+
+function testPeekKey3() {
+ var h = getHeap();
+ h.clear();
+ assertEquals('peekKey, Should be "undefined"', h.peekKey(), undefined);
+}
+
+
+function testRemove1() {
+ var h = getHeap();
+
+ assertEquals('remove, Should be "a"', h.remove(), 'a');
+ assertEquals('remove, Should be "b"', h.remove(), 'b');
+ assertEquals('remove, Should be "c"', h.remove(), 'c');
+ assertEquals('remove, Should be "d"', h.remove(), 'd');
+}
+
+
+function testRemove2() {
+ var h = getHeap2();
+
+ assertEquals('remove, Should be "a"', h.remove(), 'a');
+ assertEquals('remove, Should be "b"', h.remove(), 'b');
+ assertEquals('remove, Should be "c"', h.remove(), 'c');
+ assertEquals('remove, Should be "d"', h.remove(), 'd');
+}
+
+
+function testInsertPeek1() {
+ var h = new goog.structs.Heap();
+
+ h.insert(3, 'd');
+ assertEquals('peek, Should be "d"', h.peek(), 'd');
+ h.insert(2, 'c');
+ assertEquals('peek, Should be "c"', h.peek(), 'c');
+ h.insert(1, 'b');
+ assertEquals('peek, Should be "b"', h.peek(), 'b');
+ h.insert(0, 'a');
+ assertEquals('peek, Should be "a"', h.peek(), 'a');
+}
+
+
+function testInsertPeek2() {
+ var h = new goog.structs.Heap();
+
+ h.insert(1, 'b');
+ assertEquals('peak, Should be "b"', h.peek(), 'b');
+ h.insert(3, 'd');
+ assertEquals('peak, Should be "b"', h.peek(), 'b');
+ h.insert(0, 'a');
+ assertEquals('peak, Should be "a"', h.peek(), 'a');
+ h.insert(2, 'c');
+ assertEquals('peak, Should be "a"', h.peek(), 'a');
+}
+
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/inversionmap.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/inversionmap.js.svn-base
new file mode 100644
index 0000000..1c7c2e2
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/inversionmap.js.svn-base
@@ -0,0 +1,159 @@
+// Copyright 2008 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Provides inversion and inversion map functionality for storing
+ * integer ranges and corresponding values.
+ *
+ */
+
+goog.provide('goog.structs.InversionMap');
+
+goog.require('goog.array');
+
+
+
+/**
+ * Maps ranges to values using goog.structs.Inversion.
+ * @param {Array.<number>} rangeArray An array of monotonically
+ * increasing integer values, with at least one instance.
+ * @param {Array.<*>} valueArray An array of corresponding values.
+ * Length must be the same as rangeArray.
+ * @param {boolean=} opt_delta If true, saves only delta from previous value.
+ * @constructor
+ */
+goog.structs.InversionMap = function(rangeArray, valueArray, opt_delta) {
+ if (rangeArray.length != valueArray.length) {
+ // rangeArray and valueArray has to match in number of entries.
+ return null;
+ }
+ this.storeInversion_(rangeArray, opt_delta);
+
+ /**
+ * @type {Array}
+ * @protected
+ */
+ this.values = valueArray;
+};
+
+
+/**
+ * @type {Array}
+ * @protected
+ */
+goog.structs.InversionMap.prototype.rangeArray;
+
+
+/**
+ * Stores the integers as ranges (half-open).
+ * If delta is true, the integers are delta from the previous value and
+ * will be restored to the absolute value.
+ * When used as a set, even indices are IN, and odd are OUT.
+ * @param {Array.<number?>} rangeArray An array of monotonically
+ * increasing integer values, with at least one instance.
+ * @param {boolean=} opt_delta If true, saves only delta from previous value.
+ * @private
+ */
+goog.structs.InversionMap.prototype.storeInversion_ = function(rangeArray,
+ opt_delta) {
+ this.rangeArray = rangeArray;
+
+ for (var i = 1; i < rangeArray.length; i++) {
+ if (rangeArray[i] == null) {
+ rangeArray[i] = rangeArray[i - 1] + 1;
+ } else if (opt_delta) {
+ rangeArray[i] += rangeArray[i - 1];
+ }
+ }
+};
+
+
+/**
+ * Splices a range -> value map into this inversion map.
+ * @param {Array.<number>} rangeArray An array of monotonically
+ * increasing integer values, with at least one instance.
+ * @param {Array.<*>} valueArray An array of corresponding values.
+ * Length must be the same as rangeArray.
+ * @param {boolean=} opt_delta If true, saves only delta from previous value.
+ */
+goog.structs.InversionMap.prototype.spliceInversion = function(
+ rangeArray, valueArray, opt_delta) {
+ // By building another inversion map, we build the arrays that we need
+ // to splice in.
+ var otherMap = new goog.structs.InversionMap(
+ rangeArray, valueArray, opt_delta);
+
+ // Figure out where to splice those arrays.
+ var startRange = otherMap.rangeArray[0];
+ var endRange =
+ (/** @type {number} */ goog.array.peek(otherMap.rangeArray));
+ var startSplice = this.getLeast(startRange);
+ var endSplice = this.getLeast(endRange);
+
+ // The inversion map works by storing the start points of ranges...
+ if (startRange != this.rangeArray[startSplice]) {
+ // ...if we're splicing in a start point that isn't already here,
+ // then we need to insert it after the insertion point.
+ startSplice++;
+ } // otherwise we overwrite the insertion point.
+
+ var spliceLength = endSplice - startSplice + 1;
+ goog.partial(goog.array.splice, this.rangeArray, startSplice,
+ spliceLength).apply(null, otherMap.rangeArray);
+ goog.partial(goog.array.splice, this.values, startSplice,
+ spliceLength).apply(null, otherMap.values);
+};
+
+
+/**
+ * Gets the value corresponding to a number from the inversion map.
+ * @param {number} intKey The number for which value needs to be retrieved
+ * from inversion map.
+ * @return {*} Value retrieved from inversion map; null if not found.
+ */
+goog.structs.InversionMap.prototype.at = function(intKey) {
+ var index = this.getLeast(intKey);
+ if (index < 0) {
+ return null;
+ }
+ return this.values[index];
+};
+
+
+/**
+ * Gets the largest index such that rangeArray[index] <= intKey from the
+ * inversion map.
+ * @param {number} intKey The probe for which rangeArray is searched.
+ * @return {number} Largest index such that rangeArray[index] <= intKey.
+ * @protected
+ */
+goog.structs.InversionMap.prototype.getLeast = function(intKey) {
+ var arr = this.rangeArray;
+ var low = 0;
+ var high = arr.length;
+ while (high - low > 8) {
+ var mid = (high + low) >> 1;
+ if (arr[mid] <= intKey) {
+ low = mid;
+ } else {
+ high = mid;
+ }
+ }
+ for (; low < high; ++low) {
+ if (intKey < arr[low]) {
+ break;
+ }
+ }
+ return low - 1;
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/inversionmap_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/inversionmap_test.html.svn-base
new file mode 100644
index 0000000..d461edf
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/inversionmap_test.html.svn-base
@@ -0,0 +1,157 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2008 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs.InversionMap</title>
+<script type="text/javascript" src="../base.js"></script>
+<script type="text/javascript">
+ goog.require('goog.structs.InversionMap');
+ goog.require('goog.testing.jsunit');
+</script>
+</head>
+<body>
+<script type="text/javascript">
+ function testInversionWithDelta() {
+ var alphabetNames = new goog.structs.InversionMap(
+ [ 0, 97, 1, 1, 1, 20, 1, 1, 1 ],
+ [ null,
+ 'LATIN SMALL LETTER A',
+ 'LATIN SMALL LETTER B',
+ 'LATIN SMALL LETTER C',
+ null,
+ 'LATIN SMALL LETTER X',
+ 'LATIN SMALL LETTER Y',
+ 'LATIN SMALL LETTER Z',
+ null ],
+ true);
+
+ assertEquals('LATIN SMALL LETTER A', alphabetNames.at(97));
+ assertEquals('LATIN SMALL LETTER Y', alphabetNames.at(121));
+ assertEquals(null, alphabetNames.at(140));
+ assertEquals(null, alphabetNames.at(0));
+ }
+
+ function testInversionWithoutDelta() {
+ var alphabetNames = new goog.structs.InversionMap(
+ [ 0, 97, 98, 99, 100, 120, 121, 122, 123 ],
+ [ null,
+ 'LATIN SMALL LETTER A',
+ 'LATIN SMALL LETTER B',
+ 'LATIN SMALL LETTER C',
+ null,
+ 'LATIN SMALL LETTER X',
+ 'LATIN SMALL LETTER Y',
+ 'LATIN SMALL LETTER Z',
+ null ],
+ false);
+
+ assertEquals('LATIN SMALL LETTER A', alphabetNames.at(97));
+ assertEquals('LATIN SMALL LETTER Y', alphabetNames.at(121));
+ assertEquals(null, alphabetNames.at(140));
+ assertEquals(null, alphabetNames.at(0));
+ }
+
+ function testInversionWithoutDeltaNoOpt() {
+ var alphabetNames = new goog.structs.InversionMap(
+ [ 0, 97, 98, 99, 100, 120, 121, 122, 123 ],
+ [ null,
+ 'LATIN SMALL LETTER A',
+ 'LATIN SMALL LETTER B',
+ 'LATIN SMALL LETTER C',
+ null,
+ 'LATIN SMALL LETTER X',
+ 'LATIN SMALL LETTER Y',
+ 'LATIN SMALL LETTER Z',
+ null ]);
+
+ assertEquals('LATIN SMALL LETTER A', alphabetNames.at(97));
+ assertEquals('LATIN SMALL LETTER Y', alphabetNames.at(121));
+ assertEquals(null, alphabetNames.at(140));
+ assertEquals(null, alphabetNames.at(0));
+ }
+
+ function testInversionMapSplice1() {
+ var alphabetNames = newAsciiMap();
+ alphabetNames.spliceInversion(
+ [ 99, 105, 114 ], [ 'XXX', 'YYY', 'ZZZ' ]);
+ assertEquals('LATIN SMALL LETTER B', alphabetNames.at(98));
+ assertEquals('XXX', alphabetNames.at(100));
+ assertEquals('ZZZ', alphabetNames.at(114));
+ assertEquals('ZZZ', alphabetNames.at(119));
+ assertEquals('LATIN SMALL LETTER X', alphabetNames.at(120));
+ }
+
+ function testInversionMapSplice2() {
+ var alphabetNames = newAsciiMap();
+ alphabetNames.spliceInversion(
+ [ 105, 114, 121 ], [ 'XXX', 'YYY', 'ZZZ' ]);
+ assertEquals(null, alphabetNames.at(104));
+ assertEquals('XXX', alphabetNames.at(105));
+ assertEquals('YYY', alphabetNames.at(120));
+ assertEquals('ZZZ', alphabetNames.at(121));
+ assertEquals('LATIN SMALL LETTER Z', alphabetNames.at(122));
+ }
+
+ function testInversionMapSplice3() {
+ var alphabetNames = newAsciiMap();
+ alphabetNames.spliceInversion(
+ [ 98, 99 ], [ 'CHANGED LETTER B', 'CHANGED LETTER C' ]);
+ assertEquals('LATIN SMALL LETTER A', alphabetNames.at(97));
+ assertEquals('CHANGED LETTER B', alphabetNames.at(98));
+ assertEquals('CHANGED LETTER C', alphabetNames.at(99));
+ assertEquals('LATIN SMALL LETTER D', alphabetNames.at(100));
+ assertEquals(null, alphabetNames.at(101));
+ }
+
+ function testInversionMapSplice4() {
+ var alphabetNames = newAsciiMap();
+ alphabetNames.spliceInversion(
+ [ 98, 1 ], [ 'CHANGED LETTER B', 'CHANGED LETTER C' ],
+ true /* delta mode */);
+ assertEquals('LATIN SMALL LETTER A', alphabetNames.at(97));
+ assertEquals('CHANGED LETTER B', alphabetNames.at(98));
+ assertEquals('CHANGED LETTER C', alphabetNames.at(99));
+ assertEquals('LATIN SMALL LETTER D', alphabetNames.at(100));
+ assertEquals(null, alphabetNames.at(101));
+ }
+
+ function testInversionMapSplice5() {
+ var map = new goog.structs.InversionMap(
+ [0, 97, 98, 99],
+ [null,
+ 'LATIN SMALL LETTER A',
+ 'LATIN SMALL LETTER B',
+ 'LATIN SMALL LETTER C']);
+ map.spliceInversion(
+ [98], ['CHANGED LETTER B']);
+ assertEquals('LATIN SMALL LETTER A', map.at(97));
+ assertEquals('CHANGED LETTER B', map.at(98));
+ assertEquals('LATIN SMALL LETTER C', map.at(99));
+
+ assertArrayEquals([0, 97, 98, 99], map.rangeArray);
+ }
+
+ function newAsciiMap() {
+ return new goog.structs.InversionMap(
+ [ 0, 97, 98, 99, 100, 101, 120, 121, 122, 123 ],
+ [ null,
+ 'LATIN SMALL LETTER A',
+ 'LATIN SMALL LETTER B',
+ 'LATIN SMALL LETTER C',
+ 'LATIN SMALL LETTER D',
+ null,
+ 'LATIN SMALL LETTER X',
+ 'LATIN SMALL LETTER Y',
+ 'LATIN SMALL LETTER Z',
+ null ]);
+ }
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/linkedmap.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/linkedmap.js.svn-base
new file mode 100644
index 0000000..bfaf230
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/linkedmap.js.svn-base
@@ -0,0 +1,472 @@
+// Copyright 2007 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview A LinkedMap data structure that is accessed using key/value
+ * pairs like an ordinary Map, but which guarantees a consistent iteration
+ * order over its entries. The iteration order is either insertion order (the
+ * default) or ordered from most recent to least recent use. By setting a fixed
+ * size, the LRU version of the LinkedMap makes an effective object cache. This
+ * data structure is similar to Java's LinkedHashMap.
+ *
+ */
+
+
+goog.provide('goog.structs.LinkedMap');
+
+goog.require('goog.structs.Map');
+
+
+
+/**
+ * Class for a LinkedMap datastructure, which combines O(1) map access for
+ * key/value pairs with a linked list for a consistent iteration order. Sample
+ * usage:
+ *
+ * <pre>
+ * var m = new LinkedMap();
+ * m.set('param1', 'A');
+ * m.set('param2', 'B');
+ * m.set('param3', 'C');
+ * alert(m.getKeys()); // param1, param2, param3
+ *
+ * var c = new LinkedMap(5, true);
+ * for (var i = 0; i < 10; i++) {
+ * c.set('entry' + i, false);
+ * }
+ * alert(c.getKeys()); // entry9, entry8, entry7, entry6, entry5
+ *
+ * c.set('entry5', true);
+ * c.set('entry1', false);
+ * alert(c.getKeys()); // entry1, entry5, entry9, entry8, entry7
+ * </pre>
+ *
+ * @param {number=} opt_maxCount The maximum number of objects to store in the
+ * LinkedMap. If unspecified or 0, there is no maximum.
+ * @param {boolean=} opt_cache When set, the LinkedMap stores items in order
+ * from most recently used to least recently used, instead of insertion
+ * order.
+ * @constructor
+ */
+goog.structs.LinkedMap = function(opt_maxCount, opt_cache) {
+ /**
+ * The maximum number of entries to allow, or null if there is no limit.
+ * @type {?number}
+ * @private
+ */
+ this.maxCount_ = opt_maxCount || null;
+
+ /**
+ * @type {boolean}
+ * @private
+ */
+ this.cache_ = !!opt_cache;
+
+ this.map_ = new goog.structs.Map();
+
+ this.head_ = new goog.structs.LinkedMap.Node_('', undefined);
+ this.head_.next = this.head_.prev = this.head_;
+};
+
+
+/**
+ * Finds a node and updates it to be the most recently used.
+ * @param {string} key The key of the node.
+ * @return {goog.structs.LinkedMap.Node_} The node or null if not found.
+ * @private
+ */
+goog.structs.LinkedMap.prototype.findAndMoveToTop_ = function(key) {
+ var node = /** @type {goog.structs.LinkedMap.Node_} */ (this.map_.get(key));
+ if (node) {
+ if (this.cache_) {
+ node.remove();
+ this.insert_(node);
+ }
+ }
+ return node;
+};
+
+
+/**
+ * Retrieves the value for a given key. If this is a caching LinkedMap, the
+ * entry will become the most recently used.
+ * @param {string} key The key to retrieve the value for.
+ * @param {*=} opt_val A default value that will be returned if the key is
+ * not found, defaults to undefined.
+ * @return {*} The retrieved value.
+ */
+goog.structs.LinkedMap.prototype.get = function(key, opt_val) {
+ var node = this.findAndMoveToTop_(key);
+ return node ? node.value : opt_val;
+};
+
+
+/**
+ * Retrieves the value for a given key without updating the entry to be the
+ * most recently used.
+ * @param {string} key The key to retrieve the value for.
+ * @param {*=} opt_val A default value that will be returned if the key is
+ * not found.
+ * @return {*} The retrieved value.
+ */
+goog.structs.LinkedMap.prototype.peekValue = function(key, opt_val) {
+ var node = this.map_.get(key);
+ return node ? node.value : opt_val;
+};
+
+
+/**
+ * Sets a value for a given key. If this is a caching LinkedMap, this entry
+ * will become the most recently used.
+ * @param {string} key The key to retrieve the value for.
+ * @param {*} value A default value that will be returned if the key is
+ * not found.
+ */
+goog.structs.LinkedMap.prototype.set = function(key, value) {
+ var node = this.findAndMoveToTop_(key);
+ if (node) {
+ node.value = value;
+ } else {
+ node = new goog.structs.LinkedMap.Node_(key, value);
+ this.map_.set(key, node);
+ this.insert_(node);
+ }
+};
+
+
+/**
+ * Returns the value of the first node without making any modifications.
+ * @return {*} The value of the first node or undefined if the map is empty.
+ */
+goog.structs.LinkedMap.prototype.peek = function() {
+ return this.head_.next.value;
+};
+
+
+/**
+ * Returns the value of the last node without making any modifications.
+ * @return {*} The value of the last node or undefined if the map is empty.
+ */
+goog.structs.LinkedMap.prototype.peekLast = function() {
+ return this.head_.prev.value;
+};
+
+
+/**
+ * Removes the first node from the list and returns its value.
+ * @return {*} The value of the popped node, or undefined if the map was empty.
+ */
+goog.structs.LinkedMap.prototype.shift = function() {
+ return this.popNode_(this.head_.next);
+};
+
+
+/**
+ * Removes the last node from the list and returns its value.
+ * @return {*} The value of the popped node, or undefined if the map was empty.
+ */
+goog.structs.LinkedMap.prototype.pop = function() {
+ return this.popNode_(this.head_.prev);
+};
+
+
+/**
+ * Removes a value from the LinkedMap based on its key.
+ * @param {string} key The key to remove.
+ * @return {boolean} True if the entry was removed, false if the key was not
+ * found.
+ */
+goog.structs.LinkedMap.prototype.remove = function(key) {
+ var node = /** @type {goog.structs.LinkedMap.Node_} */ (this.map_.get(key));
+ if (node) {
+ this.removeNode(node);
+ return true;
+ }
+ return false;
+};
+
+
+/**
+ * Removes a node from the {@code LinkedMap}. It can be overridden to do
+ * further cleanup such as disposing of the node value.
+ * @param {!goog.structs.LinkedMap.Node_} node The node to remove.
+ * @protected
+ */
+goog.structs.LinkedMap.prototype.removeNode = function(node) {
+ node.remove();
+ this.map_.remove(node.key);
+};
+
+
+/**
+ * @return {number} The number of items currently in the LinkedMap.
+ */
+goog.structs.LinkedMap.prototype.getCount = function() {
+ return this.map_.getCount();
+};
+
+
+/**
+ * @return {boolean} True if the cache is empty, false if it contains any items.
+ */
+goog.structs.LinkedMap.prototype.isEmpty = function() {
+ return this.map_.isEmpty();
+};
+
+
+/**
+ * Sets the maximum number of entries allowed in this object, truncating any
+ * excess objects if necessary.
+ * @param {number} maxCount The new maximum number of entries to allow.
+ */
+goog.structs.LinkedMap.prototype.setMaxCount = function(maxCount) {
+ this.maxCount_ = maxCount || null;
+ if (this.maxCount_ != null) {
+ this.truncate_(this.maxCount_);
+ }
+};
+
+
+/**
+ * @return {Array.<string>} The list of the keys in the appropriate order for
+ * this LinkedMap.
+ */
+goog.structs.LinkedMap.prototype.getKeys = function() {
+ return this.map(function(val, key) {
+ return key;
+ });
+};
+
+
+/**
+ * @return {!Array} The list of the values in the appropriate order for
+ * this LinkedMap.
+ */
+goog.structs.LinkedMap.prototype.getValues = function() {
+ return this.map(function(val, key) {
+ return val;
+ });
+};
+
+
+/**
+ * Tests whether a provided value is currently in the LinkedMap. This does not
+ * affect item ordering in cache-style LinkedMaps.
+ * @param {Object} value The value to check for.
+ * @return {boolean} Whether the value is in the LinkedMap.
+ */
+goog.structs.LinkedMap.prototype.contains = function(value) {
+ return this.some(function(el) {
+ return el == value;
+ });
+};
+
+
+/**
+ * Tests whether a provided key is currently in the LinkedMap. This does not
+ * affect item ordering in cache-style LinkedMaps.
+ * @param {string} key The key to check for.
+ * @return {boolean} Whether the key is in the LinkedMap.
+ */
+goog.structs.LinkedMap.prototype.containsKey = function(key) {
+ return this.map_.containsKey(key);
+};
+
+
+/**
+ * Removes all entries in this object.
+ */
+goog.structs.LinkedMap.prototype.clear = function() {
+ this.truncate_(0);
+};
+
+
+/**
+ * Calls a function on each item in the LinkedMap.
+ *
+ * @see goog.structs.forEach
+ * @param {Function} f The function to call for each item. The function takes
+ * three arguments: the value, the key, and the LinkedMap.
+ * @param {Object=} opt_obj The object context to use as "this" for the
+ * function.
+ */
+goog.structs.LinkedMap.prototype.forEach = function(f, opt_obj) {
+ for (var n = this.head_.next; n != this.head_; n = n.next) {
+ f.call(opt_obj, n.value, n.key, this);
+ }
+};
+
+
+/**
+ * Calls a function on each item in the LinkedMap and returns the results of
+ * those calls in an array.
+ *
+ * @see goog.structs.map
+ * @param {!Function} f The function to call for each item. The function takes
+ * three arguments: the value, the key, and the LinkedMap.
+ * @param {Object=} opt_obj The object context to use as "this" for the
+ * function.
+ * @return {!Array} The results of the function calls for each item in the
+ * LinkedMap.
+ */
+goog.structs.LinkedMap.prototype.map = function(f, opt_obj) {
+ var rv = [];
+ for (var n = this.head_.next; n != this.head_; n = n.next) {
+ rv.push(f.call(opt_obj, n.value, n.key, this));
+ }
+ return rv;
+};
+
+
+/**
+ * Calls a function on each item in the LinkedMap and returns true if any of
+ * those function calls returns a true-like value.
+ *
+ * @see goog.structs.some
+ * @param {Function} f The function to call for each item. The function takes
+ * three arguments: the value, the key, and the LinkedMap, and returns a
+ * boolean.
+ * @param {Object=} opt_obj The object context to use as "this" for the
+ * function.
+ * @return {boolean} Whether f evaluates to true for at least one item in the
+ * LinkedMap.
+ */
+goog.structs.LinkedMap.prototype.some = function(f, opt_obj) {
+ for (var n = this.head_.next; n != this.head_; n = n.next) {
+ if (f.call(opt_obj, n.value, n.key, this)) {
+ return true;
+ }
+ }
+ return false;
+};
+
+
+/**
+ * Calls a function on each item in the LinkedMap and returns true only if every
+ * function call returns a true-like value.
+ *
+ * @see goog.structs.some
+ * @param {Function} f The function to call for each item. The function takes
+ * three arguments: the value, the key, and the Cache, and returns a
+ * boolean.
+ * @param {Object=} opt_obj The object context to use as "this" for the
+ * function.
+ * @return {boolean} Whether f evaluates to true for every item in the Cache.
+ */
+goog.structs.LinkedMap.prototype.every = function(f, opt_obj) {
+ for (var n = this.head_.next; n != this.head_; n = n.next) {
+ if (!f.call(opt_obj, n.value, n.key, this)) {
+ return false;
+ }
+ }
+ return true;
+};
+
+
+/**
+ * Appends a node to the list. LinkedMap in cache mode adds new nodes to
+ * the head of the list, otherwise they are appended to the tail. If there is a
+ * maximum size, the list will be truncated if necessary.
+ *
+ * @param {goog.structs.LinkedMap.Node_} node The item to insert.
+ * @private
+ */
+goog.structs.LinkedMap.prototype.insert_ = function(node) {
+ if (this.cache_) {
+ node.next = this.head_.next;
+ node.prev = this.head_;
+
+ this.head_.next = node;
+ node.next.prev = node;
+ } else {
+ node.prev = this.head_.prev;
+ node.next = this.head_;
+
+ this.head_.prev = node;
+ node.prev.next = node;
+ }
+
+ if (this.maxCount_ != null) {
+ this.truncate_(this.maxCount_);
+ }
+};
+
+
+/**
+ * Removes elements from the LinkedMap if the given count has been exceeded.
+ * In cache mode removes nodes from the tail of the list. Otherwise removes
+ * nodes from the head.
+ * @param {number} count Number of elements to keep.
+ * @private
+ */
+goog.structs.LinkedMap.prototype.truncate_ = function(count) {
+ for (var i = this.map_.getCount(); i > count; i--) {
+ this.removeNode(this.cache_ ? this.head_.prev : this.head_.next);
+ }
+};
+
+
+/**
+ * Removes the node from the LinkedMap if it is not the head, and returns
+ * the node's value.
+ * @param {!goog.structs.LinkedMap.Node_} node The item to remove.
+ * @return {*} The value of the popped node.
+ * @private
+ */
+goog.structs.LinkedMap.prototype.popNode_ = function(node) {
+ if (this.head_ != node) {
+ this.removeNode(node);
+ }
+ return node.value;
+};
+
+
+
+/**
+ * Internal class for a doubly-linked list node containing a key/value pair.
+ * @param {string} key The key.
+ * @param {*} value The value.
+ * @constructor
+ * @private
+ */
+goog.structs.LinkedMap.Node_ = function(key, value) {
+ this.key = key;
+ this.value = value;
+};
+
+
+/**
+ * The next node in the list.
+ * @type {!goog.structs.LinkedMap.Node_}
+ */
+goog.structs.LinkedMap.Node_.prototype.next;
+
+
+/**
+ * The previous node in the list.
+ * @type {!goog.structs.LinkedMap.Node_}
+ */
+goog.structs.LinkedMap.Node_.prototype.prev;
+
+
+/**
+ * Causes this node to remove itself from the list.
+ */
+goog.structs.LinkedMap.Node_.prototype.remove = function() {
+ this.prev.next = this.next;
+ this.next.prev = this.prev;
+
+ delete this.prev;
+ delete this.next;
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/linkedmap_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/linkedmap_test.html.svn-base
new file mode 100644
index 0000000..d20faac
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/linkedmap_test.html.svn-base
@@ -0,0 +1,300 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2006 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs.LinkedMap</title>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.structs.LinkedMap');
+ goog.require('goog.testing.jsunit');
+ goog.require('goog.testing.recordFunction');
+</script>
+</head>
+<body>
+<script>
+
+function fillLinkedMap(m) {
+ m.set('a', 0);
+ m.set('b', 1);
+ m.set('c', 2);
+ m.set('d', 3);
+}
+
+var someObj = {};
+
+function testLinkedMap() {
+ var m = new goog.structs.LinkedMap();
+ fillLinkedMap(m);
+
+ assertArrayEquals(['a', 'b', 'c', 'd'], m.getKeys());
+ assertArrayEquals([0, 1, 2, 3], m.getValues());
+}
+
+function testMaxSizeLinkedMap() {
+ var m = new goog.structs.LinkedMap(3);
+ fillLinkedMap(m);
+
+ assertArrayEquals(['b', 'c', 'd'], m.getKeys());
+ assertArrayEquals([1, 2, 3], m.getValues());
+}
+
+function testLruLinkedMap() {
+ var m = new goog.structs.LinkedMap(undefined, true);
+ fillLinkedMap(m);
+
+ assertArrayEquals(['d', 'c', 'b', 'a'], m.getKeys());
+ assertArrayEquals([3, 2, 1, 0], m.getValues());
+
+ m.get('a');
+ assertArrayEquals(['a', 'd', 'c', 'b'], m.getKeys());
+ assertArrayEquals([0, 3, 2, 1], m.getValues());
+
+ m.set('b', 4);
+ assertArrayEquals(['b', 'a', 'd', 'c'], m.getKeys());
+ assertArrayEquals([4, 0, 3, 2], m.getValues());
+}
+
+function testMaxSizeLruLinkedMap() {
+ var m = new goog.structs.LinkedMap(3, true);
+ fillLinkedMap(m);
+
+ assertArrayEquals(['d', 'c', 'b'], m.getKeys());
+ assertArrayEquals([3, 2, 1], m.getValues());
+
+ m.get('c');
+ assertArrayEquals(['c', 'd', 'b'], m.getKeys());
+ assertArrayEquals([2, 3, 1], m.getValues());
+
+ m.set('d', 4);
+ assertArrayEquals(['d', 'c', 'b'], m.getKeys());
+ assertArrayEquals([4, 2, 1], m.getValues());
+}
+
+function testGetCount() {
+ var m = new goog.structs.LinkedMap();
+ assertEquals(0, m.getCount());
+ m.set('a', 0);
+ assertEquals(1, m.getCount());
+ m.set('a', 1);
+ assertEquals(1, m.getCount());
+ m.set('b', 2);
+ assertEquals(2, m.getCount());
+ m.remove('a');
+ assertEquals(1, m.getCount());
+}
+
+function testIsEmpty() {
+ var m = new goog.structs.LinkedMap();
+ assertTrue(m.isEmpty());
+ m.set('a', 0);
+ assertFalse(m.isEmpty());
+ m.remove('a');
+ assertTrue(m.isEmpty());
+}
+
+function testSetMaxCount() {
+ var m = new goog.structs.LinkedMap(3);
+ fillLinkedMap(m);
+ assertEquals(3, m.getCount());
+
+ m.setMaxCount(5);
+ m.set('e', 5);
+ m.set('f', 6);
+ m.set('g', 7);
+ assertEquals(5, m.getCount());
+
+ m.setMaxCount(4);
+ assertEquals(4, m.getCount());
+
+ m.setMaxCount(0);
+ m.set('h', 8);
+ m.set('i', 9);
+ m.set('j', 10);
+ assertEquals(7, m.getCount());
+}
+
+function testClear() {
+ var m = new goog.structs.LinkedMap();
+ fillLinkedMap(m);
+ m.clear();
+ assertTrue(m.isEmpty());
+}
+
+function testForEach() {
+ var m = new goog.structs.LinkedMap();
+ fillLinkedMap(m);
+
+ m.forEach(function(val, key, linkedMap) {
+ linkedMap.set(key, val * 2);
+ assertEquals('forEach should run in provided context.', someObj, this);
+ }, someObj);
+
+ assertArrayEquals(['a', 'b', 'c', 'd'], m.getKeys());
+ assertArrayEquals([0, 2, 4, 6], m.getValues());
+}
+
+function testMap() {
+ var m = new goog.structs.LinkedMap();
+ fillLinkedMap(m);
+
+ var result = m.map(function(val, key, linkedMap) {
+ assertEquals('The LinkedMap object should get passed in', m, linkedMap);
+ assertEquals('map should run in provided context', someObj, this);
+ return key + val;
+ }, someObj);
+
+ assertArrayEquals(['a0', 'b1', 'c2', 'd3'], result);
+}
+
+function testSome() {
+ var m = new goog.structs.LinkedMap();
+ fillLinkedMap(m);
+
+ var result = m.some(function(val, key, linkedMap) {
+ assertEquals('The LinkedMap object should get passed in', m, linkedMap);
+ assertEquals('map should run in provided context', someObj, this);
+ return val > 2;
+ }, someObj);
+
+ assertTrue(result);
+ assertFalse(m.some(function(val) {return val > 3}));
+
+ assertTrue(m.some(function(val, key) {return key == 'c';}));
+ assertFalse(m.some(function(val, key) {return key == 'e';}));
+}
+
+function testEvery() {
+ var m = new goog.structs.LinkedMap();
+ fillLinkedMap(m);
+
+ var result = m.every(function(val, key, linkedMap) {
+ assertEquals('The LinkedMap object should get passed in', m, linkedMap);
+ assertEquals('map should run in provided context', someObj, this);
+ return val < 5;
+ }, someObj);
+
+ assertTrue(result);
+ assertFalse(m.every(function(val) {return val < 2}));
+
+ assertTrue(m.every(function(val, key) {return key.length == 1;}));
+ assertFalse(m.every(function(val, key) {return key == 'b';}));
+}
+
+function testPeek() {
+ var m = new goog.structs.LinkedMap();
+ assertEquals(undefined, m.peek());
+ assertEquals(undefined, m.peekLast());
+
+ fillLinkedMap(m);
+ assertEquals(0, m.peek());
+
+ m.remove('a');
+ assertEquals(1, m.peek());
+
+ assertEquals(3, m.peekLast());
+
+ assertEquals(3, m.peekValue('d'));
+ assertEquals(1, m.peek());
+
+ m.remove('d');
+ assertEquals(2, m.peekLast());
+}
+
+function testPop() {
+ var m = new goog.structs.LinkedMap();
+ assertEquals(undefined, m.shift());
+ assertEquals(undefined, m.pop());
+
+ fillLinkedMap(m);
+ assertEquals(4, m.getCount());
+
+ assertEquals(0, m.shift());
+ assertEquals(1, m.peek());
+
+ assertEquals(3, m.pop());
+ assertEquals(2, m.peekLast());
+
+ assertEquals(2, m.getCount());
+}
+
+function testContains() {
+ var m = new goog.structs.LinkedMap();
+ fillLinkedMap(m);
+
+ assertTrue(m.contains(2));
+ assertFalse(m.contains(4));
+}
+
+function testContainsKey() {
+ var m = new goog.structs.LinkedMap();
+ fillLinkedMap(m);
+
+ assertTrue(m.containsKey('b'));
+ assertFalse(m.containsKey('elephant'));
+ assertFalse(m.containsKey('undefined'));
+}
+
+function testRemoveNodeCalls() {
+ var m = new goog.structs.LinkedMap(1);
+ m.removeNode = goog.testing.recordFunction(m.removeNode);
+
+ m.set('1', 1);
+ assertEquals('removeNode not called after adding an element', 0,
+ m.removeNode.getCallCount());
+ m.set('1', 2);
+ assertEquals('removeNode not called after updating an element', 0,
+ m.removeNode.getCallCount());
+ m.set('2', 2);
+ assertEquals('removeNode called after adding an overflowing element', 1,
+ m.removeNode.getCallCount());
+
+ m.remove('3');
+ assertEquals('removeNode not called after removing a non-existing element', 1,
+ m.removeNode.getCallCount());
+ m.remove('2');
+ assertEquals('removeNode called after removing an existing element', 2,
+ m.removeNode.getCallCount());
+
+ m.set('1', 1);
+ m.clear();
+ assertEquals('removeNode called after clearing the map', 3,
+ m.removeNode.getCallCount());
+ m.clear();
+ assertEquals('removeNode not called after clearing an empty map', 3,
+ m.removeNode.getCallCount());
+
+ m.set('1', 1);
+ m.pop();
+ assertEquals('removeNode called after calling pop', 4,
+ m.removeNode.getCallCount());
+ m.pop();
+ assertEquals('removeNode not called after calling pop on an empty map', 4,
+ m.removeNode.getCallCount());
+
+ m.set('1', 1);
+ m.shift();
+ assertEquals('removeNode called after calling shift', 5,
+ m.removeNode.getCallCount());
+ m.shift();
+ assertEquals('removeNode not called after calling shift on an empty map', 5,
+ m.removeNode.getCallCount());
+
+ m.setMaxCount(2);
+ m.set('1', 1);
+ m.set('2', 2);
+ assertEquals('removeNode not called after increasing the maximum map size', 5,
+ m.removeNode.getCallCount());
+ m.setMaxCount(1);
+ assertEquals('removeNode called after decreasing the maximum map size', 6,
+ m.removeNode.getCallCount());
+}
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/map.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/map.js.svn-base
new file mode 100644
index 0000000..f48d81b
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/map.js.svn-base
@@ -0,0 +1,448 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Datastructure: Hash Map.
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ * @author jonp@google.com (Jon Perlow) Optimized for IE6
+ *
+ * This file contains an implementation of a Map structure. It implements a lot
+ * of the methods used in goog.structs so those functions work on hashes. For
+ * convenience with common usage the methods accept any type for the key, though
+ * internally they will be cast to strings.
+ */
+
+
+goog.provide('goog.structs.Map');
+
+goog.require('goog.iter.Iterator');
+goog.require('goog.iter.StopIteration');
+goog.require('goog.object');
+goog.require('goog.structs');
+
+
+
+/**
+ * Class for Hash Map datastructure.
+ * @param {*=} opt_map Map or Object to initialize the map with.
+ * @param {...*} var_args If 2 or more arguments are present then they
+ * will be used as key-value pairs.
+ * @constructor
+ */
+goog.structs.Map = function(opt_map, var_args) {
+
+ /**
+ * Underlying JS object used to implement the map.
+ * @type {!Object}
+ * @private
+ */
+ this.map_ = {};
+
+ /**
+ * An array of keys. This is necessary for two reasons:
+ * 1. Iterating the keys using for (var key in this.map_) allocates an
+ * object for every key in IE which is really bad for IE6 GC perf.
+ * 2. Without a side data structure, we would need to escape all the keys
+ * as that would be the only way we could tell during iteration if the
+ * key was an internal key or a property of the object.
+ *
+ * This array can contain deleted keys so it's necessary to check the map
+ * as well to see if the key is still in the map (this doesn't require a
+ * memory allocation in IE).
+ * @type {!Array.<string>}
+ * @private
+ */
+ this.keys_ = [];
+
+ var argLength = arguments.length;
+
+ if (argLength > 1) {
+ if (argLength % 2) {
+ throw Error('Uneven number of arguments');
+ }
+ for (var i = 0; i < argLength; i += 2) {
+ this.set(arguments[i], arguments[i + 1]);
+ }
+ } else if (opt_map) {
+ this.addAll(/** @type {Object} */ (opt_map));
+ }
+};
+
+
+/**
+ * The number of key value pairs in the map.
+ * @private
+ * @type {number}
+ */
+goog.structs.Map.prototype.count_ = 0;
+
+
+/**
+ * Version used to detect changes while iterating.
+ * @private
+ * @type {number}
+ */
+goog.structs.Map.prototype.version_ = 0;
+
+
+/**
+ * @return {number} The number of key-value pairs in the map.
+ */
+goog.structs.Map.prototype.getCount = function() {
+ return this.count_;
+};
+
+
+/**
+ * Returns the values of the map.
+ * @return {!Array} The values in the map.
+ */
+goog.structs.Map.prototype.getValues = function() {
+ this.cleanupKeysArray_();
+
+ var rv = [];
+ for (var i = 0; i < this.keys_.length; i++) {
+ var key = this.keys_[i];
+ rv.push(this.map_[key]);
+ }
+ return rv;
+};
+
+
+/**
+ * Returns the keys of the map.
+ * @return {!Array.<string>} Array of string values.
+ */
+goog.structs.Map.prototype.getKeys = function() {
+ this.cleanupKeysArray_();
+ return /** @type {!Array.<string>} */ (this.keys_.concat());
+};
+
+
+/**
+ * Whether the map contains the given key.
+ * @param {*} key The key to check for.
+ * @return {boolean} Whether the map contains the key.
+ */
+goog.structs.Map.prototype.containsKey = function(key) {
+ return goog.structs.Map.hasKey_(this.map_, key);
+};
+
+
+/**
+ * Whether the map contains the given value. This is O(n).
+ * @param {*} val The value to check for.
+ * @return {boolean} Whether the map contains the value.
+ */
+goog.structs.Map.prototype.containsValue = function(val) {
+ for (var i = 0; i < this.keys_.length; i++) {
+ var key = this.keys_[i];
+ if (goog.structs.Map.hasKey_(this.map_, key) && this.map_[key] == val) {
+ return true;
+ }
+ }
+ return false;
+};
+
+
+/**
+ * Whether this map is equal to the argument map.
+ * @param {goog.structs.Map} otherMap The map against which to test equality.
+ * @param {function(*, *) : boolean=} opt_equalityFn Optional equality function
+ * to test equality of values. If not specified, this will test whether
+ * the values contained in each map are identical objects.
+ * @return {boolean} Whether the maps are equal.
+ */
+goog.structs.Map.prototype.equals = function(otherMap, opt_equalityFn) {
+ if (this === otherMap) {
+ return true;
+ }
+
+ if (this.count_ != otherMap.getCount()) {
+ return false;
+ }
+
+ var equalityFn = opt_equalityFn || goog.structs.Map.defaultEquals;
+
+ this.cleanupKeysArray_();
+ for (var key, i = 0; key = this.keys_[i]; i++) {
+ if (!equalityFn(this.get(key), otherMap.get(key))) {
+ return false;
+ }
+ }
+
+ return true;
+};
+
+
+/**
+ * Default equality test for values.
+ * @param {*} a The first value.
+ * @param {*} b The second value.
+ * @return {boolean} Whether a and b reference the same object.
+ */
+goog.structs.Map.defaultEquals = function(a, b) {
+ return a === b;
+};
+
+
+/**
+ * @return {boolean} Whether the map is empty.
+ */
+goog.structs.Map.prototype.isEmpty = function() {
+ return this.count_ == 0;
+};
+
+
+/**
+ * Removes all key-value pairs from the map.
+ */
+goog.structs.Map.prototype.clear = function() {
+ this.map_ = {};
+ this.keys_.length = 0;
+ this.count_ = 0;
+ this.version_ = 0;
+};
+
+
+/**
+ * Removes a key-value pair based on the key. This is O(logN) amortized due to
+ * updating the keys array whenever the count becomes half the size of the keys
+ * in the keys array.
+ * @param {*} key The key to remove.
+ * @return {boolean} Whether object was removed.
+ */
+goog.structs.Map.prototype.remove = function(key) {
+ if (goog.structs.Map.hasKey_(this.map_, key)) {
+ delete this.map_[key];
+ this.count_--;
+ this.version_++;
+
+ // clean up the keys array if the threshhold is hit
+ if (this.keys_.length > 2 * this.count_) {
+ this.cleanupKeysArray_();
+ }
+
+ return true;
+ }
+ return false;
+};
+
+
+/**
+ * Cleans up the temp keys array by removing entries that are no longer in the
+ * map.
+ * @private
+ */
+goog.structs.Map.prototype.cleanupKeysArray_ = function() {
+ if (this.count_ != this.keys_.length) {
+ // First remove keys that are no longer in the map.
+ var srcIndex = 0;
+ var destIndex = 0;
+ while (srcIndex < this.keys_.length) {
+ var key = this.keys_[srcIndex];
+ if (goog.structs.Map.hasKey_(this.map_, key)) {
+ this.keys_[destIndex++] = key;
+ }
+ srcIndex++;
+ }
+ this.keys_.length = destIndex;
+ }
+
+ if (this.count_ != this.keys_.length) {
+ // If the count still isn't correct, that means we have duplicates. This can
+ // happen when the same key is added and removed multiple times. Now we have
+ // to allocate one extra Object to remove the duplicates. This could have
+ // been done in the first pass, but in the common case, we can avoid
+ // allocating an extra object by only doing this when necessary.
+ var seen = {};
+ var srcIndex = 0;
+ var destIndex = 0;
+ while (srcIndex < this.keys_.length) {
+ var key = this.keys_[srcIndex];
+ if (!(goog.structs.Map.hasKey_(seen, key))) {
+ this.keys_[destIndex++] = key;
+ seen[key] = 1;
+ }
+ srcIndex++;
+ }
+ this.keys_.length = destIndex;
+ }
+};
+
+
+/**
+ * Returns the value for the given key. If the key is not found and the default
+ * value is not given this will return {@code undefined}.
+ * @param {*} key The key to get the value for.
+ * @param {*=} opt_val The value to return if no item is found for the given
+ * key, defaults to undefined.
+ * @return {*} The value for the given key.
+ */
+goog.structs.Map.prototype.get = function(key, opt_val) {
+ if (goog.structs.Map.hasKey_(this.map_, key)) {
+ return this.map_[key];
+ }
+ return opt_val;
+};
+
+
+/**
+ * Adds a key-value pair to the map.
+ * @param {*} key The key.
+ * @param {*} value The value to add.
+ */
+goog.structs.Map.prototype.set = function(key, value) {
+ if (!(goog.structs.Map.hasKey_(this.map_, key))) {
+ this.count_++;
+ this.keys_.push(key);
+ // Only change the version if we add a new key.
+ this.version_++;
+ }
+ this.map_[key] = value;
+};
+
+
+/**
+ * Adds multiple key-value pairs from another goog.structs.Map or Object.
+ * @param {Object} map Object containing the data to add.
+ */
+goog.structs.Map.prototype.addAll = function(map) {
+ var keys, values;
+ if (map instanceof goog.structs.Map) {
+ keys = map.getKeys();
+ values = map.getValues();
+ } else {
+ keys = goog.object.getKeys(map);
+ values = goog.object.getValues(map);
+ }
+ // we could use goog.array.forEach here but I don't want to introduce that
+ // dependency just for this.
+ for (var i = 0; i < keys.length; i++) {
+ this.set(keys[i], values[i]);
+ }
+};
+
+
+/**
+ * Clones a map and returns a new map.
+ * @return {!goog.structs.Map} A new map with the same key-value pairs.
+ */
+goog.structs.Map.prototype.clone = function() {
+ return new goog.structs.Map(this);
+};
+
+
+/**
+ * Returns a new map in which all the keys and values are interchanged
+ * (keys become values and values become keys). If multiple keys map to the
+ * same value, the chosen transposed value is implementation-dependent.
+ *
+ * It acts very similarly to {goog.object.transpose(Object)}.
+ *
+ * @return {!goog.structs.Map} The transposed map.
+ */
+goog.structs.Map.prototype.transpose = function() {
+ var transposed = new goog.structs.Map();
+ for (var i = 0; i < this.keys_.length; i++) {
+ var key = this.keys_[i];
+ var value = this.map_[key];
+ transposed.set(value, key);
+ }
+
+ return transposed;
+};
+
+
+/**
+ * @return {!Object} Object representation of the map.
+ */
+goog.structs.Map.prototype.toObject = function() {
+ this.cleanupKeysArray_();
+ var obj = {};
+ for (var i = 0; i < this.keys_.length; i++) {
+ var key = this.keys_[i];
+ obj[key] = this.map_[key];
+ }
+ return obj;
+};
+
+
+/**
+ * Returns an iterator that iterates over the keys in the map. Removal of keys
+ * while iterating might have undesired side effects.
+ * @return {!goog.iter.Iterator} An iterator over the keys in the map.
+ */
+goog.structs.Map.prototype.getKeyIterator = function() {
+ return this.__iterator__(true);
+};
+
+
+/**
+ * Returns an iterator that iterates over the values in the map. Removal of
+ * keys while iterating might have undesired side effects.
+ * @return {!goog.iter.Iterator} An iterator over the values in the map.
+ */
+goog.structs.Map.prototype.getValueIterator = function() {
+ return this.__iterator__(false);
+};
+
+
+/**
+ * Returns an iterator that iterates over the values or the keys in the map.
+ * This throws an exception if the map was mutated since the iterator was
+ * created.
+ * @param {boolean=} opt_keys True to iterate over the keys. False to iterate
+ * over the values. The default value is false.
+ * @return {!goog.iter.Iterator} An iterator over the values or keys in the map.
+ */
+goog.structs.Map.prototype.__iterator__ = function(opt_keys) {
+ // Clean up keys to minimize the risk of iterating over dead keys.
+ this.cleanupKeysArray_();
+
+ var i = 0;
+ var keys = this.keys_;
+ var map = this.map_;
+ var version = this.version_;
+ var selfObj = this;
+
+ var newIter = new goog.iter.Iterator;
+ newIter.next = function() {
+ while (true) {
+ if (version != selfObj.version_) {
+ throw Error('The map has changed since the iterator was created');
+ }
+ if (i >= keys.length) {
+ throw goog.iter.StopIteration;
+ }
+ var key = keys[i++];
+ return opt_keys ? key : map[key];
+ }
+ };
+ return newIter;
+};
+
+
+/**
+ * Safe way to test for hasOwnProperty. It even allows testing for
+ * 'hasOwnProperty'.
+ * @param {Object} obj The object to test for presence of the given key.
+ * @param {*} key The key to check for.
+ * @return {boolean} Whether the object has the key.
+ * @private
+ */
+goog.structs.Map.hasKey_ = function(obj, key) {
+ return Object.prototype.hasOwnProperty.call(obj, key);
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/map_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/map_test.html.svn-base
new file mode 100644
index 0000000..a526a59
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/map_test.html.svn-base
@@ -0,0 +1,430 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2006 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs.Map</title>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.iter');
+ goog.require('goog.structs');
+ goog.require('goog.structs.Map');
+ goog.require('goog.testing.jsunit');
+</script>
+</head>
+<body>
+<script>
+
+function stringifyMap(m) {
+ var keys = goog.structs.getKeys(m);
+ var s = '';
+ for (var i = 0; i < keys.length; i++) {
+ s += keys[i] + m[keys[i]];
+ }
+ return s;
+}
+
+function getMap() {
+ var m = new goog.structs.Map;
+ m.set('a', 0);
+ m.set('b', 1);
+ m.set('c', 2);
+ m.set('d', 3);
+ return m;
+}
+
+function testGetCount() {
+ var m = getMap();
+ assertEquals('count, should be 4', m.getCount(), 4);
+ m.remove('d');
+ assertEquals('count, should be 3', m.getCount(), 3);
+}
+
+function testKeys() {
+ var m = getMap();
+ assertEquals('getKeys, The keys should be a,b,c', m.getKeys().join(','),
+ 'a,b,c,d');
+}
+
+function testValues() {
+ var m = getMap();
+ assertEquals('getValues, The values should be 0,1,2',
+ m.getValues().join(','), '0,1,2,3');
+}
+
+function testContainsKey() {
+ var m = getMap();
+ assertTrue("containsKey, Should contain the 'a' key", m.containsKey('a'));
+ assertFalse("containsKey, Should not contain the 'e' key",
+ m.containsKey('e'));
+}
+
+function testClear() {
+ var m = getMap();
+ m.clear();
+ assertTrue('cleared so it should be empty', m.isEmpty());
+ assertTrue("cleared so it should not contain 'a' key", !m.containsKey('a'));
+}
+
+function testAddAll() {
+ var m = new goog.structs.Map;
+ m.addAll({a:0,b:1,c:2,d:3});
+ assertTrue('addAll so it should not be empty', !m.isEmpty());
+ assertTrue("addAll so it should contain 'c' key", m.containsKey('c'));
+
+ var m2 = new goog.structs.Map;
+ m2.addAll(m);
+ assertTrue('addAll so it should not be empty', !m2.isEmpty());
+ assertTrue("addAll so it should contain 'c' key", m2.containsKey('c'));
+}
+
+function testConstructor() {
+ var m = getMap();
+ var m2 = new goog.structs.Map(m);
+ assertTrue('constr with Map so it should not be empty', !m2.isEmpty());
+ assertTrue("constr with Map so it should contain 'c' key",
+ m2.containsKey('c'));
+}
+
+
+function testConstructorWithVarArgs() {
+ var m = new goog.structs.Map('a', 1);
+ assertTrue('constr with var_args so it should not be empty', !m.isEmpty());
+ assertEquals('constr with var_args', 1, m.get('a'));
+
+ m = new goog.structs.Map('a', 1, 'b', 2);
+ assertTrue('constr with var_args so it should not be empty', !m.isEmpty());
+ assertEquals('constr with var_args', 1, m.get('a'));
+ assertEquals('constr with var_args', 2, m.get('b'));
+
+ assertThrows('Odd number of arguments is not allowed', function() {
+ var m = new goog.structs.Map('a', 1, 'b');
+ });
+}
+
+function testClone() {
+ var m = getMap();
+ var m2 = m.clone();
+ assertTrue('clone so it should not be empty', !m2.isEmpty());
+ assertTrue("clone so it should contain 'c' key", m2.containsKey('c'));
+}
+
+
+function testRemove() {
+ var m = new goog.structs.Map();
+ for (var i = 0; i < 1000; i++) {
+ m.set(i, 'foo');
+ }
+
+ for (var i = 0; i < 1000; i++) {
+ assertTrue(m.keys_.length <= 2 * m.getCount());
+ m.remove(i);
+ }
+ assertTrue(m.isEmpty());
+ assertEquals('', m.getKeys().join(''));
+}
+
+
+function testForEach() {
+ var m = getMap();
+ var s = '';
+ goog.structs.forEach(m, function(val, key, m2) {
+ assertNotUndefined(key);
+ assertEquals(m, m2);
+ s += key + val;
+ });
+ assertEquals(s, 'a0b1c2d3');
+}
+
+function testFilter() {
+ var m = getMap();
+
+ var m2 = goog.structs.filter(m, function (val, key, m3) {
+ assertNotUndefined(key);
+ assertEquals(m, m3);
+ return val > 1;
+ });
+ assertEquals(stringifyMap(m2), 'c2d3');
+}
+
+
+function testMap() {
+ var m = getMap();
+ var m2 = goog.structs.map(m, function (val, key, m3) {
+ assertNotUndefined(key);
+ assertEquals(m, m3);
+ return val * val;
+ });
+ assertEquals(stringifyMap(m2), 'a0b1c4d9');
+}
+
+function testSome() {
+ var m = getMap();
+ var b = goog.structs.some(m, function (val, key, m2) {
+ assertNotUndefined(key);
+ assertEquals(m, m2);
+ return val > 1;
+ });
+ assertTrue(b);
+ var b = goog.structs.some(m, function (val, key, m2) {
+ assertNotUndefined(key);
+ assertEquals(m, m2);
+ return val > 100;
+ });
+ assertFalse(b);
+}
+
+function testEvery() {
+ var m = getMap();
+ var b = goog.structs.every(m, function (val, key, m2) {
+ assertNotUndefined(key);
+ assertEquals(m, m2);
+ return val >= 0;
+ });
+ assertTrue(b);
+ b = goog.structs.every(m, function (val, key, m2) {
+ assertNotUndefined(key);
+ assertEquals(m, m2);
+ return val > 1;
+ });
+ assertFalse(b);
+}
+
+function testContainsValue() {
+ var m = getMap();
+ assertTrue(m.containsValue(3));
+ assertFalse(m.containsValue(4));
+}
+
+function testObjectProperties() {
+ var m = new goog.structs.Map;
+
+ assertEquals(m.get('toString'), undefined);
+ assertEquals(m.get('valueOf'), undefined);
+ assertEquals(m.get('eval'), undefined);
+ assertEquals(m.get('toSource'), undefined);
+ assertEquals(m.get('prototype'), undefined);
+ assertEquals(m.get(':foo'), undefined);
+
+ m.set('toString', 'once');
+ m.set('valueOf', 'upon');
+ m.set('eval', 'a');
+ m.set('toSource', 'midnight');
+ m.set('prototype', 'dreary');
+ m.set('hasOwnProperty', 'dark');
+ m.set(':foo', 'happy');
+
+ assertEquals(m.get('toString'), 'once');
+ assertEquals(m.get('valueOf'), 'upon');
+ assertEquals(m.get('eval'), 'a');
+ assertEquals(m.get('toSource'), 'midnight');
+ assertEquals(m.get('prototype'), 'dreary');
+ assertEquals(m.get('hasOwnProperty'), 'dark');
+ assertEquals(m.get(':foo'), 'happy');
+
+ var keys = m.getKeys().join(',');
+ assertEquals(keys,
+ 'toString,valueOf,eval,toSource,prototype,hasOwnProperty,:foo');
+
+ var values = m.getValues().join(',');
+ assertEquals(values, 'once,upon,a,midnight,dreary,dark,happy');
+}
+
+function testDuplicateKeys() {
+ var m = new goog.structs.Map;
+
+ m.set('a', 1);
+ m.set('b', 2);
+ m.set('c', 3);
+ m.set('d', 4);
+ m.set('e', 5);
+ m.set('f', 6);
+ assertEquals(6, m.getKeys().length);
+ m.set('foo', 1);
+ assertEquals(7, m.getKeys().length);
+ m.remove('foo');
+ assertEquals(6, m.getKeys().length);
+ m.set('foo', 2);
+ assertEquals(7, m.getKeys().length);
+ m.remove('foo');
+ m.set('foo', 3);
+ m.remove('foo');
+ m.set('foo', 4);
+ assertEquals(7, m.getKeys().length);
+}
+
+function testGetKeyIterator() {
+ var m = new goog.structs.Map;
+ m.set('a', 1);
+ m.set('b', 2);
+ m.set('c', 3);
+ m.set('d', 4);
+ m.set('e', 5);
+
+ var iter = m.getKeyIterator();
+ assertEquals('Should contain the keys', 'abcde', goog.iter.join(iter, ''));
+
+ m.remove('b');
+ m.remove('d');
+ iter = m.getKeyIterator();
+ assertEquals('Should not contain the removed keys',
+ 'ace', goog.iter.join(iter, ''));
+}
+
+function testGetValueIterator() {
+ var m = new goog.structs.Map;
+ m.set('a', 1);
+ m.set('b', 2);
+ m.set('c', 3);
+ m.set('d', 4);
+ m.set('e', 5);
+
+ var iter = m.getValueIterator();
+ assertEquals('Should contain the values', '12345', goog.iter.join(iter, ''));
+
+ m.remove('b');
+ m.remove('d');
+ iter = m.getValueIterator();
+ assertEquals('Should not contain the removed keys',
+ '135', goog.iter.join(iter, ''));
+}
+
+function testDefaultIterator() {
+ // The default iterator should behave like the value iterator
+
+ var m = new goog.structs.Map;
+ m.set('a', 1);
+ m.set('b', 2);
+ m.set('c', 3);
+ m.set('d', 4);
+ m.set('e', 5);
+
+ assertEquals('Should contain the values', '12345', goog.iter.join(m, ''));
+
+ m.remove('b');
+ m.remove('d');
+ assertEquals('Should not contain the removed keys',
+ '135', goog.iter.join(m, ''));
+}
+
+function testMutatedIterator() {
+ var message = 'The map has changed since the iterator was created';
+
+ var m = new goog.structs.Map;
+ m.set('a', 1);
+ m.set('b', 2);
+ m.set('c', 3);
+ m.set('d', 4);
+
+ var iter = m.getValueIterator();
+ m.set('e', 5);
+ var ex = assertThrows('Expected an exception since the map has changed',
+ function() {
+ iter.next();
+ });
+ assertEquals(message, ex.message);
+
+ m = new goog.structs.Map;
+ m.set('a', 1);
+ m.set('b', 2);
+ m.set('c', 3);
+ m.set('d', 4);
+
+ iter = m.getValueIterator();
+ m.remove('d');
+ var ex = assertThrows('Expected an exception since the map has changed',
+ function() {
+ iter.next();
+ });
+ assertEquals(message, ex.message);
+
+ m = new goog.structs.Map;
+ m.set('a', 1);
+ m.set('b', 2);
+ m.set('c', 3);
+ m.set('d', 4);
+
+ iter = m.getValueIterator();
+ m.set('d', 5);
+ iter.next();
+ // Changing an existing value is OK.
+ iter.next();
+};
+
+function testTranspose() {
+ var m = new goog.structs.Map;
+ m.set('a', 1);
+ m.set('b', 2);
+ m.set('c', 3);
+ m.set('d', 4);
+ m.set('e', 5);
+
+ var transposed = m.transpose();
+ assertEquals('Should contain the keys', 'abcde',
+ goog.iter.join(transposed, ''));
+}
+
+function testToObject() {
+ Object.prototype.b = 0;
+ try {
+ var map = new goog.structs.Map();
+ map.set('a', 0);
+ var obj = map.toObject();
+ assertTrue('object representation has key "a"', obj.hasOwnProperty('a'));
+ assertFalse('object representation does not have key "b"',
+ obj.hasOwnProperty('b'));
+ assertEquals('value for key "a"', 0, obj['a']);
+ } finally {
+ delete Object.prototype.b;
+ }
+}
+
+function testEqualsWithSameObject() {
+ var map1 = getMap();
+ assertTrue('maps are the same object', map1.equals(map1));
+}
+
+function testEqualsWithDifferentSizeMaps() {
+ var map1 = getMap();
+ var map2 = new goog.structs.Map();
+
+ assertFalse('maps are different sizes', map1.equals(map2));
+}
+
+function testEqualsWithDefaultEqualityFn() {
+ var map1 = new goog.structs.Map();
+ var map2 = new goog.structs.Map();
+
+ assertTrue('maps are both empty', map1.equals(map2));
+
+ map1 = getMap();
+ map2 = getMap();
+ assertTrue('maps are the same', map1.equals(map2));
+
+ map2.set('d', '3');
+ assertFalse('maps have 3 and \'3\'', map1.equals(map2));
+}
+
+function testEqualsWithCustomEqualityFn() {
+ var map1 = new goog.structs.Map();
+ var map2 = new goog.structs.Map();
+
+ map1.set('a', 0);
+ map1.set('b', 1);
+
+ map2.set('a', '0');
+ map2.set('b', '1');
+
+ var equalsFn = function(a, b) { return a == b };
+
+ assertTrue('maps are equal with ==', map1.equals(map2, equalsFn));
+}
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/node.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/node.js.svn-base
new file mode 100644
index 0000000..bc6a9fb
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/node.js.svn-base
@@ -0,0 +1,74 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Generic immutable node object to be used in collections.
+ *
+ */
+
+
+goog.provide('goog.structs.Node');
+
+
+
+/**
+ * A generic immutable node. This can be used in various collections that
+ * require a node object for its item (such as a heap).
+ * @param {*} key Key.
+ * @param {*} value Vaue.
+ * @constructor
+ */
+goog.structs.Node = function(key, value) {
+ /**
+ * The key.
+ * @type {*}
+ * @private
+ */
+ this.key_ = key;
+
+ /**
+ * The value.
+ * @type {*}
+ * @private
+ */
+ this.value_ = value;
+};
+
+
+/**
+ * Gets the key.
+ * @return {*} The key.
+ */
+goog.structs.Node.prototype.getKey = function() {
+ return this.key_;
+};
+
+
+/**
+ * Gets the value.
+ * @return {*} The value.
+ */
+goog.structs.Node.prototype.getValue = function() {
+ return this.value_;
+};
+
+
+/**
+ * Clones a node and returns a new node.
+ * @return {goog.structs.Node} A new goog.structs.Node with the same key value
+ * pair.
+ */
+goog.structs.Node.prototype.clone = function() {
+ return new goog.structs.Node(this.key_, this.value_);
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/pool.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/pool.js.svn-base
new file mode 100644
index 0000000..ba69dd0
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/pool.js.svn-base
@@ -0,0 +1,381 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Datastructure: Pool.
+ *
+ *
+ * A generic class for handling pools of objects.
+ * When an object is released, it is attempted to be reused.
+ */
+
+
+goog.provide('goog.structs.Pool');
+
+goog.require('goog.Disposable');
+goog.require('goog.structs.Queue');
+goog.require('goog.structs.Set');
+
+
+
+/**
+ * A generic pool class. If min is greater than max, an error is thrown.
+ * @param {number=} opt_minCount Min. number of objects (Default: 1).
+ * @param {number=} opt_maxCount Max. number of objects (Default: 10).
+ * @constructor
+ * @extends {goog.Disposable}
+ */
+goog.structs.Pool = function(opt_minCount, opt_maxCount) {
+ goog.Disposable.call(this);
+
+ /**
+ * Minimum number of objects allowed
+ * @type {number}
+ * @private
+ */
+ this.minCount_ = opt_minCount || 0;
+
+ /**
+ * Maximum number of objects allowed
+ * @type {number}
+ * @private
+ */
+ this.maxCount_ = opt_maxCount || 10;
+
+ // Make sure that the max and min constraints are valid.
+ if (this.minCount_ > this.maxCount_) {
+ throw Error(goog.structs.Pool.ERROR_MIN_MAX_);
+ }
+
+ /**
+ * Set used to store objects that are currently in the pool and available
+ * to be used.
+ * @type {goog.structs.Queue}
+ * @private
+ */
+ this.freeQueue_ = new goog.structs.Queue();
+
+ /**
+ * Set used to store objects that are currently in the pool and in use.
+ * @type {goog.structs.Set}
+ * @private
+ */
+ this.inUseSet_ = new goog.structs.Set();
+
+ /**
+ * The minimum delay between objects being made available, in milliseconds. If
+ * this is 0, no minimum delay is enforced.
+ * @type {number}
+ * @protected
+ */
+ this.delay = 0;
+
+ /**
+ * The time of the last object being made available, in milliseconds since the
+ * epoch (i.e., the result of Date#toTime). If this is null, no access has
+ * occurred yet.
+ * @type {number?}
+ * @protected
+ */
+ this.lastAccess = null;
+
+ // Make sure that the minCount constraint is satisfied.
+ this.adjustForMinMax();
+
+
+ // TODO(user): Remove once JSCompiler's undefined properties warnings
+ // don't error for guarded properties.
+ var magicProps = {canBeReused: 0};
+};
+goog.inherits(goog.structs.Pool, goog.Disposable);
+
+
+/**
+ * Error to throw when the max/min constraint is attempted to be invalidated.
+ * I.e., when it is attempted for maxCount to be less than minCount.
+ * @type {string}
+ * @private
+ */
+goog.structs.Pool.ERROR_MIN_MAX_ =
+ '[goog.structs.Pool] Min can not be greater than max';
+
+
+/**
+ * Error to throw when the Pool is attempted to be disposed and it is asked to
+ * make sure that there are no objects that are in use (i.e., haven't been
+ * released).
+ * @type {string}
+ * @private
+ */
+goog.structs.Pool.ERROR_DISPOSE_UNRELEASED_OBJS_ =
+ '[goog.structs.Pool] Objects not released';
+
+
+/**
+ * Sets the minimum count of the pool.
+ * If min is greater than the max count of the pool, an error is thrown.
+ * @param {number} min The minimum count of the pool.
+ */
+goog.structs.Pool.prototype.setMinimumCount = function(min) {
+ // Check count constraints.
+ if (min > this.maxCount_) {
+ throw Error(goog.structs.Pool.ERROR_MIN_MAX_);
+ }
+ this.minCount_ = min;
+
+ // Adjust the objects in the pool as needed.
+ this.adjustForMinMax();
+};
+
+
+/**
+ * Sets the maximum count of the pool.
+ * If max is less than the max count of the pool, an error is thrown.
+ * @param {number} max The maximium count of the pool.
+ */
+goog.structs.Pool.prototype.setMaximumCount = function(max) {
+ // Check count constraints.
+ if (max < this.minCount_) {
+ throw Error(goog.structs.Pool.ERROR_MIN_MAX_);
+ }
+ this.maxCount_ = max;
+
+ // Adjust the objects in the pool as needed.
+ this.adjustForMinMax();
+};
+
+
+/**
+ * Sets the minimum delay between objects being returned by getObject, in
+ * milliseconds. This defaults to zero, meaning that no minimum delay is
+ * enforced and objects may be used as soon as they're available.
+ * @param {number} delay The minimum delay, in milliseconds.
+ */
+goog.structs.Pool.prototype.setDelay = function(delay) {
+ this.delay = delay;
+};
+
+
+/**
+ * @return {Object|undefined} A new object from the pool if there is one
+ * available, otherwise undefined.
+ */
+goog.structs.Pool.prototype.getObject = function() {
+ var time = goog.now();
+ if (goog.isDefAndNotNull(this.lastAccess) &&
+ time - this.lastAccess < this.delay) {
+ return undefined;
+ }
+
+ var obj = this.removeFreeObject_();
+ if (obj) {
+ this.lastAccess = time;
+ this.inUseSet_.add(obj);
+ }
+
+ return obj;
+};
+
+
+/**
+ * Returns an object to the pool of available objects so that it can be reused.
+ * @param {Object} obj The object to return to the pool of free objects.
+ * @return {boolean} Whether the object was found in the Pool's set of in-use
+ * objects (in other words, whether any action was taken).
+ */
+goog.structs.Pool.prototype.releaseObject = function(obj) {
+ if (this.inUseSet_.remove(obj)) {
+ this.addFreeObject(obj);
+ return true;
+ }
+ return false;
+};
+
+
+/**
+ * Removes a free object from the collection of objects that are free so that it
+ * can be used.
+ *
+ * NOTE: This method does not mark the returned object as in use.
+ *
+ * @return {Object|undefined} The object removed from the free collection, if
+ * there is one available. Otherwise, undefined.
+ * @private
+ */
+goog.structs.Pool.prototype.removeFreeObject_ = function() {
+ var obj;
+ while (this.getFreeCount() > 0) {
+ obj = /** @type {Object} */(this.freeQueue_.dequeue());
+
+ if (!this.objectCanBeReused(obj)) {
+ this.adjustForMinMax();
+ } else {
+ break;
+ }
+ }
+
+ if (!obj && this.getCount() < this.maxCount_) {
+ obj = this.createObject();
+ }
+
+ return obj;
+};
+
+
+/**
+ * Adds an object to the collection of objects that are free. If the object can
+ * not be added, then it is disposed.
+ *
+ * @param {Object} obj The object to add to collection of free objects.
+ */
+goog.structs.Pool.prototype.addFreeObject = function(obj) {
+ this.inUseSet_.remove(obj);
+ if (this.objectCanBeReused(obj) && this.getCount() < this.maxCount_) {
+ this.freeQueue_.enqueue(obj);
+ } else {
+ this.disposeObject(obj);
+ }
+};
+
+
+/**
+ * Adjusts the objects held in the pool to be within the min/max constraints.
+ *
+ * NOTE: It is possible that the number of objects in the pool will still be
+ * greater than the maximum count of objects allowed. This will be the case
+ * if no more free objects can be disposed of to get below the minimum count
+ * (i.e., all objects are in use).
+ */
+goog.structs.Pool.prototype.adjustForMinMax = function() {
+ var freeQueue = this.freeQueue_;
+
+ // Make sure the at least the minimum number of objects are created.
+ while (this.getCount() < this.minCount_) {
+ freeQueue.enqueue(this.createObject());
+ }
+
+ // Make sure no more than the maximum number of objects are created.
+ while (this.getCount() > this.maxCount_ && this.getFreeCount() > 0) {
+ this.disposeObject(/** @type {Object} */(freeQueue.dequeue()));
+ }
+};
+
+
+/**
+ * Should be overriden by sub-classes to return an instance of the object type
+ * that is expected in the pool.
+ * @return {Object} The created object.
+ */
+goog.structs.Pool.prototype.createObject = function() {
+ return {};
+};
+
+
+/**
+ * Should be overriden to dispose of an object. Default implementation is to
+ * remove all its members, which should render it useless. Calls the object's
+ * {@code dispose()} method, if available.
+ * @param {Object} obj The object to dispose.
+ */
+goog.structs.Pool.prototype.disposeObject = function(obj) {
+ if (typeof obj.dispose == 'function') {
+ obj.dispose();
+ } else {
+ for (var i in obj) {
+ obj[i] = null;
+ }
+ }
+};
+
+
+/**
+ * Should be overriden to determine whether an object has become unusable and
+ * should not be returned by getObject(). Calls the object's
+ * {@code canBeReused()} method, if available.
+ * @param {Object} obj The object to test.
+ * @return {boolean} Whether the object can be reused.
+ */
+goog.structs.Pool.prototype.objectCanBeReused = function(obj) {
+ if (typeof obj.canBeReused == 'function') {
+ return obj.canBeReused();
+ }
+ return true;
+};
+
+
+/**
+ * Returns true if the given object is in the pool.
+ * @param {Object} obj The object to check the pool for.
+ * @return {boolean} Whether the pool contains the object.
+ */
+goog.structs.Pool.prototype.contains = function(obj) {
+ return this.freeQueue_.contains(obj) || this.inUseSet_.contains(obj);
+};
+
+
+/**
+ * Returns the number of objects currently in the pool.
+ * @return {number} Number of objects currently in the pool.
+ */
+goog.structs.Pool.prototype.getCount = function() {
+ return this.freeQueue_.getCount() + this.inUseSet_.getCount();
+};
+
+
+/**
+ * Returns the number of objects currently in use in the pool.
+ * @return {number} Number of objects currently in use in the pool.
+ */
+goog.structs.Pool.prototype.getInUseCount = function() {
+ return this.inUseSet_.getCount();
+};
+
+
+/**
+ * Returns the number of objects currently free in the pool.
+ * @return {number} Number of objects currently free in the pool.
+ */
+goog.structs.Pool.prototype.getFreeCount = function() {
+ return this.freeQueue_.getCount();
+};
+
+
+/**
+ * Determines if the pool contains no objects.
+ * @return {boolean} Whether the pool contains no objects.
+ */
+goog.structs.Pool.prototype.isEmpty = function() {
+ return this.freeQueue_.isEmpty() && this.inUseSet_.isEmpty();
+};
+
+
+/**
+ * Disposes of the pool and all objects currently held in the pool.
+ * @override
+ * @protected
+ */
+goog.structs.Pool.prototype.disposeInternal = function() {
+ goog.structs.Pool.superClass_.disposeInternal.call(this);
+ if (this.getInUseCount() > 0) {
+ throw Error(goog.structs.Pool.ERROR_DISPOSE_UNRELEASED_OBJS_);
+ }
+ delete this.inUseSet_;
+
+ // Call disposeObject on each object held by the pool.
+ var freeQueue = this.freeQueue_;
+ while (!freeQueue.isEmpty()) {
+ this.disposeObject(/** @type {Object} */ (freeQueue.dequeue()));
+ }
+ delete this.freeQueue_;
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/pool_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/pool_test.html.svn-base
new file mode 100644
index 0000000..461e70f
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/pool_test.html.svn-base
@@ -0,0 +1,291 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2006 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs.Pool</title>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.structs');
+ goog.require('goog.structs.Pool');
+ goog.require('goog.testing.MockClock');
+ goog.require('goog.testing.jsunit');
+</script>
+</head>
+<body>
+<script>
+
+// Implementation of the Pool class with isObjectDead() always returning TRUE,
+// so that the the Pool will not reuse any objects.
+function NoObjectReusePool(opt_min, opt_max) {
+ goog.structs.Pool.call(this, opt_min, opt_max);
+};
+goog.inherits(NoObjectReusePool, goog.structs.Pool);
+
+NoObjectReusePool.prototype.objectCanBeReused = function(obj) {
+ return false;
+};
+
+
+function testExceedMax1() {
+ var p = new goog.structs.Pool(0, 3);
+ var obj1 = p.getObject();
+ var obj2 = p.getObject();
+ var obj3 = p.getObject();
+ var obj4 = p.getObject();
+ var obj5 = p.getObject();
+
+ assertNotUndefined(obj1);
+ assertNotUndefined(obj2);
+ assertNotUndefined(obj3);
+ assertUndefined(obj4);
+ assertUndefined(obj5);
+}
+
+
+function testExceedMax2() {
+ var p = new goog.structs.Pool(0, 1);
+ var obj1 = p.getObject();
+ var obj2 = p.getObject();
+ var obj3 = p.getObject();
+ var obj4 = p.getObject();
+ var obj5 = p.getObject();
+
+ assertNotUndefined(obj1);
+ assertUndefined(obj2);
+ assertUndefined(obj3);
+ assertUndefined(obj4);
+ assertUndefined(obj5);
+}
+
+
+function testExceedMax3() {
+ var p = new goog.structs.Pool(); // default: 10
+ var objs = [];
+
+ for (var i = 0; i < 12; i++) {
+ objs[i] = p.getObject();
+ }
+
+ for (var i = 0; i < 10; i++) {
+ assertNotNull('First 10 should be not null', objs[i]);
+ }
+
+ assertUndefined(objs[10]);
+ assertUndefined(objs[11]);
+}
+
+
+function testReleaseAndGet1() {
+ var p = new goog.structs.Pool(0, 10);
+ var o = p.getObject();
+ assertEquals(1, p.getCount());
+ assertEquals(1, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+ assertTrue('Result should be true', p.releaseObject(o));
+ assertEquals(1, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(1, p.getFreeCount());
+}
+
+
+function testReleaseAndGet2() {
+ var p = new NoObjectReusePool(0, 10);
+ var o = p.getObject();
+ assertEquals(1, p.getCount());
+ assertEquals(1, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+ assertTrue('Result should be true', p.releaseObject(o));
+ assertEquals(0, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+}
+
+
+function testReleaseAndGet3() {
+ var p = new goog.structs.Pool(0, 10);
+ var o1 = p.getObject();
+ var o2 = p.getObject();
+ var o3 = p.getObject();
+ var o4 = {};
+ assertEquals(3, p.getCount());
+ assertEquals(3, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+ assertTrue('Result should be true', p.releaseObject(o1));
+ assertTrue('Result should be true', p.releaseObject(o2));
+ assertFalse('Result should be false', p.releaseObject(o4));
+ assertEquals(3, p.getCount());
+ assertEquals(1, p.getInUseCount());
+ assertEquals(2, p.getFreeCount());
+}
+
+
+function testReleaseAndGet4() {
+ var p = new NoObjectReusePool(0, 10);
+ var o1 = p.getObject();
+ var o2 = p.getObject();
+ var o3 = p.getObject();
+ var o4 = {};
+ assertEquals(3, p.getCount());
+ assertEquals(3, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+ assertTrue('Result should be true', p.releaseObject(o1));
+ assertTrue('Result should be true', p.releaseObject(o2));
+ assertFalse('Result should be false', p.releaseObject(o4));
+ assertEquals(1, p.getCount());
+ assertEquals(1, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+}
+
+
+function testIsInPool1() {
+ var p = new goog.structs.Pool();
+ var o1 = p.getObject();
+ var o2 = p.getObject();
+ var o3 = p.getObject();
+ var o4 = {};
+ var o5 = {};
+ var o6 = o1;
+
+ assertTrue(p.contains(o1));
+ assertTrue(p.contains(o2));
+ assertTrue(p.contains(o3));
+ assertFalse(p.contains(o4));
+ assertFalse(p.contains(o5));
+ assertTrue(p.contains(o6));
+}
+
+
+function testSetMin1() {
+ var p = new goog.structs.Pool(0, 10);
+
+ assertEquals(0, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+
+ p.setMinimumCount(10);
+
+ assertEquals(10, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(10, p.getFreeCount());
+}
+
+
+function testSetMin2() {
+ var p = new goog.structs.Pool(0, 10);
+
+ assertEquals(0, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+
+ var o1 = p.getObject();
+
+ assertEquals(1, p.getCount());
+ assertEquals(1, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+
+ p.setMinimumCount(10);
+
+ assertEquals(10, p.getCount());
+ assertEquals(1, p.getInUseCount());
+ assertEquals(9, p.getFreeCount());
+}
+
+
+function testSetMax1() {
+ var p = new goog.structs.Pool(0, 10);
+
+ assertEquals(0, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+
+ var o1 = p.getObject();
+ var o2 = p.getObject();
+ var o3 = p.getObject();
+ var o4 = p.getObject();
+ var o5 = p.getObject();
+
+ assertEquals(5, p.getCount());
+ assertEquals(5, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+
+ assertTrue('Result should be true', p.releaseObject(o5));
+
+ assertEquals(5, p.getCount());
+ assertEquals(4, p.getInUseCount());
+ assertEquals(1, p.getFreeCount());
+
+ p.setMaximumCount(4);
+
+ assertEquals(4, p.getCount());
+ assertEquals(4, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+}
+
+
+function testInvalidMinMax1() {
+ var p = new goog.structs.Pool(0, 10);
+
+ assertEquals(0, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+
+ assertThrows(function() {
+ p.setMinimumCount(11);
+ });
+}
+
+
+function testInvalidMinMax2() {
+ var p = new goog.structs.Pool(5, 10);
+
+ assertEquals(5, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(5, p.getFreeCount());
+
+ assertThrows(function() {
+ p.setMaximumCount(4);
+ });
+}
+
+
+function testInvalidMinMax3() {
+ assertThrows(function() {
+ new goog.structs.Pool(10, 1);
+ });
+}
+
+
+function testRateLimiting() {
+ var clock = new goog.testing.MockClock();
+ clock.install();
+
+ var p = new goog.structs.Pool(0, 3);
+ p.setDelay(100);
+
+ assertNotUndefined(p.getObject());
+ assertUndefined(p.getObject());
+
+ clock.tick(100);
+ assertNotUndefined(p.getObject());
+ assertUndefined(p.getObject());
+
+ clock.tick(100);
+ assertNotUndefined(p.getObject());
+ assertUndefined(p.getObject());
+
+ clock.tick(100);
+ assertUndefined(p.getObject());
+
+ goog.dispose(clock);
+}
+
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/prioritypool.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/prioritypool.js.svn-base
new file mode 100644
index 0000000..ce2af7f
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/prioritypool.js.svn-base
@@ -0,0 +1,179 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Datastructure: Priority Pool.
+ *
+ *
+ * An extending of Pool that handles queueing and prioritization.
+ */
+
+
+goog.provide('goog.structs.PriorityPool');
+
+goog.require('goog.structs.Pool');
+goog.require('goog.structs.PriorityQueue');
+
+
+
+/**
+ * A generic pool class. If max is greater than min, an error is thrown.
+ * @param {number=} opt_minCount Min. number of objects (Default: 1).
+ * @param {number=} opt_maxCount Max. number of objects (Default: 10).
+ * @constructor
+ * @extends {goog.structs.Pool}
+ */
+goog.structs.PriorityPool = function(opt_minCount, opt_maxCount) {
+ /**
+ * Queue of requests for pool objects.
+ * @type {goog.structs.PriorityQueue}
+ * @private
+ */
+ this.requestQueue_ = new goog.structs.PriorityQueue();
+
+ // Must break convention of putting the super-class's constructor first. This
+ // is because the super-class constructor calls adjustForMinMax, which this
+ // class overrides. In this class's implementation, it assumes that there
+ // is a requestQueue_, and will error if not present.
+ goog.structs.Pool.call(this, opt_minCount, opt_maxCount);
+};
+goog.inherits(goog.structs.PriorityPool, goog.structs.Pool);
+
+
+/**
+ * The key for the most recent timeout created.
+ * @type {number|undefined}
+ * @private
+ */
+goog.structs.PriorityPool.prototype.delayTimeout_;
+
+
+/**
+ * Default priority for pool objects requests.
+ * @type {number}
+ * @private
+ */
+goog.structs.PriorityPool.DEFAULT_PRIORITY_ = 100;
+
+
+/** @override */
+goog.structs.PriorityPool.prototype.setDelay = function(delay) {
+ goog.base(this, 'setDelay', delay);
+
+ // If the pool hasn't been accessed yet, no need to do anything.
+ if (!goog.isDefAndNotNull(this.lastAccess)) {
+ return;
+ }
+
+ goog.global.clearTimeout(this.delayTimeout_);
+ this.delayTimeout_ = goog.global.setTimeout(
+ goog.bind(this.handleQueueRequests_, this),
+ this.delay + this.lastAccess - goog.now());
+
+ // Handle all requests.
+ this.handleQueueRequests_();
+};
+
+
+/**
+ * Get a new object from the the pool, if there is one available, otherwise
+ * return undefined.
+ * @param {Function=} opt_callback The function to callback when an object is
+ * available. This could be immediately. If this is not present, then an
+ * object is immediately returned if available, or undefined if not.
+ * @param {*=} opt_priority The priority of the request.
+ * @return {Object|undefined} The new object from the pool if there is one
+ * available and a callback is not given. Otherwise, undefined.
+ */
+goog.structs.PriorityPool.prototype.getObject = function(opt_callback,
+ opt_priority) {
+ if (!opt_callback) {
+ var result = goog.base(this, 'getObject');
+ if (result && this.delay) {
+ this.delayTimeout_ = goog.global.setTimeout(
+ goog.bind(this.handleQueueRequests_, this),
+ this.delay);
+ }
+ return result;
+ }
+
+ var priority = opt_priority || goog.structs.PriorityPool.DEFAULT_PRIORITY_;
+ this.requestQueue_.enqueue(priority, opt_callback);
+
+ // Handle all requests.
+ this.handleQueueRequests_();
+
+ return undefined;
+};
+
+
+/**
+ * Handles the request queue. Tries to fires off as many queued requests as
+ * possible.
+ * @private
+ */
+goog.structs.PriorityPool.prototype.handleQueueRequests_ = function() {
+ var requestQueue = this.requestQueue_;
+ while (requestQueue.getCount() > 0) {
+ var obj = this.getObject();
+
+ if (!obj) {
+ return;
+ } else {
+ var requestCallback = requestQueue.dequeue();
+ requestCallback.apply(this, [obj]);
+ }
+ }
+};
+
+
+/**
+ * Adds an object to the collection of objects that are free. If the object can
+ * not be added, then it is disposed.
+ *
+ * NOTE: This method does not remove the object from the in use collection.
+ *
+ * @param {Object} obj The object to add to the collection of free objects.
+ */
+goog.structs.PriorityPool.prototype.addFreeObject = function(obj) {
+ goog.structs.PriorityPool.superClass_.addFreeObject.call(this, obj);
+
+ // Handle all requests.
+ this.handleQueueRequests_();
+};
+
+
+/**
+ * Adjusts the objects held in the pool to be within the min/max constraints.
+ *
+ * NOTE: It is possible that the number of objects in the pool will still be
+ * greater than the maximum count of objects allowed. This will be the case
+ * if no more free objects can be disposed of to get below the minimum count
+ * (i.e., all objects are in use).
+ */
+goog.structs.PriorityPool.prototype.adjustForMinMax = function() {
+ goog.structs.PriorityPool.superClass_.adjustForMinMax.call(this);
+
+ // Handle all requests.
+ this.handleQueueRequests_();
+};
+
+
+/** @override */
+goog.structs.PriorityPool.prototype.disposeInternal = function() {
+ goog.structs.PriorityPool.superClass_.disposeInternal.call(this);
+ goog.global.clearTimeout(this.delayTimeout_);
+ this.requestQueue_.clear();
+ this.requestQueue_ = null;
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/prioritypool_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/prioritypool_test.html.svn-base
new file mode 100644
index 0000000..7a0b367
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/prioritypool_test.html.svn-base
@@ -0,0 +1,562 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2006 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs.PriorityPool</title>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.structs.PriorityPool');
+ goog.require('goog.testing.MockClock');
+ goog.require('goog.testing.jsunit');
+ goog.require('goog.structs');
+</script>
+</head>
+<body>
+<script>
+
+// Implementation of the Pool class with isObjectDead() always returning TRUE,
+// so that the the Pool will not reuse any objects.
+function NoObjectReusePriorityPool(opt_min, opt_max) {
+ goog.structs.PriorityPool.call(this, opt_min, opt_max);
+};
+goog.inherits(NoObjectReusePriorityPool, goog.structs.PriorityPool);
+
+NoObjectReusePriorityPool.prototype.objectCanBeReused = function(obj) {
+ return false;
+};
+
+
+function testExceedMax1() {
+ var p = new goog.structs.PriorityPool(0, 3);
+
+ var getCount1 = 0;
+ var callback1 = function(obj) {
+ assertNotNull(obj);
+ getCount1++;
+ };
+
+ var getCount2 = 0;
+ var callback2 = function(obj) {
+ getCount2++;
+ };
+
+ p.getObject(callback1);
+ p.getObject(callback1);
+ p.getObject(callback1);
+ p.getObject(callback2);
+ p.getObject(callback2);
+ p.getObject(callback2);
+
+ assertEquals('getCount for allocated, Should be 3', getCount1, 3);
+ assertEquals('getCount for unallocated, Should be 0', getCount2, 0);
+}
+
+
+function testExceedMax2() {
+ var p = new goog.structs.PriorityPool(0, 1);
+
+ var getCount1 = 0;
+ var callback1 = function(obj) {
+ assertNotNull(obj);
+ getCount1++;
+ };
+
+ var getCount2 = 0;
+ var callback2 = function(obj) {
+ getCount2++;
+ };
+
+ p.getObject(callback1);
+ p.getObject(callback2);
+ p.getObject(callback2);
+ p.getObject(callback2);
+ p.getObject(callback2);
+ p.getObject(callback2);
+
+ assertEquals('getCount for allocated, Should be 1', getCount1, 1);
+ assertEquals('getCount for unallocated, Should be 0', getCount2, 0);
+}
+
+function testExceedMax3() {
+ var p = new goog.structs.PriorityPool(0, 2);
+
+ var obj1 = null;
+ var callback1 = function(obj) {
+ obj1 = obj;
+ };
+
+ var obj2 = null;
+ var callback2 = function(obj) {
+ obj2 = obj;
+ };
+
+ var obj3 = null;
+ var callback3 = function(obj) {
+ obj3 = obj;
+ };
+
+ p.getObject(callback1);
+ p.getObject(callback2);
+ p.getObject(callback3);
+
+ assertNotNull(obj1);
+ assertNotNull(obj2);
+ assertNull(obj3);
+}
+
+function testExceedMax4() {
+ var p = new goog.structs.PriorityPool(); // default: 10
+ var objs = [];
+
+ var getCount1 = 0;
+ var callback1 = function(obj) {
+ assertNotNull(obj);
+ getCount1++;
+ };
+
+ var getCount2 = 0;
+ var callback2 = function(obj) {
+ getCount2++;
+ };
+
+ for (var i = 0; i < 12; i++) {
+ p.getObject(i < 10 ? callback1 : callback2);
+ }
+
+ assertEquals('getCount for allocated, Should be 10', getCount1, 10);
+ assertEquals('getCount for unallocated, Should be 0', getCount2, 0);
+}
+
+
+function testReleaseAndGet1() {
+ var p = new goog.structs.PriorityPool(0, 10);
+
+ var o = null;
+ var callback = function(obj) {
+ o = obj;
+ };
+
+ p.getObject(callback);
+ assertEquals(1, p.getCount());
+ assertEquals(1, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+ assertTrue('Result should be true', p.releaseObject(o));
+ assertEquals(1, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(1, p.getFreeCount());
+}
+
+
+function testReleaseAndGet2() {
+ var p = new NoObjectReusePriorityPool(0, 10);
+
+ var o = null;
+ var callback = function(obj) {
+ o = obj;
+ };
+
+ p.getObject(callback);
+ assertEquals(1, p.getCount());
+ assertEquals(1, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+ assertTrue('Result should be true', p.releaseObject(o));
+ assertEquals(0, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+}
+
+
+function testReleaseAndGet3() {
+ var p = new goog.structs.PriorityPool(0, 10);
+ var o1 = null;
+ var callback1 = function(obj) {
+ o1 = obj;
+ };
+
+ var o2 = null;
+ var callback2 = function(obj) {
+ o2 = obj;
+ };
+
+ var o3 = null;
+ var callback3 = function(obj) {
+ o3 = obj;
+ };
+
+ var o4 = {};
+
+ p.getObject(callback1);
+ p.getObject(callback2);
+ p.getObject(callback3);
+
+ assertEquals(3, p.getCount());
+ assertEquals(3, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+ assertTrue('Result should be true', p.releaseObject(o1));
+ assertTrue('Result should be true', p.releaseObject(o2));
+ assertFalse('Result should be false', p.releaseObject(o4));
+ assertEquals(3, p.getCount());
+ assertEquals(1, p.getInUseCount());
+ assertEquals(2, p.getFreeCount());
+}
+
+
+function testReleaseAndGet4() {
+ var p = new NoObjectReusePriorityPool(0, 10);
+
+ var o1 = null;
+ var callback1 = function(obj) {
+ o1 = obj;
+ };
+
+ var o2 = null;
+ var callback2 = function(obj) {
+ o2 = obj;
+ };
+
+ var o3 = null;
+ var callback3 = function(obj) {
+ o3 = obj;
+ };
+
+ var o4 = {};
+
+ p.getObject(callback1);
+ p.getObject(callback2);
+ p.getObject(callback3);
+ assertEquals(3, p.getCount());
+ assertEquals(3, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+ assertTrue('Result should be true', p.releaseObject(o1));
+ assertTrue('Result should be true', p.releaseObject(o2));
+ assertFalse('Result should be false', p.releaseObject(o4));
+ assertEquals(1, p.getCount());
+ assertEquals(1, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+}
+
+
+function testIsInPool1() {
+ var p = new goog.structs.PriorityPool();
+ var o1 = null;
+ var callback1 = function(obj) {
+ o1 = obj;
+ };
+
+ var o2 = null;
+ var callback2 = function(obj) {
+ o2 = obj;
+ };
+
+ var o3 = null;
+ var callback3 = function(obj) {
+ o3 = obj;
+ };
+
+ var o4 = {};
+ var o5 = {};
+
+ p.getObject(callback1);
+ p.getObject(callback2);
+ p.getObject(callback3);
+ var o6 = o1;
+
+ assertTrue(p.contains(o1));
+ assertTrue(p.contains(o2));
+ assertTrue(p.contains(o3));
+ assertFalse(p.contains(o4));
+ assertFalse(p.contains(o5));
+ assertTrue(p.contains(o6));
+}
+
+
+function testSetMin1() {
+ var p = new goog.structs.PriorityPool(0, 10);
+
+ assertEquals(0, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+
+ p.setMinimumCount(10);
+
+ assertEquals(10, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(10, p.getFreeCount());
+}
+
+
+function testSetMin2() {
+ var p = new goog.structs.PriorityPool(0, 10);
+
+ assertEquals(0, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+
+ var o1 = null;
+ var callback1 = function(obj) {
+ o1 = obj;
+ };
+ p.getObject(callback1);
+
+ assertEquals(1, p.getCount());
+ assertEquals(1, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+
+ p.setMinimumCount(10);
+
+ assertEquals(10, p.getCount());
+ assertEquals(1, p.getInUseCount());
+ assertEquals(9, p.getFreeCount());
+}
+
+
+function testSetMax1() {
+ var p = new goog.structs.PriorityPool(0, 10);
+
+ assertEquals(0, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+
+ var o1 = null;
+ var callback1 = function(obj) {
+ o1 = obj;
+ };
+
+ var o2 = null;
+ var callback2 = function(obj) {
+ o2 = obj;
+ };
+
+ var o3 = null;
+ var callback3 = function(obj) {
+ o3 = obj;
+ };
+
+ var o4 = null;
+ var callback4 = function(obj) {
+ o4 = obj;
+ };
+
+ var o5 = null;
+ var callback5 = function(obj) {
+ o5 = obj;
+ };
+
+ p.getObject(callback1);
+ p.getObject(callback2);
+ p.getObject(callback3);
+ p.getObject(callback4);
+ p.getObject(callback5);
+
+ assertEquals(5, p.getCount());
+ assertEquals(5, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+
+ assertTrue('Result should be true', p.releaseObject(o5));
+
+ assertEquals(5, p.getCount());
+ assertEquals(4, p.getInUseCount());
+ assertEquals(1, p.getFreeCount());
+
+ p.setMaximumCount(4);
+
+ assertEquals(4, p.getCount());
+ assertEquals(4, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+}
+
+
+function testInvalidMinMax1() {
+ var p = new goog.structs.PriorityPool(0, 10);
+
+ assertEquals(0, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+
+ assertThrows(function() {
+ p.setMinimumCount(11);
+ });
+}
+
+
+function testInvalidMinMax2() {
+ var p = new goog.structs.PriorityPool(5, 10);
+
+ assertEquals(5, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(5, p.getFreeCount());
+
+ assertThrows(function() {
+ p.setMaximumCount(4);
+ });
+}
+
+
+function testInvalidMinMax3() {
+ assertThrows(function() {
+ new goog.structs.PriorityPool(10, 1);
+ });
+}
+
+function testQueue1() {
+ var p = new goog.structs.PriorityPool(0, 2);
+
+ var o1 = null;
+ var callback1 = function(obj) {
+ o1 = obj;
+ };
+
+ var o2 = null;
+ var callback2 = function(obj) {
+ o2 = obj;
+ };
+
+ var o3 = null;
+ var callback3 = function(obj) {
+ o3 = obj;
+ };
+
+ p.getObject(callback1);
+ p.getObject(callback2);
+ p.getObject(callback3);
+
+ assertNotNull(o1);
+ assertNotNull(o2);
+ assertNull(o3);
+
+ p.releaseObject(o1);
+ assertNotNull(o3);
+}
+
+
+function testPriority1() {
+ var p = new goog.structs.PriorityPool(0, 2);
+
+ var o1 = null;
+ var callback1 = function(obj) {
+ o1 = obj;
+ };
+
+ var o2 = null;
+ var callback2 = function(obj) {
+ o2 = obj;
+ };
+
+ var o3 = null;
+ var callback3 = function(obj) {
+ o3 = obj;
+ };
+
+ var o4 = null;
+ var callback4 = function(obj) {
+ o4 = obj;
+ };
+
+ p.getObject(callback1);
+ p.getObject(callback2);
+ p.getObject(callback3, 10);
+ p.getObject(callback4, 5);
+
+ assertNotNull(o1);
+ assertNotNull(o2);
+ assertNull(o3);
+ assertNull(o4);
+
+ p.releaseObject(o1);
+ assertNull(o3);
+ assertNotNull(o4);
+}
+
+
+function testRateLimiting() {
+ var clock = new goog.testing.MockClock();
+ clock.install();
+
+ var p = new goog.structs.PriorityPool(0, 4);
+ p.setDelay(100);
+
+ var getCount = 0;
+ var callback = function(obj) {
+ assertNotNull(obj);
+ getCount++;
+ };
+
+ p.getObject(callback);
+ assertEquals(1, getCount);
+
+ p.getObject(callback);
+ assertEquals(1, getCount);
+
+ clock.tick(100);
+ assertEquals(2, getCount);
+
+ p.getObject(callback);
+ p.getObject(callback);
+ assertEquals(2, getCount);
+
+ clock.tick(100);
+ assertEquals(3, getCount);
+
+ clock.tick(100);
+ assertEquals(4, getCount);
+
+ p.getObject(callback);
+ assertEquals(4, getCount);
+
+ clock.tick(100);
+ assertEquals(4, getCount);
+
+ goog.dispose(clock);
+}
+
+
+function testRateLimitingWithChangingDelay() {
+ var clock = new goog.testing.MockClock();
+ clock.install();
+
+ var p = new goog.structs.PriorityPool(0, 3);
+ p.setDelay(100);
+
+ var getCount = 0;
+ var callback = function(obj) {
+ assertNotNull(obj);
+ getCount++;
+ };
+
+ p.getObject(callback);
+ assertEquals(1, getCount);
+
+ p.getObject(callback);
+ assertEquals(1, getCount);
+
+ clock.tick(50);
+ assertEquals(1, getCount);
+
+ p.setDelay(50);
+ assertEquals(2, getCount);
+
+ p.getObject(callback);
+ assertEquals(2, getCount);
+
+ clock.tick(20);
+ assertEquals(2, getCount);
+
+ p.setDelay(40);
+ assertEquals(2, getCount);
+
+ clock.tick(20);
+ assertEquals(3, getCount);
+
+ goog.dispose(clock);
+}
+
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/priorityqueue.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/priorityqueue.js.svn-base
new file mode 100644
index 0000000..07b2b28
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/priorityqueue.js.svn-base
@@ -0,0 +1,64 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Datastructure: Priority Queue.
+ *
+ *
+ * This file provides the implementation of a Priority Queue. Smaller priorities
+ * move to the front of the queue. If two values have the same priority,
+ * it is arbitrary which value will come to the front of the queue first.
+ */
+
+// TODO(user): Should this rely on natural ordering via some Comparable
+// interface?
+
+
+goog.provide('goog.structs.PriorityQueue');
+
+goog.require('goog.structs');
+goog.require('goog.structs.Heap');
+
+
+
+/**
+ * Class for Priority Queue datastructure.
+ *
+ * @constructor
+ * @extends {goog.structs.Heap}
+ */
+goog.structs.PriorityQueue = function() {
+ goog.structs.Heap.call(this);
+};
+goog.inherits(goog.structs.PriorityQueue, goog.structs.Heap);
+
+
+/**
+ * Puts the specified value in the queue.
+ * @param {*} priority The priority of the value.
+ * @param {*} value The value.
+ */
+goog.structs.PriorityQueue.prototype.enqueue = function(priority, value) {
+ this.insert(priority, value);
+};
+
+
+/**
+ * Retrieves and removes the head of this queue.
+ * @return {*} The element at the head of this queue. Returns
+ * undefined if the queue is empty.
+ */
+goog.structs.PriorityQueue.prototype.dequeue = function() {
+ return this.remove();
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/priorityqueue_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/priorityqueue_test.html.svn-base
new file mode 100644
index 0000000..ceae23c
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/priorityqueue_test.html.svn-base
@@ -0,0 +1,179 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2006 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs.PriorityQueue</title>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.structs');
+ goog.require('goog.structs.PriorityQueue');
+ goog.require('goog.testing.jsunit');
+</script>
+</head>
+<body>
+<script>
+
+function getPriorityQueue() {
+ var p = new goog.structs.PriorityQueue();
+ p.enqueue(0, 'a');
+ p.enqueue(1, 'b');
+ p.enqueue(2, 'c');
+ p.enqueue(3, 'd');
+ return p;
+}
+
+
+function getPriorityQueue2() {
+ var p = new goog.structs.PriorityQueue();
+ p.insert(1, 'b');
+ p.insert(3, 'd');
+ p.insert(0, 'a');
+ p.insert(2, 'c');
+ return p;
+}
+
+
+function testGetCount1() {
+ var p = getPriorityQueue();
+ assertEquals('count, should be 4', p.getCount(), 4);
+ p.dequeue();
+ assertEquals('count, should be 3', p.getCount(), 3);
+}
+
+
+function testGetCount2() {
+ var p = getPriorityQueue();
+ assertEquals('count, should be 4', p.getCount(), 4);
+ p.dequeue();
+ assertEquals('count, should be 3', p.getCount(), 3);
+}
+
+
+function testGetCount3() {
+ var p = getPriorityQueue();
+ p.dequeue();
+ p.dequeue();
+ p.dequeue();
+ p.dequeue();
+ assertEquals('count, should be 0', p.getCount(), 0);
+}
+
+
+function testKeys() {
+ var p = getPriorityQueue();
+ var keys = p.getKeys();
+ for (var i = 0; i < 4; i++) {
+ assertTrue('getKeys, key ' + i + ' found', goog.structs.contains(keys, i));
+ }
+ assertEquals('getKeys, Should be 4 keys', goog.structs.getCount(keys), 4);
+}
+
+
+function testValues() {
+ var p = getPriorityQueue();
+ var values = p.getValues();
+
+ assertTrue('getKeys, value "a" found', goog.structs.contains(values, 'a'));
+ assertTrue('getKeys, value "b" found', goog.structs.contains(values, 'b'));
+ assertTrue('getKeys, value "c" found', goog.structs.contains(values, 'c'));
+ assertTrue('getKeys, value "d" found', goog.structs.contains(values, 'd'));
+ assertEquals('getKeys, Should be 4 keys', goog.structs.getCount(values), 4);
+}
+
+
+function testClear() {
+ var p = getPriorityQueue();
+ p.clear();
+ assertTrue('cleared so it should be empty', p.isEmpty());
+}
+
+
+function testIsEmpty() {
+ var p = getPriorityQueue();
+ assertFalse('4 values so should not be empty', p.isEmpty());
+
+ p.dequeue();
+ p.dequeue();
+ p.dequeue();
+ assertFalse('1 values so should not be empty', p.isEmpty());
+
+ p.dequeue();
+ assertTrue('0 values so should be empty', p.isEmpty());
+}
+
+
+function testPeek1() {
+ var p = getPriorityQueue();
+ assertEquals('peek, Should be "a"', p.peek(), 'a');
+}
+
+
+function testPeek2() {
+ var p = getPriorityQueue2();
+ assertEquals('peek, Should be "a"', p.peek(), 'a');
+}
+
+
+function testPeek3() {
+ var p = getPriorityQueue();
+ p.clear();
+ assertEquals('peek, Should be "a"', p.peek(), undefined);
+}
+
+
+function testDequeue1() {
+ var p = getPriorityQueue();
+
+ assertEquals('dequeue, Should be "a"', p.dequeue(), 'a');
+ assertEquals('dequeue, Should be "b"', p.dequeue(), 'b');
+ assertEquals('dequeue, Should be "c"', p.dequeue(), 'c');
+ assertEquals('dequeue, Should be "d"', p.dequeue(), 'd');
+}
+
+
+function testDequeue2() {
+ var p = getPriorityQueue2();
+
+ assertEquals('dequeue, Should be "a"', p.dequeue(), 'a');
+ assertEquals('dequeue, Should be "b"', p.dequeue(), 'b');
+ assertEquals('dequeue, Should be "c"', p.dequeue(), 'c');
+ assertEquals('dequeue, Should be "d"', p.dequeue(), 'd');
+}
+
+
+function testEnqueuePeek1() {
+ var p = new goog.structs.PriorityQueue();
+
+ p.enqueue(3, 'd');
+ assertEquals('peak, Should be "d"', p.peek(), 'd');
+ p.enqueue(2, 'c');
+ assertEquals('peak, Should be "c"', p.peek(), 'c');
+ p.enqueue(1, 'b');
+ assertEquals('peak, Should be "b"', p.peek(), 'b');
+ p.enqueue(0, 'a');
+ assertEquals('peak, Should be "a"', p.peek(), 'a');
+}
+
+
+function testEnqueuePeek2() {
+ var p = new goog.structs.PriorityQueue();
+
+ p.enqueue(1, 'b');
+ assertEquals('peak, Should be "b"', p.peek(), 'b');
+ p.enqueue(3, 'd');
+ assertEquals('peak, Should be "b"', p.peek(), 'b');
+ p.enqueue(0, 'a');
+ assertEquals('peak, Should be "a"', p.peek(), 'a');
+ p.enqueue(2, 'c');
+ assertEquals('peak, Should be "a"', p.peek(), 'a');
+}
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/quadtree.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/quadtree.js.svn-base
new file mode 100644
index 0000000..db52476
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/quadtree.js.svn-base
@@ -0,0 +1,571 @@
+// Copyright 2008 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Datastructure: A point Quad Tree for representing 2D data. Each
+ * region has the same ratio as the bounds for the tree.
+ *
+ * The implementation currently requires pre-determined bounds for data as it
+ * can not rebalance itself to that degree.
+ *
+ * @see ../demos/quadtree.html
+ */
+
+
+goog.provide('goog.structs.QuadTree');
+goog.provide('goog.structs.QuadTree.Node');
+goog.provide('goog.structs.QuadTree.Point');
+
+goog.require('goog.math.Coordinate');
+
+
+
+/**
+ * Constructs a new quad tree.
+ * @param {number} minX Minimum x-value that can be held in tree.
+ * @param {number} minY Minimum y-value that can be held in tree.
+ * @param {number} maxX Maximum x-value that can be held in tree.
+ * @param {number} maxY Maximum y-value that can be held in tree.
+ * @constructor
+ */
+goog.structs.QuadTree = function(minX, minY, maxX, maxY) {
+
+ /**
+ * The root node for the quad tree.
+ * @type {goog.structs.QuadTree.Node}
+ * @private
+ */
+ this.root_ = new goog.structs.QuadTree.Node(
+ minX, minY, maxX - minX, maxY - minY);
+};
+
+
+/**
+ * Count of the number of items in the tree.
+ * @type {number}
+ * @private
+ */
+goog.structs.QuadTree.prototype.count_ = 0;
+
+
+/**
+ * Returns a reference to the tree's root node. Callers shouldn't modify nodes,
+ * directly. This is a convenience for visualization and debugging purposes.
+ * @return {goog.structs.QuadTree.Node} The root node.
+ */
+goog.structs.QuadTree.prototype.getRootNode = function() {
+ return this.root_;
+};
+
+
+/**
+ * Sets the value of an (x, y) point within the quad-tree.
+ * @param {number} x The x-coordinate.
+ * @param {number} y The y-coordinate.
+ * @param {*} value The value associated with the point.
+ */
+goog.structs.QuadTree.prototype.set = function(x, y, value) {
+ var root = this.root_;
+ if (x < root.x || y < root.y || x > root.x + root.w || y > root.y + root.h) {
+ throw Error('Out of bounds : (' + x + ', ' + y + ')');
+ }
+ if (this.insert_(root, new goog.structs.QuadTree.Point(x, y, value))) {
+ this.count_++;
+ }
+};
+
+
+/**
+ * Gets the value of the point at (x, y) or null if the point is empty.
+ * @param {number} x The x-coordinate.
+ * @param {number} y The y-coordinate.
+ * @param {*=} opt_default The default value to return if the node doesn't
+ * exist.
+ * @return {*} The value of the node, the default value if the node
+ * doesn't exist, or undefined if the node doesn't exist and no default
+ * has been provided.
+ */
+goog.structs.QuadTree.prototype.get = function(x, y, opt_default) {
+ var node = this.find_(this.root_, x, y);
+ return node ? node.point.value : opt_default;
+};
+
+
+/**
+ * Removes a point from (x, y) if it exists.
+ * @param {number} x The x-coordinate.
+ * @param {number} y The y-coordinate.
+ * @return {*} The value of the node that was removed, or null if the
+ * node doesn't exist.
+ */
+goog.structs.QuadTree.prototype.remove = function(x, y) {
+ var node = this.find_(this.root_, x, y);
+ if (node) {
+ var value = node.point.value;
+ node.point = null;
+ node.nodeType = goog.structs.QuadTree.NodeType.EMPTY;
+ this.balance_(node);
+ this.count_--;
+ return value;
+ } else {
+ return null;
+ }
+};
+
+
+/**
+ * Returns true if the point at (x, y) exists in the tree.
+ * @param {number} x The x-coordinate.
+ * @param {number} y The y-coordinate.
+ * @return {boolean} Whether the tree contains a point at (x, y).
+ */
+goog.structs.QuadTree.prototype.contains = function(x, y) {
+ return this.get(x, y) != null;
+};
+
+
+/**
+ * @return {boolean} Whether the tree is empty.
+ */
+goog.structs.QuadTree.prototype.isEmpty = function() {
+ return this.root_.nodeType == goog.structs.QuadTree.NodeType.EMPTY;
+};
+
+
+/**
+ * @return {number} The number of items in the tree.
+ */
+goog.structs.QuadTree.prototype.getCount = function() {
+ return this.count_;
+};
+
+
+/**
+ * Removes all items from the tree.
+ */
+goog.structs.QuadTree.prototype.clear = function() {
+ this.root_.nw = this.root_.ne = this.root_.sw = this.root_.se = null;
+ this.root_.nodeType = goog.structs.QuadTree.NodeType.EMPTY;
+ this.root_.point = null;
+ this.count_ = 0;
+};
+
+
+/**
+ * Returns an array containing the coordinates of each point stored in the tree.
+ * @return {Array.<goog.math.Coordinate?>} Array of coordinates.
+ */
+goog.structs.QuadTree.prototype.getKeys = function() {
+ var arr = [];
+ this.traverse_(this.root_, function(node) {
+ arr.push(new goog.math.Coordinate(node.point.x, node.point.y));
+ });
+ return arr;
+};
+
+
+/**
+ * Returns an array containing all values stored within the tree.
+ * @return {Array.<Object>} The values stored within the tree.
+ */
+goog.structs.QuadTree.prototype.getValues = function() {
+ var arr = [];
+ this.traverse_(this.root_, function(node) {
+ // Must have a point because it's a leaf.
+ arr.push(node.point.value);
+ });
+ return arr;
+};
+
+
+/**
+ * Clones the quad-tree and returns the new instance.
+ * @return {goog.structs.QuadTree} A clone of the tree.
+ */
+goog.structs.QuadTree.prototype.clone = function() {
+ var x1 = this.root_.x;
+ var y1 = this.root_.y;
+ var x2 = x1 + this.root_.w;
+ var y2 = y1 + this.root_.h;
+ var clone = new goog.structs.QuadTree(x1, y1, x2, y2);
+ // This is inefficient as the clone needs to recalculate the structure of the
+ // tree, even though we know it already. But this is easier and can be
+ // optimized when/if needed.
+ this.traverse_(this.root_, function(node) {
+ clone.set(node.point.x, node.point.y, node.point.value);
+ });
+ return clone;
+};
+
+
+/**
+ * Traverses the tree and calls a function on each node.
+ * @param {function(Object, goog.math.Coordinate, goog.structs.QuadTree)} fn
+ * The function to call for every value. This function takes 3 arguments
+ * (the value, the coordinate, and the tree itself) and the return value is
+ * irrelevant.
+ * @param {Object=} opt_obj The object to be used as the value of 'this'
+ * within {@ code fn}.
+ */
+goog.structs.QuadTree.prototype.forEach = function(fn, opt_obj) {
+ this.traverse_(this.root_, function(node) {
+ var coord = new goog.math.Coordinate(node.point.x, node.point.y);
+ fn.call(opt_obj, node.point.value, coord, this);
+ });
+};
+
+
+/**
+ * Traverses the tree depth-first, with quadrants being traversed in clockwise
+ * order (NE, SE, SW, NW). The provided function will be called for each
+ * leaf node that is encountered.
+ * @param {goog.structs.QuadTree.Node} node The current node.
+ * @param {function(goog.structs.QuadTree.Node)} fn The function to call
+ * for each leaf node. This function takes the node as an argument, and its
+ * return value is irrelevant.
+ * @private
+ */
+goog.structs.QuadTree.prototype.traverse_ = function(node, fn) {
+ switch (node.nodeType) {
+ case goog.structs.QuadTree.NodeType.LEAF:
+ fn.call(this, node);
+ break;
+
+ case goog.structs.QuadTree.NodeType.POINTER:
+ this.traverse_(node.ne, fn);
+ this.traverse_(node.se, fn);
+ this.traverse_(node.sw, fn);
+ this.traverse_(node.nw, fn);
+ break;
+ }
+};
+
+
+/**
+ * Finds a leaf node with the same (x, y) coordinates as the target point, or
+ * null if no point exists.
+ * @param {goog.structs.QuadTree.Node} node The node to search in.
+ * @param {number} x The x-coordinate of the point to search for.
+ * @param {number} y The y-coordinate of the point to search for.
+ * @return {goog.structs.QuadTree.Node} The leaf node that matches the target,
+ * or null if it doesn't exist.
+ * @private
+ */
+goog.structs.QuadTree.prototype.find_ = function(node, x, y) {
+ switch (node.nodeType) {
+ case goog.structs.QuadTree.NodeType.EMPTY:
+ return null;
+
+ case goog.structs.QuadTree.NodeType.LEAF:
+ return node.point.x == x && node.point.y == y ? node : null;
+
+ case goog.structs.QuadTree.NodeType.POINTER:
+ return this.find_(this.getQuadrantForPoint_(node, x, y), x, y);
+
+ default:
+ throw Error('Invalid nodeType');
+ }
+};
+
+
+/**
+ * Inserts a point into the tree, updating the tree's structure if necessary.
+ * @param {goog.structs.QuadTree.Node} parent The parent to insert the point
+ * into.
+ * @param {goog.structs.QuadTree.Point} point The point to insert.
+ * @return {boolean} True if a new node was added to the tree; False if a node
+ * already existed with the correpsonding coordinates and had its value
+ * reset.
+ * @private
+ */
+goog.structs.QuadTree.prototype.insert_ = function(parent, point) {
+ switch (parent.nodeType) {
+ case goog.structs.QuadTree.NodeType.EMPTY:
+ this.setPointForNode_(parent, point);
+ return true;
+
+ case goog.structs.QuadTree.NodeType.LEAF:
+ if (parent.point.x == point.x && parent.point.y == point.y) {
+ this.setPointForNode_(parent, point);
+ return false;
+ } else {
+ this.split_(parent);
+ return this.insert_(parent, point);
+ }
+
+ case goog.structs.QuadTree.NodeType.POINTER:
+ return this.insert_(
+ this.getQuadrantForPoint_(parent, point.x, point.y), point);
+
+ default:
+ throw Error('Invalid nodeType in parent');
+ }
+};
+
+
+/**
+ * Converts a leaf node to a pointer node and reinserts the node's point into
+ * the correct child.
+ * @param {goog.structs.QuadTree.Node} node The node to split.
+ * @private
+ */
+goog.structs.QuadTree.prototype.split_ = function(node) {
+ var oldPoint = node.point;
+ node.point = null;
+
+ node.nodeType = goog.structs.QuadTree.NodeType.POINTER;
+
+ var x = node.x;
+ var y = node.y;
+ var hw = node.w / 2;
+ var hh = node.h / 2;
+
+ node.nw = new goog.structs.QuadTree.Node(x, y, hw, hh, node);
+ node.ne = new goog.structs.QuadTree.Node(x + hw, y, hw, hh, node);
+ node.sw = new goog.structs.QuadTree.Node(x, y + hh, hw, hh, node);
+ node.se = new goog.structs.QuadTree.Node(x + hw, y + hh, hw, hh, node);
+
+ this.insert_(node, oldPoint);
+};
+
+
+/**
+ * Attempts to balance a node. A node will need balancing if all its children
+ * are empty or it contains just one leaf.
+ * @param {goog.structs.QuadTree.Node} node The node to balance.
+ * @private
+ */
+goog.structs.QuadTree.prototype.balance_ = function(node) {
+ switch (node.nodeType) {
+ case goog.structs.QuadTree.NodeType.EMPTY:
+ case goog.structs.QuadTree.NodeType.LEAF:
+ if (node.parent) {
+ this.balance_(node.parent);
+ }
+ break;
+
+ case goog.structs.QuadTree.NodeType.POINTER:
+ var nw = node.nw, ne = node.ne, sw = node.sw, se = node.se;
+ var firstLeaf = null;
+
+ // Look for the first non-empty child, if there is more than one then we
+ // break as this node can't be balanced.
+ if (nw.nodeType != goog.structs.QuadTree.NodeType.EMPTY) {
+ firstLeaf = nw;
+ }
+ if (ne.nodeType != goog.structs.QuadTree.NodeType.EMPTY) {
+ if (firstLeaf) {
+ break;
+ }
+ firstLeaf = ne;
+ }
+ if (sw.nodeType != goog.structs.QuadTree.NodeType.EMPTY) {
+ if (firstLeaf) {
+ break;
+ }
+ firstLeaf = sw;
+ }
+ if (se.nodeType != goog.structs.QuadTree.NodeType.EMPTY) {
+ if (firstLeaf) {
+ break;
+ }
+ firstLeaf = se;
+ }
+
+ if (!firstLeaf) {
+ // All child nodes are empty: so make this node empty.
+ node.nodeType = goog.structs.QuadTree.NodeType.EMPTY;
+ node.nw = node.ne = node.sw = node.se = null;
+
+ } else if (firstLeaf.nodeType == goog.structs.QuadTree.NodeType.POINTER) {
+ // Only child was a pointer, therefore we can't rebalance.
+ break;
+
+ } else {
+ // Only child was a leaf: so update node's point and make it a leaf.
+ node.nodeType = goog.structs.QuadTree.NodeType.LEAF;
+ node.nw = node.ne = node.sw = node.se = null;
+ node.point = firstLeaf.point;
+ }
+
+ // Try and balance the parent as well.
+ if (node.parent) {
+ this.balance_(node.parent);
+ }
+
+ break;
+ }
+};
+
+
+/**
+ * Returns the child quadrant within a node that contains the given (x, y)
+ * coordinate.
+ * @param {goog.structs.QuadTree.Node} parent The node.
+ * @param {number} x The x-coordinate to look for.
+ * @param {number} y The y-coordinate to look for.
+ * @return {goog.structs.QuadTree.Node} The child quadrant that contains the
+ * point.
+ * @private
+ */
+goog.structs.QuadTree.prototype.getQuadrantForPoint_ = function(parent, x, y) {
+ var mx = parent.x + parent.w / 2;
+ var my = parent.y + parent.h / 2;
+ if (x < mx) {
+ return y < my ? parent.nw : parent.sw;
+ } else {
+ return y < my ? parent.ne : parent.se;
+ }
+};
+
+
+/**
+ * Sets the point for a node, as long as the node is a leaf or empty.
+ * @param {goog.structs.QuadTree.Node} node The node to set the point for.
+ * @param {goog.structs.QuadTree.Point} point The point to set.
+ * @private
+ */
+goog.structs.QuadTree.prototype.setPointForNode_ = function(node, point) {
+ if (node.nodeType == goog.structs.QuadTree.NodeType.POINTER) {
+ throw Error('Can not set point for node of type POINTER');
+ }
+ node.nodeType = goog.structs.QuadTree.NodeType.LEAF;
+ node.point = point;
+};
+
+
+/**
+ * Enumeration of node types.
+ * @enum {number}
+ */
+goog.structs.QuadTree.NodeType = {
+ EMPTY: 0,
+ LEAF: 1,
+ POINTER: 2
+};
+
+
+
+/**
+ * Constructs a new quad tree node.
+ * @param {number} x X-coordiate of node.
+ * @param {number} y Y-coordinate of node.
+ * @param {number} w Width of node.
+ * @param {number} h Height of node.
+ * @param {goog.structs.QuadTree.Node=} opt_parent Optional parent node.
+ * @constructor
+ */
+goog.structs.QuadTree.Node = function(x, y, w, h, opt_parent) {
+ /**
+ * The x-coordinate of the node.
+ * @type {number}
+ */
+ this.x = x;
+
+ /**
+ * The y-coordinate of the node.
+ * @type {number}
+ */
+ this.y = y;
+
+ /**
+ * The width of the node.
+ * @type {number}
+ */
+ this.w = w;
+
+ /**
+ * The height of the node.
+ * @type {number}
+ */
+ this.h = h;
+
+ /**
+ * The parent node.
+ * @type {goog.structs.QuadTree.Node?}
+ */
+ this.parent = opt_parent || null;
+};
+
+
+/**
+ * The node's type.
+ * @type {goog.structs.QuadTree.NodeType}
+ */
+goog.structs.QuadTree.Node.prototype.nodeType =
+ goog.structs.QuadTree.NodeType.EMPTY;
+
+
+/**
+ * The child node in the North-West quadrant.
+ * @type {goog.structs.QuadTree.Node?}
+ */
+goog.structs.QuadTree.Node.prototype.nw = null;
+
+
+/**
+ * The child node in the North-East quadrant.
+ * @type {goog.structs.QuadTree.Node?}
+ */
+goog.structs.QuadTree.Node.prototype.ne = null;
+
+
+/**
+ * The child node in the South-West quadrant.
+ * @type {goog.structs.QuadTree.Node?}
+ */
+goog.structs.QuadTree.Node.prototype.sw = null;
+
+
+/**
+ * The child node in the South-East quadrant.
+ * @type {goog.structs.QuadTree.Node?}
+ */
+goog.structs.QuadTree.Node.prototype.se = null;
+
+
+/**
+ * The point for the node, if it is a leaf node.
+ * @type {goog.structs.QuadTree.Point?}
+ */
+goog.structs.QuadTree.Node.prototype.point = null;
+
+
+
+/**
+ * Creates a new point object.
+ * @param {number} x The x-coordinate of the point.
+ * @param {number} y The y-coordinate of the point.
+ * @param {*=} opt_value Optional value associated with the point.
+ * @constructor
+ */
+goog.structs.QuadTree.Point = function(x, y, opt_value) {
+ /**
+ * The x-coordinate for the point.
+ * @type {number}
+ */
+ this.x = x;
+
+ /**
+ * The y-coordinate for the point.
+ * @type {number}
+ */
+ this.y = y;
+
+ /**
+ * Optional value associated with the point.
+ * @type {*}
+ */
+ this.value = goog.isDef(opt_value) ? opt_value : null;
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/quadtree_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/quadtree_test.html.svn-base
new file mode 100644
index 0000000..c51e144
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/quadtree_test.html.svn-base
@@ -0,0 +1,179 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2008 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs.QuadTree</title>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.array');
+ goog.require('goog.structs');
+ goog.require('goog.structs.QuadTree');
+ goog.require('goog.testing.jsunit');
+</script>
+</head>
+<body>
+<script>
+
+ function getTree() {
+ var qt = new goog.structs.QuadTree(0, 0, 100, 100);
+ qt.set(5, 20, 'Foo');
+ qt.set(50, 32, 'Bar');
+ qt.set(47, 96, 'Baz');
+ qt.set(50, 50, 'Bing');
+ qt.set(12, 0, 'Bong');
+ return qt;
+ }
+
+ function testGetCount() {
+ var qt = getTree();
+ assertEquals('Count should be 5', 5, qt.getCount());
+ qt.remove(50, 32);
+ assertEquals('Count should be 4', 4, qt.getCount());
+ }
+
+ function testGetKeys() {
+ var keys = getTree().getKeys();
+ var keyString = keys.sort().join(' ');
+ var expected = '(12, 0) (47, 96) (5, 20) (50, 32) (50, 50)';
+ assertEquals('Sorted keys should be ' + expected, expected, keyString);
+ }
+
+ function testGetValues() {
+ var values = getTree().getValues();
+ var valueString = values.sort().join(',');
+ assertEquals('Sorted values should be Bar,Baz,Bing,Bong,Foo',
+ 'Bar,Baz,Bing,Bong,Foo', valueString);
+ }
+
+ function testContains() {
+ var qt = getTree();
+ assertTrue('Should contain (5, 20)', qt.contains(5, 20));
+ assertFalse('Should not contain (13, 13)', qt.contains(13, 13));
+ }
+
+ function testClear() {
+ var qt = getTree();
+ qt.clear();
+ assertTrue('Tree should be empty', qt.isEmpty());
+ assertFalse('Tree should not contain (5, 20)', qt.contains(5, 20));
+ }
+
+ function testConstructor() {
+ var qt = new goog.structs.QuadTree(-10, -5, 6, 12);
+ var root = qt.getRootNode();
+ assertEquals('X of root should be -10', -10, root.x);
+ assertEquals('Y of root should be -5', -5, root.y);
+ assertEquals('Width of root should be 16', 16, root.w);
+ assertEquals('Height of root should be 17', 17, root.h);
+ assertTrue('Tree should be empty', qt.isEmpty());
+ }
+
+ function testClone() {
+ var qt = getTree().clone();
+ assertFalse('Clone should not be empty', qt.isEmpty());
+ assertTrue('Should contain (47, 96)', qt.contains(47, 96));
+ }
+
+ function testRemove() {
+ var qt = getTree();
+ assertEquals('(5, 20) should be removed', 'Foo', qt.remove(5, 20));
+ assertEquals('(5, 20) should be removed', 'Bar', qt.remove(50, 32));
+ assertEquals('(5, 20) should be removed', 'Baz', qt.remove(47, 96));
+ assertEquals('(5, 20) should be removed', 'Bing', qt.remove(50, 50));
+ assertEquals('(5, 20) should be removed', 'Bong', qt.remove(12, 0));
+ assertNull('(6, 6) wasn\'t there to remove', qt.remove(6, 6));
+ assertTrue('Tree should be empty', qt.isEmpty());
+ assertTreesChildrenAreNull(qt)
+ }
+
+ function testIsEmpty() {
+ var qt = getTree();
+ qt.clear();
+ assertTrue(qt.isEmpty());
+ assertEquals('Root should be empty node',
+ goog.structs.QuadTree.NodeType.EMPTY, qt.getRootNode().nodeType);
+ assertTreesChildrenAreNull(qt);
+ }
+
+ function testForEach() {
+ var qt = getTree();
+ var s = '';
+ goog.structs.forEach(qt, function(val, key, qt2) {
+ assertNotUndefined(key);
+ assertEquals(qt, qt2);
+ s += key.x + ',' + key.y + '=' + val + ' ';
+ });
+ assertEquals('50,32=Bar 50,50=Bing 47,96=Baz 5,20=Foo 12,0=Bong ', s);
+ }
+
+ function testBalancing() {
+ var qt = new goog.structs.QuadTree(0, 0, 100, 100);
+ var root = qt.getRootNode();
+
+ // Add a point to the NW quadrant.
+ qt.set(25, 25, 'first');
+
+ assertEquals('Root should be a leaf node.',
+ goog.structs.QuadTree.NodeType.LEAF, root.nodeType);
+ assertTreesChildrenAreNull(qt);
+
+ assertEquals('first', root.point.value);
+
+ // Add another point in the NW quadrant
+ qt.set(25, 30, 'second');
+
+ assertEquals('Root should now be a pointer.',
+ goog.structs.QuadTree.NodeType.POINTER, root.nodeType);
+ assertNotNull('NE should be not be null', root.ne);
+ assertNotNull('NW should be not be null', root.nw);
+ assertNotNull('SE should be not be null', root.se);
+ assertNotNull('SW should be not be null', root.sw);
+ assertNull(root.point);
+
+ // Delete the second point.
+ qt.remove(25, 30);
+
+ assertEquals('Root should have been rebalanced and be a leaf node.',
+ goog.structs.QuadTree.NodeType.LEAF, root.nodeType);
+ assertTreesChildrenAreNull(qt);
+ assertEquals('first', root.point.value);
+ }
+
+ function testTreeBounds() {
+ var qt = getTree();
+ assertFails(qt, qt.set, [-10, -10, 1]);
+ assertFails(qt, qt.set, [-10, 10, 2]);
+ assertFails(qt, qt.set, [10, -10, 3]);
+ assertFails(qt, qt.set, [-10, 110, 4]);
+ assertFails(qt, qt.set, [10, 130, 5]);
+ assertFails(qt, qt.set, [110, -10, 6]);
+ assertFails(qt, qt.set, [150, 14, 7]);
+ }
+
+ // Helper functions
+
+ function assertFails(context, fn, args) {
+ assertThrows('Exception expected from ' + fn.toString() +
+ ' with arguments ' + args,
+ function() {
+ fn.apply(context, args);
+ });
+ }
+
+ function assertTreesChildrenAreNull(qt) {
+ var root = qt.getRootNode();
+ assertNull('NE should be null', root.ne);
+ assertNull('NW should be null', root.nw);
+ assertNull('SE should be null', root.se);
+ assertNull('SW should be null', root.sw);
+ }
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/queue.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/queue.js.svn-base
new file mode 100644
index 0000000..3be02f5
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/queue.js.svn-base
@@ -0,0 +1,157 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Datastructure: Queue.
+ *
+ *
+ * This file provides the implementation of a FIFO Queue structure.
+ * API is similar to that of com.google.common.collect.IntQueue
+ */
+
+goog.provide('goog.structs.Queue');
+
+goog.require('goog.array');
+
+
+
+/**
+ * Class for FIFO Queue data structure.
+ *
+ * @constructor
+ */
+goog.structs.Queue = function() {
+ this.elements_ = [];
+};
+
+
+/**
+ * The index of the next element to be removed from the queue.
+ * @private
+ * @type {number}
+ */
+goog.structs.Queue.prototype.head_ = 0;
+
+
+/**
+ * The index at which the next element would be added to the queue.
+ * @private
+ * @type {number}
+ */
+goog.structs.Queue.prototype.tail_ = 0;
+
+
+/**
+ * Puts the specified element on this queue.
+ * @param {*} element The element to be added to the queue.
+ */
+goog.structs.Queue.prototype.enqueue = function(element) {
+ this.elements_[this.tail_++] = element;
+};
+
+
+/**
+ * Retrieves and removes the head of this queue.
+ * @return {*} The element at the head of this queue. Returns undefined if the
+ * queue is empty.
+ */
+goog.structs.Queue.prototype.dequeue = function() {
+ if (this.head_ == this.tail_) {
+ return undefined;
+ }
+ var result = this.elements_[this.head_];
+ delete this.elements_[this.head_];
+ this.head_++;
+ return result;
+};
+
+
+/**
+ * Retrieves but does not remove the head of this queue.
+ * @return {*} The element at the head of this queue. Returns undefined if the
+ * queue is empty.
+ */
+goog.structs.Queue.prototype.peek = function() {
+ if (this.head_ == this.tail_) {
+ return undefined;
+ }
+ return this.elements_[this.head_];
+};
+
+
+/**
+ * Returns the number of elements in this queue.
+ * @return {number} The number of elements in this queue.
+ */
+goog.structs.Queue.prototype.getCount = function() {
+ return this.tail_ - this.head_;
+};
+
+
+/**
+ * Returns true if this queue contains no elements.
+ * @return {boolean} true if this queue contains no elements.
+ */
+goog.structs.Queue.prototype.isEmpty = function() {
+ return this.tail_ - this.head_ == 0;
+};
+
+
+/**
+ * Removes all elements from the queue.
+ */
+goog.structs.Queue.prototype.clear = function() {
+ this.elements_.length = 0;
+ this.head_ = 0;
+ this.tail_ = 0;
+};
+
+
+/**
+ * Returns true if the given value is in the queue.
+ * @param {*} obj The value to look for.
+ * @return {boolean} Whether the object is in the queue.
+ */
+goog.structs.Queue.prototype.contains = function(obj) {
+ return goog.array.contains(this.elements_, obj);
+};
+
+
+/**
+ * Removes the first occurrence of a particular value from the queue.
+ * @param {*} obj Object to remove.
+ * @return {boolean} True if an element was removed.
+ */
+goog.structs.Queue.prototype.remove = function(obj) {
+ var index = goog.array.indexOf(this.elements_, obj);
+ if (index < 0) {
+ return false;
+ }
+ if (index == this.head_) {
+ this.dequeue();
+ } else {
+ goog.array.removeAt(this.elements_, index);
+ this.tail_--;
+ }
+ return true;
+};
+
+
+/**
+ * Returns all the values in the queue.
+ * @return {Array} An array of the values in the queue.
+ */
+goog.structs.Queue.prototype.getValues = function() {
+ return this.elements_.slice(this.head_, this.tail_);
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/queue_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/queue_test.html.svn-base
new file mode 100644
index 0000000..bbfae75
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/queue_test.html.svn-base
@@ -0,0 +1,140 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2006 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs.Queue</title>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.structs.Queue');
+ goog.require('goog.testing.jsunit');
+</script>
+</head>
+<body>
+<script>
+
+function stringifyQueue(q) {
+ var values = q.getValues();
+ var s = '';
+ for (var i = 0; i < values.length; i++) {
+ s += values[i];
+ }
+ return s;
+}
+
+function createQueue() {
+ var q = new goog.structs.Queue();
+ q.enqueue('a');
+ q.enqueue('b');
+ q.enqueue('c');
+ return q;
+}
+
+function testConstructor() {
+ var q = new goog.structs.Queue();
+ assertTrue('testConstructor(), queue should be empty initially', q.isEmpty());
+ assertEquals('testConstructor(), count should be 0', q.getCount(), 0);
+ assertEquals('testConstructor(), head element should be undefined', q.peek(),
+ undefined);
+}
+
+function testCount() {
+ var q = createQueue();
+ assertEquals('testCount(), count should be 3', q.getCount(), 3);
+ q.enqueue('d');
+ assertEquals('testCount(), count should be 4', q.getCount(), 4);
+ q.dequeue();
+ assertEquals('testCount(), count should be 3', q.getCount(), 3);
+ q.clear();
+ assertEquals('testCount(), count should be 0', q.getCount(), 0);
+}
+
+function testEnqueue() {
+ var q = new goog.structs.Queue();
+ q.enqueue('a');
+ assertEquals('testEnqueue(), count should be 1', q.getCount(), 1);
+ q.enqueue('b');
+ assertEquals('testEnqueue(), count should be 2', q.getCount(), 2);
+ assertEquals('testEnqueue(), head element should be a', q.peek(), 'a');
+ q.dequeue();
+ assertEquals('testEnqueue(), count should be 1', q.getCount(), 1);
+ assertEquals('testEnqueue(), head element should be b', q.peek(), 'b');
+}
+
+function testDequeue() {
+ var q = createQueue();
+ var head = q.dequeue();
+ assertEquals('testDequeue(), should return a', head, 'a');
+ q.dequeue();
+ head = q.dequeue();
+ assertEquals('testDequeue(), should return c', head, 'c');
+ assertTrue('testDequeue(), queue should be empty', q.isEmpty());
+ head = q.dequeue();
+ assertEquals('testDequeue(), should return undefined for empty queue', head,
+ undefined);
+}
+
+function testPeek() {
+ var q = createQueue();
+ var head = q.peek();
+ assertEquals('testPeek(), should return a', head, 'a');
+ var head2 = q.dequeue();
+ assertEquals('testPeek(), dequeue should return peek() result', head, head2);
+ head = q.peek();
+ assertEquals('testPeek(), should return b', head, 'b');
+ q.clear();
+ head = q.peek();
+ assertEquals('testPeek(), should return undefined for empty queue', head,
+ undefined);
+}
+
+function testClear() {
+ var q = createQueue();
+ q.clear();
+ assertTrue('testClear(), queue should be empty', q.isEmpty());
+}
+
+function testQueue() {
+ var q = createQueue();
+ assertEquals('testQueue(), contents must be abc', stringifyQueue(q), 'abc');
+}
+
+function testRemove() {
+ var q = createQueue();
+ assertEquals('testRemove(), contents must be abc', stringifyQueue(q), 'abc');
+
+ q.dequeue();
+ assertEquals('testRemove(), contents must be bc', stringifyQueue(q), 'bc');
+
+ q.enqueue('a');
+ assertEquals('testRemove(), contents must be bca', stringifyQueue(q), 'bca');
+
+ assertTrue('testRemove(), remove should have returned true', q.remove('c'));
+ assertEquals('testRemove(), contents must be ba', stringifyQueue(q), 'ba');
+
+ assertTrue('testRemove(), remove should have returned true', q.remove('b'));
+ assertEquals('testRemove(), contents must be a', stringifyQueue(q), 'a');
+
+ assertFalse('testRemove(), remove should have returned false', q.remove('b'));
+ assertEquals('testRemove(), contents must be a', stringifyQueue(q), 'a');
+
+ assertTrue('testRemove(), remove should have returned true', q.remove('a'));
+ assertEquals('testRemove(), contents must be empty', stringifyQueue(q), '');
+}
+
+function testContains() {
+ var q = createQueue();
+ assertTrue('testContains(), contains should have returned true',
+ q.contains('a'));
+ assertFalse('testContains(), contains should have returned false',
+ q.contains('foobar'));
+}
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/set.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/set.js.svn-base
new file mode 100644
index 0000000..4719f6a
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/set.js.svn-base
@@ -0,0 +1,255 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Datastructure: Set.
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ * @author pallosp@google.com (Peter Pallos)
+ *
+ * This class implements a set data structure. Adding and removing is O(1). It
+ * supports both object and primitive values. Be careful because you can add
+ * both 1 and new Number(1), because these are not the same. You can even add
+ * multiple new Number(1) because these are not equal.
+ */
+
+
+goog.provide('goog.structs.Set');
+
+goog.require('goog.structs');
+goog.require('goog.structs.Collection');
+goog.require('goog.structs.Map');
+
+
+
+/**
+ * A set that can contain both primitives and objects. Adding and removing
+ * elements is O(1). Primitives are treated as identical if they have the same
+ * type and convert to the same string. Objects are treated as identical only
+ * if they are references to the same object. WARNING: A goog.structs.Set can
+ * contain both 1 and (new Number(1)), because they are not the same. WARNING:
+ * Adding (new Number(1)) twice will yield two distinct elements, because they
+ * are two different objects. WARNING: Any object that is added to a
+ * goog.structs.Set will be modified! Because goog.getUid() is used to
+ * identify objects, every object in the set will be mutated.
+ * @param {Array|Object=} opt_values Initial values to start with.
+ * @constructor
+ * @implements {goog.structs.Collection}
+ */
+goog.structs.Set = function(opt_values) {
+ this.map_ = new goog.structs.Map;
+ if (opt_values) {
+ this.addAll(opt_values);
+ }
+};
+
+
+/**
+ * Obtains a unique key for an element of the set. Primitives will yield the
+ * same key if they have the same type and convert to the same string. Object
+ * references will yield the same key only if they refer to the same object.
+ * @param {*} val Object or primitive value to get a key for.
+ * @return {string} A unique key for this value/object.
+ * @private
+ */
+goog.structs.Set.getKey_ = function(val) {
+ var type = typeof val;
+ if (type == 'object' && val || type == 'function') {
+ return 'o' + goog.getUid(/** @type {Object} */ (val));
+ } else {
+ return type.substr(0, 1) + val;
+ }
+};
+
+
+/**
+ * @return {number} The number of elements in the set.
+ */
+goog.structs.Set.prototype.getCount = function() {
+ return this.map_.getCount();
+};
+
+
+/**
+ * Add a primitive or an object to the set.
+ * @param {*} element The primitive or object to add.
+ */
+goog.structs.Set.prototype.add = function(element) {
+ this.map_.set(goog.structs.Set.getKey_(element), element);
+};
+
+
+/**
+ * Adds all the values in the given collection to this set.
+ * @param {Array|Object} col A collection containing the elements to add.
+ */
+goog.structs.Set.prototype.addAll = function(col) {
+ var values = goog.structs.getValues(col);
+ var l = values.length;
+ for (var i = 0; i < l; i++) {
+ this.add(values[i]);
+ }
+};
+
+
+/**
+ * Removes all values in the given collection from this set.
+ * @param {Array|Object} col A collection containing the elements to remove.
+ */
+goog.structs.Set.prototype.removeAll = function(col) {
+ var values = goog.structs.getValues(col);
+ var l = values.length;
+ for (var i = 0; i < l; i++) {
+ this.remove(values[i]);
+ }
+};
+
+
+/**
+ * Removes the given element from this set.
+ * @param {*} element The primitive or object to remove.
+ * @return {boolean} Whether the element was found and removed.
+ */
+goog.structs.Set.prototype.remove = function(element) {
+ return this.map_.remove(goog.structs.Set.getKey_(element));
+};
+
+
+/**
+ * Removes all elements from this set.
+ */
+goog.structs.Set.prototype.clear = function() {
+ this.map_.clear();
+};
+
+
+/**
+ * Tests whether this set is empty.
+ * @return {boolean} True if there are no elements in this set.
+ */
+goog.structs.Set.prototype.isEmpty = function() {
+ return this.map_.isEmpty();
+};
+
+
+/**
+ * Tests whether this set contains the given element.
+ * @param {*} element The primitive or object to test for.
+ * @return {boolean} True if this set contains the given element.
+ */
+goog.structs.Set.prototype.contains = function(element) {
+ return this.map_.containsKey(goog.structs.Set.getKey_(element));
+};
+
+
+/**
+ * Tests whether this set contains all the values in a given collection.
+ * Repeated elements in the collection are ignored, e.g. (new
+ * goog.structs.Set([1, 2])).containsAll([1, 1]) is True.
+ * @param {Object} col A collection-like object.
+ * @return {boolean} True if the set contains all elements.
+ */
+goog.structs.Set.prototype.containsAll = function(col) {
+ return goog.structs.every(col, this.contains, this);
+};
+
+
+/**
+ * Finds all values that are present in both this set and the given collection.
+ * @param {Array|Object} col A collection.
+ * @return {!goog.structs.Set} A new set containing all the values (primitives
+ * or objects) present in both this set and the given collection.
+ */
+goog.structs.Set.prototype.intersection = function(col) {
+ var result = new goog.structs.Set();
+
+ var values = goog.structs.getValues(col);
+ for (var i = 0; i < values.length; i++) {
+ var value = values[i];
+ if (this.contains(value)) {
+ result.add(value);
+ }
+ }
+
+ return result;
+};
+
+
+/**
+ * Returns an array containing all the elements in this set.
+ * @return {!Array} An array containing all the elements in this set.
+ */
+goog.structs.Set.prototype.getValues = function() {
+ return this.map_.getValues();
+};
+
+
+/**
+ * Creates a shallow clone of this set.
+ * @return {!goog.structs.Set} A new set containing all the same elements as
+ * this set.
+ */
+goog.structs.Set.prototype.clone = function() {
+ return new goog.structs.Set(this);
+};
+
+
+/**
+ * Tests whether the given collection consists of the same elements as this set,
+ * regardless of order, without repetition. Primitives are treated as equal if
+ * they have the same type and convert to the same string; objects are treated
+ * as equal if they are references to the same object. This operation is O(n).
+ * @param {Object} col A collection.
+ * @return {boolean} True if the given collection consists of the same elements
+ * as this set, regardless of order, without repetition.
+ */
+goog.structs.Set.prototype.equals = function(col) {
+ return this.getCount() == goog.structs.getCount(col) && this.isSubsetOf(col);
+};
+
+
+/**
+ * Tests whether the given collection contains all the elements in this set.
+ * Primitives are treated as equal if they have the same type and convert to the
+ * same string; objects are treated as equal if they are references to the same
+ * object. This operation is O(n).
+ * @param {Object} col A collection.
+ * @return {boolean} True if this set is a subset of the given collection.
+ */
+goog.structs.Set.prototype.isSubsetOf = function(col) {
+ var colCount = goog.structs.getCount(col);
+ if (this.getCount() > colCount) {
+ return false;
+ }
+ // TODO(user) Find the minimal collection size where the conversion makes
+ // the contains() method faster.
+ if (!(col instanceof goog.structs.Set) && colCount > 5) {
+ // Convert to a goog.structs.Set so that goog.structs.contains runs in
+ // O(1) time instead of O(n) time.
+ col = new goog.structs.Set(col);
+ }
+ return goog.structs.every(this, function(value) {
+ return goog.structs.contains(col, value);
+ });
+};
+
+
+/**
+ * Returns an iterator that iterates over the elements in this set.
+ * @param {boolean=} opt_keys This argument is ignored.
+ * @return {!goog.iter.Iterator} An iterator over the elements in this set.
+ */
+goog.structs.Set.prototype.__iterator__ = function(opt_keys) {
+ return this.map_.__iterator__(false);
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/set_perf.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/set_perf.html.svn-base
new file mode 100644
index 0000000..1b784bd
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/set_perf.html.svn-base
@@ -0,0 +1,237 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2009 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<!--
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <title>Closure Performance Tests - goog.ui.Set vs goog.ui.StringSet</title>
+ <link rel="stylesheet" type="text/css" href="../testing/performancetable.css"/>
+ <script src="../base.js"></script>
+ <script>
+ goog.require('goog.functions');
+ goog.require('goog.string');
+ goog.require('goog.structs.Set');
+ goog.require('goog.structs.StringSet');
+ goog.require('goog.testing.PerformanceTable');
+ goog.require('goog.testing.PropertyReplacer');
+ goog.require('goog.testing.jsunit');
+ </script>
+</head>
+<body>
+ <h1>goog.ui.Set and goog.ui.StringSet Performance Tests</h1>
+ <p>
+ <strong>User-agent:</strong>
+ <script>document.write(navigator.userAgent);</script>
+ </p>
+ <div id="perfTable"></div>
+ <hr>
+
+ <script>
+ var table = new goog.testing.PerformanceTable(
+ goog.dom.getElement('perfTable'));
+
+ // Number of operations to measure in each table line.
+ var OPS_COUNT = 20000;
+
+ var stubs = new goog.testing.PropertyReplacer();
+
+ function tearDown() {
+ stubs.reset();
+ }
+
+ function testCreateSetFromArrayWithoutRepetition() {
+ var values = []
+ for (var i = 0; i < OPS_COUNT; i++) {
+ values.push(i);
+ }
+
+ table.run(function() {
+ var s = new goog.structs.StringSet(values);
+ }, 'Create string set from number array without repetition');
+
+ values = []
+ for (var i = 0; i < OPS_COUNT; i++) {
+ values.push(String(i));
+ }
+
+ table.run(function() {
+ var s = new goog.structs.StringSet(values);
+ }, 'Create string set from string array without repetition');
+ }
+
+ function testCreateSetWithoutRepetition() {
+ table.run(function() {
+ var s = new goog.structs.Set();
+ for (var i = 0; i < OPS_COUNT; i++) {
+ s.add(i);
+ }
+ }, 'Add elements to set without repetition');
+
+ table.run(function() {
+ var s = new goog.structs.StringSet();
+ for (var i = 0; i < OPS_COUNT; i++) {
+ s.add(i);
+ }
+ }, 'Add elements to string set without repetition');
+
+ stubs.set(goog.structs.StringSet.prototype, 'encode',
+ goog.functions.identity);
+ stubs.set(goog.structs.StringSet.prototype, 'decode',
+ goog.functions.identity);
+
+ table.run(function() {
+ var s = new goog.structs.StringSet();
+ for (var i = 0; i < OPS_COUNT; i++) {
+ s.add(i);
+ }
+ }, 'Add elements to string set without repetition and escaping');
+ }
+
+ function testCreateSetWithRepetition() {
+ table.run(function() {
+ var s = new goog.structs.Set();
+ for (var n = 0; n < 10 ; n++) {
+ for (var i = 0; i < OPS_COUNT / 10; i++) {
+ s.add(i);
+ }
+ }
+ }, 'Add elements to set with repetition');
+
+ table.run(function() {
+ var s = new goog.structs.StringSet();
+ for (var n = 0; n < 10; n++) {
+ for (var i = 0; i < OPS_COUNT / 10; i++) {
+ s.add(i);
+ }
+ }
+ }, 'Add elements to string set with repetition');
+ }
+
+ function testForEach() {
+ var bigSet = new goog.structs.Set;
+ var bigStringSet = new goog.structs.StringSet;
+ for (var i = 0; i < OPS_COUNT; i++) {
+ bigSet.add(i);
+ bigStringSet.add(i);
+ }
+
+ table.run(function() {
+ goog.structs.forEach(bigSet, goog.nullFunction);
+ }, 'Iterate over set with forEach');
+
+ table.run(function() {
+ goog.structs.forEach(bigStringSet, goog.nullFunction);
+ }, 'Iterate over string set with forEach');
+ }
+
+ function testForEachWithLargeKeys() {
+ var bigSet = new goog.structs.Set;
+ var bigStringSet = new goog.structs.StringSet;
+ for (var i = 0; i < OPS_COUNT / 100; i++) {
+ bigSet.add(goog.string.repeat(String(i), 1000));
+ bigStringSet.add(goog.string.repeat(String(i), 1000));
+ }
+
+ table.run(function() {
+ for (var i = 0; i < 100; i++) {
+ goog.structs.forEach(bigSet, goog.nullFunction);
+ }
+ }, 'Iterate over set of large strings with forEach');
+
+ table.run(function() {
+ for (var i = 0; i < 100; i++) {
+ goog.structs.forEach(bigStringSet, goog.nullFunction);
+ }
+ }, 'Iterate over string set of large strings with forEach');
+ }
+
+ function testAddRemove() {
+ table.run(function() {
+ var s = new goog.structs.Set();
+ for (var i = 0; i < OPS_COUNT / 2; i++) {
+ s.add(i);
+ }
+ for (var i = 0; i < OPS_COUNT / 2; i++) {
+ s.remove(i);
+ }
+ }, 'Add then remove elements from set');
+
+ table.run(function() {
+ var s = new goog.structs.StringSet();
+ for (var i = 0; i < OPS_COUNT / 2; i++) {
+ s.add(i);
+ }
+ for (var i = 0; i < OPS_COUNT / 2; i++) {
+ s.remove(i);
+ }
+ }, 'Add then remove elements from string set');
+ }
+
+ function testContains() {
+ var bigSet = new goog.structs.Set;
+ var bigStringSet = new goog.structs.StringSet;
+ var arr = [];
+ for (var i = 0; i < OPS_COUNT; i++) {
+ bigSet.add(i);
+ bigStringSet.add(i);
+ arr.push(i);
+ }
+
+ table.run(function() {
+ for (var i = 0; i < OPS_COUNT; i++) {
+ bigSet.contains(i);
+ }
+ }, 'Membership check for each element of set');
+
+ table.run(function() {
+ for (var i = 0; i < OPS_COUNT; i++) {
+ bigStringSet.contains(i);
+ }
+ }, 'Membership check for each element of string set with contains');
+
+ table.run(function() {
+ bigStringSet.containsArray(arr);
+ }, 'Membership check for each element of string set with containsArray');
+
+ stubs.set(goog.structs.StringSet.prototype, 'encode',
+ goog.functions.identity);
+ stubs.set(goog.structs.StringSet.prototype, 'decode',
+ goog.functions.identity);
+
+ table.run(function() {
+ for (var i = 0; i < OPS_COUNT; i++) {
+ bigStringSet.contains(i);
+ }
+ }, 'Membership check for each element of string set without escaping');
+ }
+
+ function testEquals() {
+ table.run(function() {
+ var s1 = new goog.structs.Set();
+ var s2 = new goog.structs.Set();
+ for (var i = 0; i < OPS_COUNT / 4; i++) {
+ s1.add(i);
+ s2.add(i);
+ }
+ s1.equals(s2);
+ }, 'Create then compare two sets');
+
+ table.run(function() {
+ var s1 = new goog.structs.StringSet();
+ var s2 = new goog.structs.StringSet();
+ for (var i = 0; i < OPS_COUNT / 4; i++) {
+ s1.add(i);
+ s2.add(i);
+ }
+ s1.equals(s2);
+ }, 'Create then compare two string sets');
+ }
+ </script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/set_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/set_test.html.svn-base
new file mode 100644
index 0000000..aa3f587
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/set_test.html.svn-base
@@ -0,0 +1,551 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2006 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs.Set</title>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.iter');
+ goog.require('goog.structs');
+ goog.require('goog.structs.Set');
+ goog.require('goog.testing.jsunit');
+</script>
+</head>
+<body>
+<script>
+
+var Set = goog.structs.Set;
+
+function stringifySet(s) {
+ return goog.structs.getValues(s).join('');
+}
+
+function testGetCount() {
+ var s = new Set;
+ var a = new String('a'); s.add(a);
+ var b = new String('b'); s.add(b);
+ var c = new String('c'); s.add(c);
+ assertEquals('count, should be 3', s.getCount(), 3);
+ var d = new String('d'); s.add(d);
+ assertEquals('count, should be 4', s.getCount(), 4);
+ s.remove(d);
+ assertEquals('count, should be 3', s.getCount(), 3);
+
+ s = new Set;
+ s.add('a');
+ s.add('b');
+ s.add('c');
+ assertEquals('count, should be 3', s.getCount(), 3);
+ s.add('d');
+ assertEquals('count, should be 4', s.getCount(), 4);
+ s.remove('d');
+ assertEquals('count, should be 3', s.getCount(), 3);
+}
+
+function testGetValues() {
+ var s = new Set;
+ var a = new String('a'); s.add(a);
+ var b = new String('b'); s.add(b);
+ var c = new String('c'); s.add(c);
+ var d = new String('d'); s.add(d);
+ assertEquals(s.getValues().join(''), 'abcd');
+
+ var s = new Set;
+ s.add('a');
+ s.add('b');
+ s.add('c');
+ s.add('d');
+ assertEquals(s.getValues().join(''), 'abcd');
+}
+
+function testContains() {
+ var s = new Set;
+ var a = new String('a'); s.add(a);
+ var b = new String('b'); s.add(b);
+ var c = new String('c'); s.add(c);
+ var d = new String('d'); s.add(d);
+ var e = new String('e');;
+
+ assertTrue("contains, Should contain 'a'", s.contains(a));
+ assertFalse("contains, Should not contain 'e'", s.contains(e));
+
+ s = new Set;
+ s.add('a');
+ s.add('b');
+ s.add('c');
+ s.add('d');
+
+ assertTrue("contains, Should contain 'a'", s.contains('a'));
+ assertFalse("contains, Should not contain 'e'", s.contains('e'));
+}
+
+function testContainsFunctionValue() {
+ var s = new Set;
+
+ var fn1 = function() {};
+
+ assertFalse(s.contains(fn1));
+ s.add(fn1);
+ assertTrue(s.contains(fn1));
+
+ var fn2 = function() {};
+
+ assertFalse(s.contains(fn2));
+ s.add(fn2);
+ assertTrue(s.contains(fn2));
+
+ assertEquals(s.getCount(), 2);
+}
+
+function testContainsAll() {
+ var set = new Set([1, 2, 3]);
+
+ assertTrue("{1, 2, 3} contains []", set.containsAll([]));
+ assertTrue("{1, 2, 3} contains [1]", set.containsAll([1]));
+ assertTrue("{1, 2, 3} contains [1, 1]", set.containsAll([1, 1]));
+ assertTrue("{1, 2, 3} contains [3, 2, 1]", set.containsAll([3, 2, 1]));
+ assertFalse("{1, 2, 3} doesn't contain [4]", set.containsAll([4]));
+ assertFalse("{1, 2, 3} doesn't contain [1, 4]", set.containsAll([1, 4]));
+
+ assertTrue("{1, 2, 3} contains {a: 1}", set.containsAll({a: 1}));
+ assertFalse("{1, 2, 3} doesn't contain {a: 4}", set.containsAll({a: 4}));
+
+ assertTrue("{1, 2, 3} contains {1}", set.containsAll(new Set([1])));
+ assertFalse("{1, 2, 3} doesn't contain {4}", set.containsAll(new Set([4])));
+}
+
+function testIntersection() {
+ var emptySet = new Set;
+
+ assertTrue('intersection of empty set and [] should be empty',
+ emptySet.intersection([]).isEmpty());
+ assertIntersection('intersection of 2 empty sets should be empty',
+ emptySet, new Set(), new Set());
+
+ var abcdSet = new Set();
+ abcdSet.add('a');
+ abcdSet.add('b');
+ abcdSet.add('c');
+ abcdSet.add('d');
+
+ assertTrue('intersection of populated set and [] should be empty',
+ abcdSet.intersection([]).isEmpty());
+ assertIntersection('intersection of 2 empty sets should be empty',
+ abcdSet, new Set(), new Set());
+
+ var bcSet = new Set(['b', 'c']);
+ assertIntersection('intersection of [a,b,c,d] and [b,c]',
+ abcdSet, bcSet, bcSet);
+
+ var bceSet = new Set(['b', 'c', 'e']);
+ assertIntersection('intersection of [a,b,c,d] and [b,c,e]',
+ abcdSet, bceSet, bcSet);
+}
+
+/**
+ * Helper function to assert intersection is commutative.
+ */
+function assertIntersection(msg, set1, set2, expectedIntersection) {
+ assertTrue(msg + ': set1->set2',
+ set1.intersection(set2).equals(expectedIntersection));
+ assertTrue(msg + ': set2->set1',
+ set2.intersection(set1).equals(expectedIntersection));
+}
+
+function testRemoveAll() {
+ assertRemoveAll('removeAll of empty set from empty set', [], [], []);
+ assertRemoveAll('removeAll of empty set from populated set',
+ ['a', 'b', 'c', 'd'], [], ['a', 'b', 'c', 'd']);
+ assertRemoveAll('removeAll of [a,d] from [a,b,c,d]',
+ ['a', 'b', 'c', 'd'], ['a', 'd'], ['b', 'c']);
+ assertRemoveAll('removeAll of [b,c] from [a,b,c,d]',
+ ['a', 'b', 'c', 'd'], ['b', 'c'], ['a', 'd']);
+ assertRemoveAll('removeAll of [b,c,e] from [a,b,c,d]',
+ ['a', 'b', 'c', 'd'], ['b', 'c', 'e'], ['a', 'd']);
+ assertRemoveAll('removeAll of [a,b,c,d] from [a,d]',
+ ['a', 'd'], ['a', 'b', 'c', 'd'], []);
+ assertRemoveAll('removeAll of [a,b,c,d] from [b,c]',
+ ['b', 'c'], ['a', 'b', 'c', 'd'], []);
+ assertRemoveAll('removeAll of [a,b,c,d] from [b,c,e]',
+ ['b', 'c', 'e'], ['a', 'b', 'c', 'd'], ['e']);
+}
+
+/**
+ * Helper function to test removeAll.
+ */
+function assertRemoveAll(msg, elements1, elements2, expectedResult) {
+ var set1 = new Set(elements1);
+ var set2 = new Set(elements2);
+ set1.removeAll(set2);
+
+ assertTrue(msg + ': set1 count increased after removeAll',
+ elements1.length >= set1.getCount());
+ assertEquals(msg + ': set2 count changed after removeAll',
+ elements2.length, set2.getCount());
+ assertTrue(msg + ': wrong set1 after removeAll', set1.equals(expectedResult));
+ assertIntersection(msg + ': non-empty intersection after removeAll',
+ set1, set2, []);
+}
+
+function testAdd() {
+ var s = new Set;
+ var a = new String('a');
+ var b = new String('b');
+ s.add(a);
+ assertTrue(s.contains(a));
+ s.add(b)
+ assertTrue(s.contains(b));
+
+ s = new Set;
+ s.add('a')
+ assertTrue(s.contains('a'));
+ s.add('b')
+ assertTrue(s.contains('b'));
+ s.add(null);
+ assertTrue('contains null', s.contains(null));
+ assertFalse('does not contain "null"', s.contains('null'));
+}
+
+
+function testClear() {
+ var s = new Set;
+ var a = new String('a'); s.add(a);
+ var b = new String('b'); s.add(b);
+ var c = new String('c'); s.add(c);
+ var d = new String('d'); s.add(d);
+ s.clear();
+ assertTrue('cleared so it should be empty', s.isEmpty());
+ assertTrue("cleared so it should not contain 'a' key", !s.contains(a));
+
+ s = new Set;
+ s.add('a');
+ s.add('b');
+ s.add('c');
+ s.add('d');
+ s.clear();
+ assertTrue('cleared so it should be empty', s.isEmpty());
+ assertTrue("cleared so it should not contain 'a' key", !s.contains('a'));
+}
+
+
+function testAddAll() {
+ var s = new Set;
+ var a = new String('a');
+ var b = new String('b');
+ var c = new String('c');
+ var d = new String('d');
+ s.addAll([a, b, c, d]);
+ assertTrue('addAll so it should not be empty', !s.isEmpty());
+ assertTrue("addAll so it should contain 'c' key", s.contains(c));
+
+ var s2 = new Set;
+ s2.addAll(s);
+ assertTrue('addAll so it should not be empty', !s2.isEmpty());
+ assertTrue("addAll so it should contain 'c' key", s2.contains(c));
+
+
+ s = new Set;
+ s.addAll(['a', 'b', 'c', 'd']);
+ assertTrue('addAll so it should not be empty', !s.isEmpty());
+ assertTrue("addAll so it should contain 'c' key", s.contains('c'));
+
+ s2 = new Set;
+ s2.addAll(s);
+ assertTrue('addAll so it should not be empty', !s2.isEmpty());
+ assertTrue("addAll so it should contain 'c' key", s2.contains('c'));
+}
+
+
+function testConstructor() {
+ var s = new Set;
+ var a = new String('a'); s.add(a);
+ var b = new String('b'); s.add(b);
+ var c = new String('c'); s.add(c);
+ var d = new String('d'); s.add(d);
+ var s2 = new Set(s);
+ assertFalse('constr with Set so it should not be empty', s2.isEmpty());
+ assertTrue('constr with Set so it should contain c', s2.contains(c));
+
+ s = new Set;
+ s.add('a');
+ s.add('b');
+ s.add('c');
+ s.add('d');
+ s2 = new Set(s);
+ assertFalse('constr with Set so it should not be empty', s2.isEmpty());
+ assertTrue('constr with Set so it should contain c', s2.contains('c'));
+}
+
+
+function testClone() {
+ var s = new Set;
+ var a = new String('a'); s.add(a);
+ var b = new String('b'); s.add(b);
+ var c = new String('c'); s.add(c);
+ var d = new String('d'); s.add(d);
+
+ var s2 = s.clone();
+ assertFalse('clone so it should not be empty', s2.isEmpty());
+ assertTrue("clone so it should contain 'c' key", s2.contains(c));
+
+ var s = new Set;
+ s.add('a');
+ s.add('b');
+ s.add('c');
+ s.add('d');
+
+ s2 = s.clone();
+ assertFalse('clone so it should not be empty', s2.isEmpty());
+ assertTrue("clone so it should contain 'c' key", s2.contains('c'));
+}
+
+
+/**
+ * Helper method for testEquals().
+ * @param {Object} a First element to use in the tests.
+ * @param {Object} b Second element to use in the tests.
+ * @param {Object} c Third element to use in the tests.
+ * @param {Object} d Fourth element to use in the tests.
+ */
+function helperForTestEquals(a, b, c, d) {
+ var s = new Set([a, b, c]);
+
+ assertTrue("set == itself", s.equals(s));
+ assertTrue("set == same set", s.equals(new Set([a, b, c])));
+ assertTrue("set == its clone", s.equals(s.clone()));
+ assertTrue("set == array of same elements", s.equals([a, b, c]));
+ assertTrue("set == array of same elements in different order",
+ s.equals([c, b, a]));
+
+ assertFalse("set != empty set", s.equals(new Set));
+ assertFalse("set != its subset", s.equals(new Set([a, c])));
+ assertFalse("set != its superset",
+ s.equals(new Set([a, b, c, d])));
+ assertFalse("set != different set",
+ s.equals(new Set([b, c, d])));
+ assertFalse("set != its subset as array", s.equals([a, c]));
+ assertFalse("set != its superset as array", s.equals([a, b, c, d]));
+ assertFalse("set != different set as array", s.equals([b, c, d]));
+ assertFalse("set != [a, b, c, c]", s.equals([a, b, c, c]));
+ assertFalse("set != [a, b, b]", s.equals([a, b, b]));
+ assertFalse("set != [a, a]", s.equals([a, a]));
+}
+
+
+function testEquals() {
+ helperForTestEquals(1, 2, 3, 4);
+ helperForTestEquals('a', 'b', 'c', 'd');
+ helperForTestEquals(new String('a'), new String('b'),
+ new String('c'), new String('d'));
+}
+
+
+/**
+ * Helper method for testIsSubsetOf().
+ * @param {Object} a First element to use in the tests.
+ * @param {Object} b Second element to use in the tests.
+ * @param {Object} c Third element to use in the tests.
+ * @param {Object} d Fourth element to use in the tests.
+ */
+function helperForTestIsSubsetOf(a, b, c, d) {
+ var s = new Set([a, b, c]);
+
+ assertTrue("set <= itself", s.isSubsetOf(s));
+ assertTrue("set <= same set",
+ s.isSubsetOf(new Set([a, b, c])));
+ assertTrue("set <= its clone", s.isSubsetOf(s.clone()));
+ assertTrue("set <= array of same elements", s.isSubsetOf([a, b, c]));
+ assertTrue("set <= array of same elements in different order",
+ s.equals([c, b, a]));
+
+ assertTrue("set <= Set([a, b, c, d])",
+ s.isSubsetOf(new Set([a, b, c, d])));
+ assertTrue("set <= [a, b, c, d]", s.isSubsetOf([a, b, c, d]));
+ assertTrue("set <= [a, b, c, c]", s.isSubsetOf([a, b, c, c]));
+
+ assertFalse("set !<= Set([a, b])",
+ s.isSubsetOf(new Set([a, b])));
+ assertFalse("set !<= [a, b]", s.isSubsetOf([a, b]));
+ assertFalse("set !<= Set([c, d])",
+ s.isSubsetOf(new Set([c, d])));
+ assertFalse("set !<= [c, d]", s.isSubsetOf([c, d]));
+ assertFalse("set !<= Set([a, c, d])",
+ s.isSubsetOf(new Set([a, c, d])));
+ assertFalse("set !<= [a, c, d]", s.isSubsetOf([a, c, d]));
+ assertFalse("set !<= [a, a, b]", s.isSubsetOf([a, a, b]));
+ assertFalse("set !<= [a, a, b, b]", s.isSubsetOf([a, a, b, b]));
+}
+
+
+function testIsSubsetOf() {
+ helperForTestIsSubsetOf(1, 2, 3, 4);
+ helperForTestIsSubsetOf('a', 'b', 'c', 'd');
+ helperForTestIsSubsetOf(new String('a'), new String('b'),
+ new String('c'), new String('d'));
+}
+
+
+function testForEach() {
+ var s = new Set;
+ var a = new String('a'); s.add(a);
+ var b = new String('b'); s.add(b);
+ var c = new String('c'); s.add(c);
+ var d = new String('d'); s.add(d);
+ var str = '';
+ goog.structs.forEach(s, function(val, key, set) {
+ assertUndefined(key);
+ assertEquals(s, set);
+ str += val;
+ });
+ assertEquals(str, 'abcd');
+
+ s = new Set;
+ s.add('a');
+ s.add('b');
+ s.add('c');
+ s.add('d');
+ str = '';
+ goog.structs.forEach(s, function(val, key, set) {
+ assertUndefined(key);
+ assertEquals(s, set);
+ str += val;
+ });
+ assertEquals(str, 'abcd');
+}
+
+
+function testFilter() {
+ var s = new Set;
+ var a = new Number(0); s.add(a);
+ var b = new Number(1); s.add(b);
+ var c = new Number(2); s.add(c);
+ var d = new Number(3); s.add(d);
+
+ var s2 = goog.structs.filter(s, function (val, key, set) {
+ assertUndefined(key);
+ assertEquals(s, set);
+ return val > 1;
+ });
+ assertEquals(stringifySet(s2), '23');
+
+ s = new Set;
+ s.add(0);
+ s.add(1);
+ s.add(2);
+ s.add(3);
+
+ s2 = goog.structs.filter(s, function (val, key, set) {
+ assertUndefined(key);
+ assertEquals(s, set);
+ return val > 1;
+ });
+ assertEquals(stringifySet(s2), '23');
+}
+
+
+function testSome() {
+ var s = new Set;
+ var a = new Number(0); s.add(a);
+ var b = new Number(1); s.add(b);
+ var c = new Number(2); s.add(c);
+ var d = new Number(3); s.add(d);
+
+ var b = goog.structs.some(s, function (val, key, s2) {
+ assertUndefined(key);
+ assertEquals(s, s2);
+ return val > 1;
+ });
+ assertTrue(b);
+ var b = goog.structs.some(s, function (val, key, s2) {
+ assertUndefined(key);
+ assertEquals(s, s2);
+ return val > 100;
+ });
+ assertFalse(b);
+
+ s = new Set;
+ s.add(0);
+ s.add(1);
+ s.add(2);
+ s.add(3);
+
+ b = goog.structs.some(s, function (val, key, s2) {
+ assertUndefined(key);
+ assertEquals(s, s2);
+ return val > 1;
+ });
+ assertTrue(b);
+ b = goog.structs.some(s, function (val, key, s2) {
+ assertUndefined(key);
+ assertEquals(s, s2);
+ return val > 100;
+ });
+ assertFalse(b);
+}
+
+
+function testEvery() {
+ var s = new Set;
+ var a = new Number(0); s.add(a);
+ var b = new Number(1); s.add(b);
+ var c = new Number(2); s.add(c);
+ var d = new Number(3); s.add(d);
+
+ var b = goog.structs.every(s, function (val, key, s2) {
+ assertUndefined(key);
+ assertEquals(s, s2);
+ return val >= 0;
+ });
+ assertTrue(b);
+ b = goog.structs.every(s, function (val, key, s2) {
+ assertUndefined(key);
+ assertEquals(s, s2);
+ return val > 1;
+ });
+ assertFalse(b);
+
+ s = new Set;
+ s.add(0);
+ s.add(1);
+ s.add(2);
+ s.add(3);
+
+ b = goog.structs.every(s, function (val, key, s2) {
+ assertUndefined(key);
+ assertEquals(s, s2);
+ return val >= 0;
+ });
+ assertTrue(b);
+ b = goog.structs.every(s, function (val, key, s2) {
+ assertUndefined(key);
+ assertEquals(s, s2);
+ return val > 1;
+ });
+ assertFalse(b);
+}
+
+function testIterator() {
+ var s = new Set;
+ s.add(0);
+ s.add(1);
+ s.add(2);
+ s.add(3);
+ s.add(4);
+
+ assertEquals('01234', goog.iter.join(s, ''));
+
+ s.remove(1);
+ s.remove(3);
+
+ assertEquals('024', goog.iter.join(s, ''));
+}
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/simplepool.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/simplepool.js.svn-base
new file mode 100644
index 0000000..3c13e0a
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/simplepool.js.svn-base
@@ -0,0 +1,205 @@
+// Copyright 2007 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Datastructure: Pool.
+ *
+ *
+ * A generic class for handling pools of objects that is more efficient than
+ * goog.structs.Pool because it doesn't maintain a list of objects that are in
+ * use. See constructor comment.
+ */
+
+
+goog.provide('goog.structs.SimplePool');
+
+goog.require('goog.Disposable');
+
+
+
+/**
+ * A generic pool class. Simpler and more efficient than goog.structs.Pool
+ * because it doesn't maintain a list of objects that are in use. This class
+ * has constant overhead and doesn't create any additional objects as part of
+ * the pool management after construction time.
+ *
+ * IMPORTANT: If the objects being pooled are arrays or maps that can have
+ * unlimited number of properties, they need to be cleaned before being
+ * returned to the pool.
+ *
+ * Also note that {@see goog.object.clean} actually allocates an array to clean
+ * the object passed to it, so simply using this function would defy the
+ * purpose of using the pool.
+ *
+ * @param {number} initialCount Initial number of objects to populate the
+ * free pool at construction time.
+ * @param {number} maxCount Maximum number of objects to keep in the free pool.
+ * @constructor
+ * @extends {goog.Disposable}
+ */
+goog.structs.SimplePool = function(initialCount, maxCount) {
+ goog.Disposable.call(this);
+
+ /**
+ * Maximum number of objects allowed
+ * @type {number}
+ * @private
+ */
+ this.maxCount_ = maxCount;
+
+ /**
+ * Queue used to store objects that are currently in the pool and available
+ * to be used.
+ * @type {Array}
+ * @private
+ */
+ this.freeQueue_ = [];
+
+ this.createInitial_(initialCount);
+};
+goog.inherits(goog.structs.SimplePool, goog.Disposable);
+
+
+/**
+ * Function for overriding createObject. The avoids a common case requiring
+ * subclassing this class.
+ * @type {Function}
+ * @private
+ */
+goog.structs.SimplePool.prototype.createObjectFn_ = null;
+
+
+/**
+ * Function for overriding disposeObject. The avoids a common case requiring
+ * subclassing this class.
+ * @type {Function}
+ * @private
+ */
+goog.structs.SimplePool.prototype.disposeObjectFn_ = null;
+
+
+/**
+ * Sets the {@code createObject} function which is used for creating a new
+ * object in the pool.
+ * @param {Function} createObjectFn Create object function which returns the
+ * newly createrd object.
+ */
+goog.structs.SimplePool.prototype.setCreateObjectFn = function(createObjectFn) {
+ this.createObjectFn_ = createObjectFn;
+};
+
+
+/**
+ * Sets the {@code disposeObject} function which is used for disposing of an
+ * object in the pool.
+ * @param {Function} disposeObjectFn Dispose object function which takes the
+ * object to dispose as a parameter.
+ */
+goog.structs.SimplePool.prototype.setDisposeObjectFn = function(
+ disposeObjectFn) {
+ this.disposeObjectFn_ = disposeObjectFn;
+};
+
+
+/**
+ * Gets an unused object from the the pool, if there is one available,
+ * otherwise creates a new one.
+ * @return {*} An object from the pool or a new one if necessary.
+ */
+goog.structs.SimplePool.prototype.getObject = function() {
+ if (this.freeQueue_.length) {
+ return this.freeQueue_.pop();
+ }
+ return this.createObject();
+};
+
+
+/**
+ * Returns an object to the pool so that it can be reused. If the pool is
+ * already full, the object is disposed instead.
+ * @param {*} obj The object to release.
+ */
+goog.structs.SimplePool.prototype.releaseObject = function(obj) {
+ if (this.freeQueue_.length < this.maxCount_) {
+ this.freeQueue_.push(obj);
+ } else {
+ this.disposeObject(obj);
+ }
+};
+
+
+/**
+ * Populates the pool with initialCount objects.
+ * @param {number} initialCount The number of objects to add to the pool.
+ * @private
+ */
+goog.structs.SimplePool.prototype.createInitial_ = function(initialCount) {
+ if (initialCount > this.maxCount_) {
+ throw Error('[goog.structs.SimplePool] Initial cannot be greater than max');
+ }
+ for (var i = 0; i < initialCount; i++) {
+ this.freeQueue_.push(this.createObject());
+ }
+};
+
+
+/**
+ * Should be overriden by sub-classes to return an instance of the object type
+ * that is expected in the pool.
+ * @return {*} The created object.
+ */
+goog.structs.SimplePool.prototype.createObject = function() {
+ if (this.createObjectFn_) {
+ return this.createObjectFn_();
+ } else {
+ return {};
+ }
+};
+
+
+/**
+ * Should be overriden to dispose of an object. Default implementation is to
+ * remove all of the object's members, which should render it useless. Calls the
+ * object's dispose method, if available.
+ * @param {*} obj The object to dispose.
+ */
+goog.structs.SimplePool.prototype.disposeObject = function(obj) {
+ if (this.disposeObjectFn_) {
+ this.disposeObjectFn_(obj);
+ } else if (goog.isObject(obj)) {
+ if (goog.isFunction(obj.dispose)) {
+ obj.dispose();
+ } else {
+ for (var i in obj) {
+ delete obj[i];
+ }
+ }
+ }
+};
+
+
+/**
+ * Disposes of the pool and all objects currently held in the pool.
+ * @override
+ * @protected
+ */
+goog.structs.SimplePool.prototype.disposeInternal = function() {
+ goog.structs.SimplePool.superClass_.disposeInternal.call(this);
+ // Call disposeObject on each object held by the pool.
+ var freeQueue = this.freeQueue_;
+ while (freeQueue.length) {
+ this.disposeObject(freeQueue.pop());
+ }
+ delete this.freeQueue_;
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/stringset.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/stringset.js.svn-base
new file mode 100644
index 0000000..c95ad8c
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/stringset.js.svn-base
@@ -0,0 +1,404 @@
+// Copyright 2009 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Data structure for set of strings.
+ *
+ *
+ * This class implements a set data structure for strings. Adding and removing
+ * is O(1). It doesn't contain any bloat from {@link goog.structs.Set}, i.e.
+ * it isn't optimized for IE6 garbage collector (see the description of
+ * {@link goog.structs.Map#keys_} for details), and it distinguishes its
+ * elements by their string value not by hash code.
+ */
+
+goog.provide('goog.structs.StringSet');
+
+goog.require('goog.iter');
+
+
+
+/**
+ * Creates a set of strings.
+ * @param {!Array=} opt_elements Elements to add to the set. The non-string
+ * items will be converted to strings, so 15 and '15' will mean the same.
+ * @constructor
+ */
+goog.structs.StringSet = function(opt_elements) {
+ /**
+ * An object storing the escaped elements of the set in its keys.
+ * @type {!Object}
+ * @private
+ */
+ this.elements_ = {};
+
+ if (opt_elements) {
+ for (var i = 0; i < opt_elements.length; i++) {
+ this.elements_[this.encode(opt_elements[i])] = null;
+ }
+ }
+};
+
+
+/**
+ * Empty object. Referring to it is faster than creating a new empty object in
+ * {@link #encode}.
+ * @type {Object}
+ * @private
+ */
+goog.structs.StringSet.EMPTY_OBJECT_ = {};
+
+
+/**
+ * The '__proto__' and the '__count__' keys aren't enumerable in Firefox, and
+ * 'toString', 'valueOf', 'constructor', etc. aren't enumerable in IE so they
+ * have to be escaped before they are added to the internal object.
+ * NOTE: When a new set is created, 50-80% of the CPU time is spent in encode.
+ * @param {*} element The element to escape.
+ * @return {*} The escaped element or the element itself if it doesn't have to
+ * be escaped.
+ * @protected
+ */
+goog.structs.StringSet.prototype.encode = function(element) {
+ return element in goog.structs.StringSet.EMPTY_OBJECT_ ||
+ String(element).charCodeAt(0) == 32 ? ' ' + element : element;
+};
+
+
+/**
+ * Inverse function of {@link #encode}.
+ * NOTE: forEach would be 30% faster in FF if the compiler inlined decode.
+ * @param {string} key The escaped element used as the key of the internal
+ * object.
+ * @return {string} The unescaped element.
+ * @protected
+ */
+goog.structs.StringSet.prototype.decode = function(key) {
+ return key.charCodeAt(0) == 32 ? key.substr(1) : key;
+};
+
+
+/**
+ * Adds a single element to the set.
+ * @param {*} element The element to add. It will be converted to string.
+ */
+goog.structs.StringSet.prototype.add = function(element) {
+ this.elements_[this.encode(element)] = null;
+};
+
+
+/**
+ * Adds a the elements of an array to this set.
+ * @param {!Array} arr The array to add the elements of.
+ */
+goog.structs.StringSet.prototype.addArray = function(arr) {
+ for (var i = 0; i < arr.length; i++) {
+ this.elements_[this.encode(arr[i])] = null;
+ }
+};
+
+
+/**
+ * Adds the elements which are in {@code set1} but not in {@code set2} to this
+ * set.
+ * @param {!goog.structs.StringSet} set1 First set.
+ * @param {!goog.structs.StringSet} set2 Second set.
+ * @private
+ */
+goog.structs.StringSet.prototype.addDifference_ = function(set1, set2) {
+ for (var key in set1.elements_) {
+ if (set1.elements_.hasOwnProperty(key) &&
+ !set2.elements_.hasOwnProperty(key)) {
+ this.elements_[key] = null;
+ }
+ }
+};
+
+
+/**
+ * Adds a the elements of a set to this set.
+ * @param {!goog.structs.StringSet} stringSet The set to add the elements of.
+ */
+goog.structs.StringSet.prototype.addSet = function(stringSet) {
+ for (var key in stringSet.elements_) {
+ if (stringSet.elements_.hasOwnProperty(key)) {
+ this.elements_[key] = null;
+ }
+ }
+};
+
+
+/**
+ * Removes all elements of the set.
+ */
+goog.structs.StringSet.prototype.clear = function() {
+ this.elements_ = {};
+};
+
+
+/**
+ * @return {!goog.structs.StringSet} Clone of the set.
+ */
+goog.structs.StringSet.prototype.clone = function() {
+ var ret = new goog.structs.StringSet;
+ ret.addSet(this);
+ return ret;
+};
+
+
+/**
+ * Tells if the set contains the given element.
+ * @param {*} element The element to check.
+ * @return {boolean} Whether it is in the set.
+ */
+goog.structs.StringSet.prototype.contains = function(element) {
+ return this.elements_.hasOwnProperty(this.encode(element));
+};
+
+
+/**
+ * Tells if the set contains all elements of the array.
+ * @param {!Array} arr The elements to check.
+ * @return {boolean} Whether they are in the set.
+ */
+goog.structs.StringSet.prototype.containsArray = function(arr) {
+ for (var i = 0; i < arr.length; i++) {
+ if (!this.elements_.hasOwnProperty(this.encode(arr[i]))) {
+ return false;
+ }
+ }
+ return true;
+};
+
+
+/**
+ * Tells if this set has the same elements as the given set.
+ * @param {!goog.structs.StringSet} stringSet The other set.
+ * @return {boolean} Whether they have the same elements.
+ */
+goog.structs.StringSet.prototype.equals = function(stringSet) {
+ return this.isSubsetOf(stringSet) && stringSet.isSubsetOf(this);
+};
+
+
+/**
+ * Calls a function for each element in the set.
+ * @param {function(string, undefined, !goog.structs.StringSet)} f The function
+ * to call for every element. It takes the element, undefined (because sets
+ * have no notion of keys), and the set.
+ * @param {Object=} opt_obj The object to be used as the value of 'this'
+ * within {@code f}.
+ */
+goog.structs.StringSet.prototype.forEach = function(f, opt_obj) {
+ for (var key in this.elements_) {
+ if (this.elements_.hasOwnProperty(key)) {
+ f.call(opt_obj, this.decode(key), undefined, this);
+ }
+ }
+};
+
+
+/**
+ * Counts the number of elements in the set in linear time.
+ * NOTE: getCount is always called at most once per set instance in google3.
+ * If this usage pattern won't change, the linear getCount implementation is
+ * better, because
+ * <li>populating a set and getting the number of elements in it takes the same
+ * amount of time as keeping a count_ member up to date and getting its value;
+ * <li>if getCount is not called, adding and removing elements have no overhead.
+ * @return {number} The number of elements in the set.
+ */
+goog.structs.StringSet.prototype.getCount = function() {
+ var count = 0;
+ for (var key in this.elements_) {
+ if (this.elements_.hasOwnProperty(key)) {
+ count++;
+ }
+ }
+ return count;
+};
+
+
+/**
+ * Calculates the difference of two sets.
+ * @param {!goog.structs.StringSet} stringSet The set to subtract from this set.
+ * @return {!goog.structs.StringSet} {@code this} minus {@code stringSet}.
+ */
+goog.structs.StringSet.prototype.getDifference = function(stringSet) {
+ var ret = new goog.structs.StringSet;
+ ret.addDifference_(this, stringSet);
+ return ret;
+};
+
+
+/**
+ * Calculates the intersection of this set with another set.
+ * @param {!goog.structs.StringSet} stringSet The set to take the intersection
+ * with.
+ * @return {!goog.structs.StringSet} A new set with the common elements.
+ */
+goog.structs.StringSet.prototype.getIntersection = function(stringSet) {
+ var ret = new goog.structs.StringSet;
+ for (var key in this.elements_) {
+ if (stringSet.elements_.hasOwnProperty(key) &&
+ this.elements_.hasOwnProperty(key)) {
+ ret.elements_[key] = null;
+ }
+ }
+ return ret;
+};
+
+
+/**
+ * Calculates the symmetric difference of two sets.
+ * @param {!goog.structs.StringSet} stringSet The other set.
+ * @return {!goog.structs.StringSet} A new set with the elements in exactly one
+ * of {@code this} and {@code stringSet}.
+ */
+goog.structs.StringSet.prototype.getSymmetricDifference = function(stringSet) {
+ var ret = new goog.structs.StringSet;
+ ret.addDifference_(this, stringSet);
+ ret.addDifference_(stringSet, this);
+ return ret;
+};
+
+
+/**
+ * Calculates the union of this set and another set.
+ * @param {!goog.structs.StringSet} stringSet The set to take the union with.
+ * @return {!goog.structs.StringSet} A new set with the union of elements.
+ */
+goog.structs.StringSet.prototype.getUnion = function(stringSet) {
+ var ret = this.clone();
+ ret.addSet(stringSet);
+ return ret;
+};
+
+
+/**
+ * @return {!Array.<string>} The elements of the set.
+ */
+goog.structs.StringSet.prototype.getValues = function() {
+ var ret = [];
+ for (var key in this.elements_) {
+ if (this.elements_.hasOwnProperty(key)) {
+ ret.push(this.decode(key));
+ }
+ }
+ return ret;
+};
+
+
+/**
+ * Tells if this set and the given set are disjoint.
+ * @param {!goog.structs.StringSet} stringSet The other set.
+ * @return {boolean} True iff they don't have common elements.
+ */
+goog.structs.StringSet.prototype.isDisjoint = function(stringSet) {
+ for (var key in this.elements_) {
+ if (stringSet.elements_.hasOwnProperty(key) &&
+ this.elements_.hasOwnProperty(key)) {
+ return false;
+ }
+ }
+ return true;
+};
+
+
+/**
+ * @return {boolean} Whether the set is empty.
+ */
+goog.structs.StringSet.prototype.isEmpty = function() {
+ for (var key in this.elements_) {
+ if (this.elements_.hasOwnProperty(key)) {
+ return false;
+ }
+ }
+ return true;
+};
+
+
+/**
+ * Tells if this set is the subset of the given set.
+ * @param {!goog.structs.StringSet} stringSet The other set.
+ * @return {boolean} Whether this set if the subset of that.
+ */
+goog.structs.StringSet.prototype.isSubsetOf = function(stringSet) {
+ for (var key in this.elements_) {
+ if (!stringSet.elements_.hasOwnProperty(key) &&
+ this.elements_.hasOwnProperty(key)) {
+ return false;
+ }
+ }
+ return true;
+};
+
+
+/**
+ * Tells if this set is the superset of the given set.
+ * @param {!goog.structs.StringSet} stringSet The other set.
+ * @return {boolean} Whether this set if the superset of that.
+ */
+goog.structs.StringSet.prototype.isSupersetOf = function(stringSet) {
+ return this.isSubsetOf.call(stringSet, this);
+};
+
+
+/**
+ * Removes a single element from the set.
+ * @param {*} element The element to remove.
+ * @return {boolean} Whether the element was in the set.
+ */
+goog.structs.StringSet.prototype.remove = function(element) {
+ var key = this.encode(element);
+ if (this.elements_.hasOwnProperty(key)) {
+ delete this.elements_[key];
+ return true;
+ }
+ return false;
+};
+
+
+/**
+ * Removes all elements of the given array from this set.
+ * @param {!Array} arr The elements to remove.
+ */
+goog.structs.StringSet.prototype.removeArray = function(arr) {
+ for (var i = 0; i < arr.length; i++) {
+ delete this.elements_[this.encode(arr[i])];
+ }
+};
+
+
+/**
+ * Removes all elements of the given set from this set.
+ * @param {!goog.structs.StringSet} stringSet The set of elements to remove.
+ */
+goog.structs.StringSet.prototype.removeSet = function(stringSet) {
+ for (var key in stringSet.elements_) {
+ delete this.elements_[key];
+ }
+};
+
+
+/**
+ * Returns an iterator that iterates over the elements in the set.
+ * NOTE: creating the iterator copies the whole set so use {@link #forEach} when
+ * possible.
+ * @param {boolean=} opt_keys Ignored for sets.
+ * @return {!goog.iter.Iterator} An iterator over the elements in the set.
+ */
+goog.structs.StringSet.prototype.__iterator__ = function(opt_keys) {
+ return goog.iter.toIterator(this.getValues());
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/stringset_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/stringset_test.html.svn-base
new file mode 100644
index 0000000..804e5eb
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/stringset_test.html.svn-base
@@ -0,0 +1,251 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2009 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<!--
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs.StringSet</title>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.array');
+ goog.require('goog.iter');
+ goog.require('goog.structs.StringSet');
+ goog.require('goog.testing.asserts');
+ goog.require('goog.testing.jsunit');
+</script>
+</head>
+<body>
+<script>
+
+// Test how overwritten object prototype affects StringSet.
+Object.prototype.evil1 = null;
+Object.prototype.evil2 = null;
+
+var TEST_VALUES = [
+ '', ' ', ' ', 'true', 'null', 'undefined', '0', 'new', 'constructor',
+ 'prototype', '__proto__', 'set', 'hasOwnProperty', 'toString', 'valueOf',
+ 'evil1'
+];
+
+var TEST_VALUES_WITH_DUPLICATES = [
+ '', '', ' ', ' ', 'true', true, 'null', null, 'undefined', undefined, '0', 0,
+ 'new', 'constructor', 'prototype', '__proto__', 'set', 'hasOwnProperty',
+ 'toString', 'valueOf', 'evil1'
+];
+
+function testConstructor() {
+ var empty = new goog.structs.StringSet;
+ assertSameElements('elements in empty set', [], empty.getValues());
+
+ var s = new goog.structs.StringSet(TEST_VALUES_WITH_DUPLICATES);
+ assertSameElements('duplicates are filtered out by their string value',
+ TEST_VALUES, s.getValues());
+}
+
+function testAdd() {
+ var s = new goog.structs.StringSet;
+ goog.array.forEach(TEST_VALUES_WITH_DUPLICATES, s.add, s);
+ assertSameElements(TEST_VALUES, s.getValues());
+}
+
+function testAddArray() {
+ var s = new goog.structs.StringSet;
+ s.addArray(TEST_VALUES_WITH_DUPLICATES);
+ assertSameElements('added elements from array', TEST_VALUES, s.getValues());
+}
+
+function testAddSet() {
+ var s = new goog.structs.StringSet;
+ s.addSet(new goog.structs.StringSet([1, 2]));
+ assertSameElements('empty set + {1, 2}', ['1', '2'], s.getValues());
+ s.addSet(new goog.structs.StringSet([2, 3]));
+ assertSameElements('{1, 2} + {2, 3}', ['1', '2', '3'], s.getValues());
+}
+
+function testClear() {
+ var s = new goog.structs.StringSet([1, 2]);
+ s.clear();
+ assertSameElements('cleared set', [], s.getValues());
+}
+
+function testClone() {
+ var s = new goog.structs.StringSet([1, 2]);
+ var c = s.clone();
+ assertSameElements('elements in clone', ['1', '2'], c.getValues());
+ s.add(3);
+ assertSameElements('changing the original set does not affect the clone',
+ ['1', '2'], c.getValues());
+}
+
+function testContains() {
+ var e = new goog.structs.StringSet;
+ goog.array.forEach(TEST_VALUES, function(element) {
+ assertFalse('empty set does not contain ' + element, e.contains(element));
+ });
+
+ var s = new goog.structs.StringSet(TEST_VALUES);
+ goog.array.forEach(TEST_VALUES_WITH_DUPLICATES, function(element) {
+ assertTrue('s contains ' + element, s.contains(element));
+ });
+ assertFalse('s does not contain 42', s.contains(42));
+
+ Object.prototype[' a'] = 'a';
+ Object.prototype[' a'] = 'a';
+ assertFalse('empty set does not contain elements defined in Object.prototype',
+ new goog.structs.StringSet().contains(' a'));
+}
+
+function testContainsArray() {
+ var s = new goog.structs.StringSet(TEST_VALUES);
+ assertTrue('set contains empty array', s.containsArray([]));
+ assertTrue('set contains all elements of itself with some duplication',
+ s.containsArray(TEST_VALUES_WITH_DUPLICATES));
+ assertFalse('set does not contain 42', s.containsArray([42]));
+}
+
+function testEquals() {
+ var s = new goog.structs.StringSet([1, 2]);
+ assertTrue('set equals to itself', s.equals(s));
+ assertTrue('set equals to its clone', s.equals(s.clone()));
+ assertFalse('set does not equal to its subset',
+ s.equals(new goog.structs.StringSet([1])));
+ assertFalse('set does not equal to its superset',
+ s.equals(new goog.structs.StringSet([1, 2, 3])));
+}
+
+function testForEach() {
+ var s = new goog.structs.StringSet(TEST_VALUES);
+ var values = [];
+ var context = {};
+ s.forEach(function(value, key, stringSet) {
+ assertEquals('context of forEach callback', context, this);
+ values.push(value);
+ assertUndefined('key argument of forEach callback', key);
+ assertEquals('set argument of forEach callback', s, stringSet);
+ }, context);
+ assertSameElements('values passed to forEach callback', TEST_VALUES, values);
+}
+
+function testGetCount() {
+ var empty = new goog.structs.StringSet;
+ assertEquals('count(empty set)', 0, empty.getCount());
+
+ var s = new goog.structs.StringSet(TEST_VALUES);
+ assertEquals('count(non-empty set)', TEST_VALUES.length, s.getCount());
+}
+
+function testGetDifference() {
+ var s1 = new goog.structs.StringSet([1, 2]);
+ var s2 = new goog.structs.StringSet([2, 3]);
+ assertSameElements('{1, 2} - {2, 3}', ['1'],
+ s1.getDifference(s2).getValues());
+}
+
+function testGetIntersection() {
+ var s1 = new goog.structs.StringSet([1, 2]);
+ var s2 = new goog.structs.StringSet([2, 3]);
+ assertSameElements('{1, 2} * {2, 3}', ['2'],
+ s1.getIntersection(s2).getValues());
+}
+
+function testGetSymmetricDifference() {
+ var s1 = new goog.structs.StringSet([1, 2]);
+ var s2 = new goog.structs.StringSet([2, 3]);
+ assertSameElements('{1, 2} sym.diff. {2, 3}', ['1', '3'],
+ s1.getSymmetricDifference(s2).getValues());
+}
+
+function testGetUnion() {
+ var s1 = new goog.structs.StringSet([1, 2]);
+ var s2 = new goog.structs.StringSet([2, 3]);
+ assertSameElements('{1, 2} + {2, 3}', ['1', '2', '3'],
+ s1.getUnion(s2).getValues());
+}
+
+function testIsDisjoint() {
+ var s = new goog.structs.StringSet;
+ var s12 = new goog.structs.StringSet([1, 2]);
+ var s23 = new goog.structs.StringSet([2, 3]);
+ var s34 = new goog.structs.StringSet([3, 4]);
+
+ assertTrue('{} and {1, 2} are disjoint', s.isDisjoint(s12));
+ assertTrue('{1, 2} and {3, 4} are disjoint', s12.isDisjoint(s34));
+ assertFalse('{1, 2} and {2, 3} are not disjoint', s12.isDisjoint(s23));
+}
+
+function testIsEmpty() {
+ assertTrue('empty set', new goog.structs.StringSet().isEmpty());
+ assertFalse('non-empty set', new goog.structs.StringSet(['']).isEmpty());
+}
+
+function testIsSubsetOf() {
+ var s1 = new goog.structs.StringSet([1]);
+ var s12 = new goog.structs.StringSet([1, 2]);
+ var s123 = new goog.structs.StringSet([1, 2, 3]);
+ var s23 = new goog.structs.StringSet([2, 3]);
+
+ assertTrue('{1, 2} is subset of {1, 2}', s12.isSubsetOf(s12));
+ assertTrue('{1, 2} is subset of {1, 2, 3}', s12.isSubsetOf(s123));
+ assertFalse('{1, 2} is not subset of {1}', s12.isSubsetOf(s1));
+ assertFalse('{1, 2} is not subset of {2, 3}', s12.isSubsetOf(s23));
+}
+
+function testIsSupersetOf() {
+ var s1 = new goog.structs.StringSet([1]);
+ var s12 = new goog.structs.StringSet([1, 2]);
+ var s123 = new goog.structs.StringSet([1, 2, 3]);
+ var s23 = new goog.structs.StringSet([2, 3]);
+
+ assertTrue('{1, 2} is superset of {1}', s12.isSupersetOf(s1));
+ assertTrue('{1, 2} is superset of {1, 2}', s12.isSupersetOf(s12));
+ assertFalse('{1, 2} is not superset of {1, 2, 3}', s12.isSupersetOf(s123));
+ assertFalse('{1, 2} is not superset of {2, 3}', s12.isSupersetOf(s23));
+}
+
+function testRemove() {
+ var n = new goog.structs.StringSet([1, 2]);
+ assertFalse('3 not removed from {1, 2}', n.remove(3));
+ assertSameElements('set == {1, 2}', ['1', '2'], n.getValues());
+ assertTrue('2 removed from {1, 2}', n.remove(2));
+ assertSameElements('set == {1}', ['1'], n.getValues());
+ assertTrue('"1" removed from {1}', n.remove('1'));
+ assertSameElements('set == {}', [], n.getValues());
+
+ var s = new goog.structs.StringSet(TEST_VALUES);
+ goog.array.forEach(TEST_VALUES, s.remove, s);
+ assertSameElements('all special values have been removed', [], s.getValues());
+}
+
+function testRemoveArray() {
+ var s = new goog.structs.StringSet(TEST_VALUES);
+ s.removeArray(TEST_VALUES.slice(0, TEST_VALUES.length - 2));
+ assertSameElements('removed elements from array',
+ TEST_VALUES.slice(TEST_VALUES.length - 2), s.getValues());
+}
+
+function testRemoveSet() {
+ var s1 = new goog.structs.StringSet([1, 2]);
+ var s2 = new goog.structs.StringSet([2, 3]);
+ s1.removeSet(s2);
+ assertSameElements('{1, 2} - {2, 3}', ['1'], s1.getValues());
+}
+
+function testIterator() {
+ var s = new goog.structs.StringSet(TEST_VALUES_WITH_DUPLICATES);
+ var values = []
+ goog.iter.forEach(s, function(value) {
+ values.push(value);
+ });
+ assertSameElements('__iterator__ takes all elements once',
+ TEST_VALUES, values);
+}
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/structs.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/structs.js.svn-base
new file mode 100644
index 0000000..ec39582
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/structs.js.svn-base
@@ -0,0 +1,342 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Generics method for collection-like classes and objects.
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ *
+ * This file contains functions to work with collections. It supports using
+ * Map, Set, Array and Object and other classes that implement collection-like
+ * methods.
+ */
+
+
+goog.provide('goog.structs');
+
+goog.require('goog.array');
+goog.require('goog.object');
+
+
+// We treat an object as a dictionary if it has getKeys or it is an object that
+// isn't arrayLike.
+
+
+/**
+ * Returns the number of values in the collection-like object.
+ * @param {Object} col The collection-like object.
+ * @return {number} The number of values in the collection-like object.
+ */
+goog.structs.getCount = function(col) {
+ if (typeof col.getCount == 'function') {
+ return col.getCount();
+ }
+ if (goog.isArrayLike(col) || goog.isString(col)) {
+ return col.length;
+ }
+ return goog.object.getCount(col);
+};
+
+
+/**
+ * Returns the values of the collection-like object.
+ * @param {Object} col The collection-like object.
+ * @return {!Array} The values in the collection-like object.
+ */
+goog.structs.getValues = function(col) {
+ if (typeof col.getValues == 'function') {
+ return col.getValues();
+ }
+ if (goog.isString(col)) {
+ return col.split('');
+ }
+ if (goog.isArrayLike(col)) {
+ var rv = [];
+ var l = col.length;
+ for (var i = 0; i < l; i++) {
+ rv.push(col[i]);
+ }
+ return rv;
+ }
+ return goog.object.getValues(col);
+};
+
+
+/**
+ * Returns the keys of the collection. Some collections have no notion of
+ * keys/indexes and this function will return undefined in those cases.
+ * @param {Object} col The collection-like object.
+ * @return {!Array|undefined} The keys in the collection.
+ */
+goog.structs.getKeys = function(col) {
+ if (typeof col.getKeys == 'function') {
+ return col.getKeys();
+ }
+ // if we have getValues but no getKeys we know this is a key-less collection
+ if (typeof col.getValues == 'function') {
+ return undefined;
+ }
+ if (goog.isArrayLike(col) || goog.isString(col)) {
+ var rv = [];
+ var l = col.length;
+ for (var i = 0; i < l; i++) {
+ rv.push(i);
+ }
+ return rv;
+ }
+
+ return goog.object.getKeys(col);
+};
+
+
+/**
+ * Whether the collection contains the given value. This is O(n) and uses
+ * equals (==) to test the existence.
+ * @param {Object} col The collection-like object.
+ * @param {*} val The value to check for.
+ * @return {boolean} True if the map contains the value.
+ */
+goog.structs.contains = function(col, val) {
+ if (typeof col.contains == 'function') {
+ return col.contains(val);
+ }
+ if (typeof col.containsValue == 'function') {
+ return col.containsValue(val);
+ }
+ if (goog.isArrayLike(col) || goog.isString(col)) {
+ return goog.array.contains(/** @type {Array} */ (col), val);
+ }
+ return goog.object.containsValue(col, val);
+};
+
+
+/**
+ * Whether the collection is empty.
+ * @param {Object} col The collection-like object.
+ * @return {boolean} True if empty.
+ */
+goog.structs.isEmpty = function(col) {
+ if (typeof col.isEmpty == 'function') {
+ return col.isEmpty();
+ }
+
+ // We do not use goog.string.isEmpty because here we treat the string as
+ // collection and as such even whitespace matters
+
+ if (goog.isArrayLike(col) || goog.isString(col)) {
+ return goog.array.isEmpty(/** @type {Array} */ (col));
+ }
+ return goog.object.isEmpty(col);
+};
+
+
+/**
+ * Removes all the elements from the collection.
+ * @param {Object} col The collection-like object.
+ */
+goog.structs.clear = function(col) {
+ // NOTE(arv): This should not contain strings because strings are immutable
+ if (typeof col.clear == 'function') {
+ col.clear();
+ } else if (goog.isArrayLike(col)) {
+ goog.array.clear((/** @type {goog.array.ArrayLike} */ col));
+ } else {
+ goog.object.clear(col);
+ }
+};
+
+
+/**
+ * Calls a function for each value in a collection. The function takes
+ * three arguments; the value, the key and the collection.
+ *
+ * @param {Object} col The collection-like object.
+ * @param {Function} f The function to call for every value. This function takes
+ * 3 arguments (the value, the key or undefined if the collection has no
+ * notion of keys, and the collection) and the return value is irrelevant.
+ * @param {Object=} opt_obj The object to be used as the value of 'this'
+ * within {@code f}.
+ */
+goog.structs.forEach = function(col, f, opt_obj) {
+ if (typeof col.forEach == 'function') {
+ col.forEach(f, opt_obj);
+ } else if (goog.isArrayLike(col) || goog.isString(col)) {
+ goog.array.forEach(/** @type {Array} */ (col), f, opt_obj);
+ } else {
+ var keys = goog.structs.getKeys(col);
+ var values = goog.structs.getValues(col);
+ var l = values.length;
+ for (var i = 0; i < l; i++) {
+ f.call(opt_obj, values[i], keys && keys[i], col);
+ }
+ }
+};
+
+
+/**
+ * Calls a function for every value in the collection. When a call returns true,
+ * adds the value to a new collection (Array is returned by default).
+ *
+ * @param {Object} col The collection-like object.
+ * @param {Function} f The function to call for every value. This function takes
+ * 3 arguments (the value, the key or undefined if the collection has no
+ * notion of keys, and the collection) and should return a Boolean. If the
+ * return value is true the value is added to the result collection. If it
+ * is false the value is not included.
+ * @param {Object=} opt_obj The object to be used as the value of 'this'
+ * within {@code f}.
+ * @return {!Object|!Array} A new collection where the passed values are
+ * present. If col is a key-less collection an array is returned. If col
+ * has keys and values a plain old JS object is returned.
+ */
+goog.structs.filter = function(col, f, opt_obj) {
+ if (typeof col.filter == 'function') {
+ return col.filter(f, opt_obj);
+ }
+ if (goog.isArrayLike(col) || goog.isString(col)) {
+ return goog.array.filter(/** @type {!Array} */ (col), f, opt_obj);
+ }
+
+ var rv;
+ var keys = goog.structs.getKeys(col);
+ var values = goog.structs.getValues(col);
+ var l = values.length;
+ if (keys) {
+ rv = {};
+ for (var i = 0; i < l; i++) {
+ if (f.call(opt_obj, values[i], keys[i], col)) {
+ rv[keys[i]] = values[i];
+ }
+ }
+ } else {
+ // We should not use goog.array.filter here since we want to make sure that
+ // the index is undefined as well as make sure that col is passed to the
+ // function.
+ rv = [];
+ for (var i = 0; i < l; i++) {
+ if (f.call(opt_obj, values[i], undefined, col)) {
+ rv.push(values[i]);
+ }
+ }
+ }
+ return rv;
+};
+
+
+/**
+ * Calls a function for every value in the collection and adds the result into a
+ * new collection (defaults to creating a new Array).
+ *
+ * @param {Object} col The collection-like object.
+ * @param {Function} f The function to call for every value. This function
+ * takes 3 arguments (the value, the key or undefined if the collection has
+ * no notion of keys, and the collection) and should return something. The
+ * result will be used as the value in the new collection.
+ * @param {Object=} opt_obj The object to be used as the value of 'this'
+ * within {@code f}.
+ * @return {!Object|!Array} A new collection with the new values. If col is a
+ * key-less collection an array is returned. If col has keys and values a
+ * plain old JS object is returned.
+ */
+goog.structs.map = function(col, f, opt_obj) {
+ if (typeof col.map == 'function') {
+ return col.map(f, opt_obj);
+ }
+ if (goog.isArrayLike(col) || goog.isString(col)) {
+ return goog.array.map(/** @type {!Array} */ (col), f, opt_obj);
+ }
+
+ var rv;
+ var keys = goog.structs.getKeys(col);
+ var values = goog.structs.getValues(col);
+ var l = values.length;
+ if (keys) {
+ rv = {};
+ for (var i = 0; i < l; i++) {
+ rv[keys[i]] = f.call(opt_obj, values[i], keys[i], col);
+ }
+ } else {
+ // We should not use goog.array.map here since we want to make sure that
+ // the index is undefined as well as make sure that col is passed to the
+ // function.
+ rv = [];
+ for (var i = 0; i < l; i++) {
+ rv[i] = f.call(opt_obj, values[i], undefined, col);
+ }
+ }
+ return rv;
+};
+
+
+/**
+ * Calls f for each value in a collection. If any call returns true this returns
+ * true (without checking the rest). If all returns false this returns false.
+ *
+ * @param {Object|Array|string} col The collection-like object.
+ * @param {Function} f The function to call for every value. This function takes
+ * 3 arguments (the value, the key or undefined if the collection has no
+ * notion of keys, and the collection) and should return a Boolean.
+ * @param {Object=} opt_obj The object to be used as the value of 'this'
+ * within {@code f}.
+ * @return {boolean} True if any value passes the test.
+ */
+goog.structs.some = function(col, f, opt_obj) {
+ if (typeof col.some == 'function') {
+ return col.some(f, opt_obj);
+ }
+ if (goog.isArrayLike(col) || goog.isString(col)) {
+ return goog.array.some(/** @type {!Array} */ (col), f, opt_obj);
+ }
+ var keys = goog.structs.getKeys(col);
+ var values = goog.structs.getValues(col);
+ var l = values.length;
+ for (var i = 0; i < l; i++) {
+ if (f.call(opt_obj, values[i], keys && keys[i], col)) {
+ return true;
+ }
+ }
+ return false;
+};
+
+
+/**
+ * Calls f for each value in a collection. If all calls return true this return
+ * true this returns true. If any returns false this returns false at this point
+ * and does not continue to check the remaining values.
+ *
+ * @param {Object} col The collection-like object.
+ * @param {Function} f The function to call for every value. This function takes
+ * 3 arguments (the value, the key or undefined if the collection has no
+ * notion of keys, and the collection) and should return a Boolean.
+ * @param {Object=} opt_obj The object to be used as the value of 'this'
+ * within {@code f}.
+ * @return {boolean} True if all key-value pairs pass the test.
+ */
+goog.structs.every = function(col, f, opt_obj) {
+ if (typeof col.every == 'function') {
+ return col.every(f, opt_obj);
+ }
+ if (goog.isArrayLike(col) || goog.isString(col)) {
+ return goog.array.every(/** @type {!Array} */ (col), f, opt_obj);
+ }
+ var keys = goog.structs.getKeys(col);
+ var values = goog.structs.getValues(col);
+ var l = values.length;
+ for (var i = 0; i < l; i++) {
+ if (!f.call(opt_obj, values[i], keys && keys[i], col)) {
+ return false;
+ }
+ }
+ return true;
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/structs_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/structs_test.html.svn-base
new file mode 100644
index 0000000..fb9fe78
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/structs_test.html.svn-base
@@ -0,0 +1,1050 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2006 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs</title>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.array');
+ goog.require('goog.object');
+ goog.require('goog.structs');
+ goog.require('goog.structs.Set'); // needed for filter
+ goog.require('goog.structs.Map');
+ goog.require('goog.testing.jsunit');
+</script>
+</head>
+<body>
+<!-- test container with 10 elements inside, 1 hr and 1 h1 with id h1 -->
+<div id="test">
+ <hr>
+ <p>Paragraph 0</p>
+ <p>Paragraph 1</p>
+ <p>Paragraph 2</p>
+ <p>Paragraph 3</p>
+ <p>Paragraph 4</p>
+ <p>Paragraph 5</p>
+ <p>Paragraph 6</p>
+ <p>Paragraph 7</p>
+ <h1 id="h1">Header</h1>
+</div>
+
+
+<script>
+
+/*
+
+ This one does not test Map or Set
+ It tests Array, Object, String and a NodeList
+
+*/
+
+
+
+function stringifyObject(obj) {
+ var sb = [];
+ for (var key in obj) {
+ sb.push(key + obj[key]);
+ }
+ return sb.join('');
+}
+
+
+function getTestElement() {
+ return document.getElementById('test');
+}
+
+
+function getAll() {
+ return getTestElement().getElementsByTagName('*')
+}
+
+
+var node;
+
+
+function addNode() {
+ node = document.createElement('span');
+ getTestElement().appendChild(node);
+}
+
+
+function removeNode() {
+ getTestElement().removeChild(node);
+}
+
+
+function nodeNames(nl) {
+ var sb = [];
+ for (var i = 0, n; n = nl[i]; i++) {
+ sb.push(n.nodeName.toLowerCase());
+ }
+ return sb.join(',');
+}
+
+
+var allTagNames1 = 'hr,p,p,p,p,p,p,p,p,h1';
+var allTagNames2 = allTagNames1 + ',span';
+
+
+function testGetCount() {
+ var arr = ['a', 'b', 'c'];
+ assertEquals('count, should be 3', 3, goog.structs.getCount(arr));
+ arr.push('d');
+ assertEquals('count, should be 4', 4, goog.structs.getCount(arr));
+ goog.array.remove(arr, 'd');
+ assertEquals('count, should be 3', 3, goog.structs.getCount(arr));
+
+ var obj = {a: 0, b: 1, c: 2};
+ assertEquals('count, should be 3', 3, goog.structs.getCount(obj));
+ obj.d = 3;
+ assertEquals('count, should be 4', 4, goog.structs.getCount(obj));
+ delete obj.d;
+ assertEquals('count, should be 3', 3, goog.structs.getCount(obj));
+
+ var s = 'abc';
+ assertEquals('count, should be 3', 3, goog.structs.getCount(s));
+ s += 'd';
+ assertEquals('count, should be 4', 4, goog.structs.getCount(s));
+
+ var all = getAll();
+ assertEquals('count, should be 10', 10, goog.structs.getCount(all));
+ addNode();
+ assertEquals('count, should be 11', 11, goog.structs.getCount(all));
+ removeNode();
+ assertEquals('count, should be 10', 10, goog.structs.getCount(all));
+
+ var aMap = new goog.structs.Map({a: 0, b: 1, c: 2});
+ assertEquals('count, should be 3', 3, goog.structs.getCount(aMap));
+ aMap.set('d', 3);
+ assertEquals('count, should be 4', 4, goog.structs.getCount(aMap));
+ aMap.remove('a');
+ assertEquals('count, should be 3', 3, goog.structs.getCount(aMap));
+
+ var aSet = new goog.structs.Set('abc');
+ assertEquals('count, should be 3', 3, goog.structs.getCount(aSet));
+ aSet.add('d');
+ assertEquals('count, should be 4', 4, goog.structs.getCount(aSet));
+ aSet.remove('a');
+ assertEquals('count, should be 3', 3, goog.structs.getCount(aSet));
+}
+
+
+function testGetValues() {
+ var arr = ['a', 'b', 'c', 'd'];
+ assertEquals('abcd', goog.structs.getValues(arr).join(''));
+
+ var obj = {a: 0, b: 1, c: 2, d: 3};
+ assertEquals('0123', goog.structs.getValues(obj).join(''));
+
+ var s = 'abc';
+ assertEquals('abc', goog.structs.getValues(s).join(''));
+ s += 'd';
+ assertEquals('abcd', goog.structs.getValues(s).join(''));
+
+ var all = getAll();
+ assertEquals(allTagNames1, nodeNames(goog.structs.getValues(all)));
+ addNode();
+ assertEquals(allTagNames2, nodeNames(goog.structs.getValues(all)));
+ removeNode();
+ assertEquals(allTagNames1, nodeNames(goog.structs.getValues(all)));
+
+ var aMap = new goog.structs.Map({a: 1, b: 2, c: 3});
+ assertEquals('123', goog.structs.getValues(aMap).join(''));
+
+ var aSet = new goog.structs.Set([1, 2, 3]);
+ assertEquals('123', goog.structs.getValues(aMap).join(''));
+}
+
+
+function testGetKeys() {
+ var arr = ['a', 'b', 'c', 'd'];
+ assertEquals('0123', goog.structs.getKeys(arr).join(''));
+
+ var obj = {a: 0, b: 1, c: 2, d: 3};
+ assertEquals('abcd', goog.structs.getKeys(obj).join(''));
+
+ var s = 'abc';
+ assertEquals('012', goog.structs.getKeys(s).join(''));
+ s += 'd';
+ assertEquals('0123', goog.structs.getKeys(s).join(''));
+
+ var all = getAll();
+ assertEquals('0123456789', goog.structs.getKeys(all).join(''));
+ addNode();
+ assertEquals('012345678910', goog.structs.getKeys(all).join(''));
+ removeNode();
+ assertEquals('0123456789', goog.structs.getKeys(all).join(''));
+
+ var aMap = new goog.structs.Map({a: 1, b: 2, c: 3});
+ assertEquals('abc', goog.structs.getKeys(aMap).join(''));
+
+ var aSet = new goog.structs.Set([1, 2, 3]);
+ assertUndefined(goog.structs.getKeys(aSet));
+}
+
+function testContains() {
+ var arr = ['a', 'b', 'c', 'd'];
+ assertTrue("contains, Should contain 'a'", goog.structs.contains(arr, 'a'));
+ assertFalse("contains, Should not contain 'e'", goog.structs.contains(arr, 'e'));
+
+ var obj = {a: 0, b: 1, c: 2, d: 3};
+ assertTrue("contains, Should contain '0'", goog.structs.contains(obj, 0));
+ assertFalse("contains, Should not contain '4'", goog.structs.contains(obj, 4));
+
+ var s = 'abc';
+ assertTrue("contains, Should contain 'a'", goog.structs.contains(s, 'a'));
+ assertFalse("contains, Should not contain 'd'", goog.structs.contains(s, 'd'));
+
+ var all = getAll();
+ assertTrue("contains, Should contain 'h1'",
+ goog.structs.contains(all, document.getElementById('h1')));
+ assertFalse("contains, Should not contain 'document.body'",
+ goog.structs.contains(all, document.body));
+
+ var aMap = new goog.structs.Map({a: 1, b: 2, c: 3});
+ assertTrue("contains, Should contain '1'", goog.structs.contains(aMap, 1));
+ assertFalse("contains, Should not contain '4'", goog.structs.contains(aMap, 4));
+
+ var aSet = new goog.structs.Set([1, 2, 3]);
+ assertTrue("contains, Should contain '1'", goog.structs.contains(aSet, 1));
+ assertFalse("contains, Should not contain '4'", goog.structs.contains(aSet, 4));
+}
+
+
+function testClear() {
+ var arr = ['a', 'b', 'c', 'd'];
+ goog.structs.clear(arr);
+ assertTrue('cleared so it should be empty', goog.structs.isEmpty(arr));
+ assertFalse("cleared so it should not contain 'a'", goog.structs.contains(arr, 'a'));
+
+ var obj = {a: 0, b: 1, c: 2, d: 3};
+ goog.structs.clear(obj);
+ assertTrue('cleared so it should be empty', goog.structs.isEmpty(obj));
+ assertFalse("cleared so it should not contain 'a' key", goog.structs.contains(obj, 0));
+
+ var aMap = new goog.structs.Map({a: 1, b: 2, c: 3});
+ goog.structs.clear(aMap);
+ assertTrue('cleared map so it should be empty', goog.structs.isEmpty(aMap));
+ assertFalse("cleared map so it should not contain '1' value",
+ goog.structs.contains(aMap, 1));
+
+ var aSet = new goog.structs.Set([1, 2, 3]);
+ goog.structs.clear(aSet);
+ assertTrue('cleared set so it should be empty', goog.structs.isEmpty(aSet));
+ assertFalse("cleared set so it should not contain '1'", goog.structs.contains(aSet, 1));
+
+ // cannot clear a string or a NodeList
+}
+
+
+
+// Map
+
+function testMap() {
+ var RV = {};
+ var obj = {
+ map: function(g) {
+ assertEquals(f, g);
+ assertEquals(this, obj);
+ return RV;
+ }
+ };
+ function f() {}
+ assertEquals(RV, goog.structs.map(obj, f));
+}
+
+function testMap2() {
+ var THIS_OBJ = {};
+ var RV = {};
+ var obj = {
+ map: function(g, obj2) {
+ assertEquals(f, g);
+ assertEquals(this, obj);
+ assertEquals(THIS_OBJ, obj2);
+ return RV;
+ }
+ };
+ function f() {}
+ assertEquals(RV, goog.structs.map(obj, f, THIS_OBJ));
+}
+
+function testMapArrayLike() {
+ var col = [0, 1, 2];
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ return v * v;
+ }
+ assertArrayEquals([0, 1, 4], goog.structs.map(col, f));
+}
+
+function testMapArrayLike2() {
+ var THIS_OBJ = {};
+ var col = [0, 1, 2];
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ return v * v;
+ }
+ assertArrayEquals([0, 1, 4], goog.structs.map(col, f, THIS_OBJ));
+}
+
+function testMapString() {
+ var col = '012';
+ function f(v, i, col2) {
+ // Teh SpiderMonkey Array.map for strings turns the string into a String
+ // so we cannot use assertEquals because it uses ===.
+ assertTrue(col == col2);
+ assertEquals('number', typeof i);
+ return Number(v) * Number(v);
+ }
+ assertArrayEquals([0, 1, 4], goog.structs.map(col, f));
+}
+
+function testMapString2() {
+ var THIS_OBJ = {};
+ var col = '012';
+ function f(v, i, col2) {
+ // for some reason the strings are equal but identical???
+ assertEquals(String(col), String(col2));
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ return Number(v) * Number(v);
+ }
+ assertArrayEquals([0, 1, 4], goog.structs.map(col, f, THIS_OBJ));
+}
+
+function testMapMap() {
+ var col = new goog.structs.Map({a: 0, b: 1, c: 2});
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('string', typeof key);
+ return v * v;
+ }
+ assertObjectEquals({a: 0, b: 1, c: 4}, goog.structs.map(col, f));
+}
+
+function testMapMap2() {
+ var THIS_OBJ = {};
+ var col = new goog.structs.Map({a: 0, b: 1, c: 2});
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('string', typeof key);
+ assertEquals(THIS_OBJ, this);
+ return v * v;
+ }
+ assertObjectEquals({a: 0, b: 1, c: 4}, goog.structs.map(col, f, THIS_OBJ));
+}
+
+function testMapSet() {
+ var col = new goog.structs.Set([0, 1, 2]);
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('undefined', typeof key);
+ return v * v;
+ }
+ assertArrayEquals([0, 1, 4], goog.structs.map(col, f));
+}
+
+function testMapSet2() {
+ var THIS_OBJ = {};
+ var col = new goog.structs.Set([0, 1, 2]);
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('undefined', typeof key);
+ assertEquals(THIS_OBJ, this);
+ return v * v;
+ }
+ assertArrayEquals([0, 1, 4], goog.structs.map(col, f, THIS_OBJ));
+}
+
+function testMapNodeList() {
+ var col = getAll();
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ return v.tagName;
+ }
+ assertEquals('HRPPPPPPPPH1', goog.structs.map(col, f).join(''));
+}
+
+function testMapNodeList2() {
+ var THIS_OBJ = {};
+ var col = getAll();
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ return v.tagName;
+ }
+ assertEquals('HRPPPPPPPPH1', goog.structs.map(col, f, THIS_OBJ).join(''));
+}
+
+// Filter
+
+function testFilter() {
+ var RV = {};
+ var obj = {
+ filter: function(g) {
+ assertEquals(f, g);
+ assertEquals(this, obj);
+ return RV;
+ }
+ };
+ function f() {}
+ assertEquals(RV, goog.structs.filter(obj, f));
+}
+
+function testFilter2() {
+ var THIS_OBJ = {};
+ var RV = {};
+ var obj = {
+ filter: function(g, obj2) {
+ assertEquals(f, g);
+ assertEquals(this, obj);
+ assertEquals(THIS_OBJ, obj2);
+ return RV;
+ }
+ };
+ function f() {}
+ assertEquals(RV, goog.structs.filter(obj, f, THIS_OBJ));
+}
+
+function testFilterArrayLike() {
+ var col = [0, 1, 2];
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ return v > 0;
+ }
+ assertArrayEquals([1, 2], goog.structs.filter(col, f));
+}
+
+function testFilterArrayLike2() {
+ var THIS_OBJ = {};
+ var col = [0, 1, 2];
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ return v > 0;
+ }
+ assertArrayEquals([1, 2], goog.structs.filter(col, f, THIS_OBJ));
+}
+
+function testFilterString() {
+ var col = '012';
+ function f(v, i, col2) {
+ // for some reason the strings are equal but identical???
+ assertEquals(String(col), String(col2));
+ assertEquals('number', typeof i);
+ return Number(v) > 0;
+ }
+ assertArrayEquals(['1', '2'], goog.structs.filter(col, f));
+}
+
+function testFilterString2() {
+ var THIS_OBJ = {};
+ var col = '012';
+ function f(v, i, col2) {
+ // for some reason the strings are equal but identical???
+ assertEquals(String(col), String(col2));
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ return Number(v) > 0;
+ }
+ assertArrayEquals(['1', '2'], goog.structs.filter(col, f, THIS_OBJ));
+}
+
+function testFilterMap() {
+ var col = new goog.structs.Map({a: 0, b: 1, c: 2});
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('string', typeof key);
+ return v > 0;
+ }
+ assertObjectEquals({b: 1, c: 2}, goog.structs.filter(col, f));
+}
+
+function testFilterMap2() {
+ var THIS_OBJ = {};
+ var col = new goog.structs.Map({a: 0, b: 1, c: 2});
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('string', typeof key);
+ assertEquals(THIS_OBJ, this);
+ return v > 0;
+ }
+ assertObjectEquals({b: 1, c: 2}, goog.structs.filter(col, f, THIS_OBJ));
+}
+
+function testFilterSet() {
+ var col = new goog.structs.Set([0, 1, 2]);
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('undefined', typeof key);
+ return v > 0;
+ }
+ assertArrayEquals([1, 2], goog.structs.filter(col, f));
+}
+
+function testFilterSet2() {
+ var THIS_OBJ = {};
+ var col = new goog.structs.Set([0, 1, 2]);
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('undefined', typeof key);
+ assertEquals(THIS_OBJ, this);
+ return v > 0;
+ }
+ assertArrayEquals([1, 2], goog.structs.filter(col, f, THIS_OBJ));
+}
+
+function testFilterNodeList() {
+ var col = getAll();
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ return v.tagName == 'P';
+ }
+ assertEquals('p,p,p,p,p,p,p,p',
+ nodeNames(goog.structs.filter(col, f)));
+}
+
+function testFilterNodeList2() {
+ var THIS_OBJ = {};
+ var col = getAll();
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ return v.tagName == 'P';
+ }
+ assertEquals('p,p,p,p,p,p,p,p',
+ nodeNames(goog.structs.filter(col, f, THIS_OBJ)));
+}
+
+// Some
+
+function testSome() {
+ var RV = {};
+ var obj = {
+ some: function(g) {
+ assertEquals(f, g);
+ assertEquals(this, obj);
+ return RV;
+ }
+ };
+ function f() {}
+ assertEquals(RV, goog.structs.some(obj, f));
+}
+
+function testSome2() {
+ var THIS_OBJ = {};
+ var RV = {};
+ var obj = {
+ some: function(g, obj2) {
+ assertEquals(f, g);
+ assertEquals(this, obj);
+ assertEquals(THIS_OBJ, obj2);
+ return RV;
+ }
+ };
+ function f() {}
+ assertEquals(RV, goog.structs.some(obj, f, THIS_OBJ));
+}
+
+function testSomeArrayLike() {
+ var limit = 0;
+ var col = [0, 1, 2];
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ return v > limit;
+ }
+ assertTrue(goog.structs.some(col, f));
+ limit = 2;
+ assertFalse(goog.structs.some(col, f));
+}
+
+function testSomeArrayLike2() {
+ var THIS_OBJ = {};
+ var limit = 0;
+ var col = [0, 1, 2];
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ return v > limit;
+ }
+ assertTrue(goog.structs.some(col, f, THIS_OBJ));
+ limit = 2;
+ assertFalse(goog.structs.some(col, f, THIS_OBJ));
+}
+
+function testSomeString() {
+ var limit = 0;
+ var col = '012';
+ function f(v, i, col2) {
+ // for some reason the strings are equal but identical???
+ assertEquals(String(col), String(col2));
+ assertEquals('number', typeof i);
+ return Number(v) > limit;
+ }
+ assertTrue(goog.structs.some(col, f));
+ limit = 2;
+ assertFalse(goog.structs.some(col, f));
+}
+
+function testSomeString2() {
+ var THIS_OBJ = {};
+ var limit = 0;
+ var col = '012';
+ function f(v, i, col2) {
+ // for some reason the strings are equal but identical???
+ assertEquals(String(col), String(col2));
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ return Number(v) > limit;
+ }
+ assertTrue(goog.structs.some(col, f, THIS_OBJ));
+ limit = 2;
+ assertFalse(goog.structs.some(col, f, THIS_OBJ));
+}
+
+function testSomeMap() {
+ var limit = 0;
+ var col = new goog.structs.Map({a: 0, b: 1, c: 2});
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('string', typeof key);
+ return v > limit;
+ }
+ assertObjectEquals(true, goog.structs.some(col, f));
+ limit = 2;
+ assertFalse(goog.structs.some(col, f));
+}
+
+function testSomeMap2() {
+ var THIS_OBJ = {};
+ var limit = 0;
+ var col = new goog.structs.Map({a: 0, b: 1, c: 2});
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('string', typeof key);
+ assertEquals(THIS_OBJ, this);
+ return v > limit;
+ }
+ assertObjectEquals(true, goog.structs.some(col, f, THIS_OBJ));
+ limit = 2;
+ assertFalse(goog.structs.some(col, f, THIS_OBJ));
+}
+
+function testSomeSet() {
+ var limit = 0;
+ var col = new goog.structs.Set([0, 1, 2]);
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('undefined', typeof key);
+ return v > limit;
+ }
+ assertTrue(goog.structs.some(col, f));
+ limit = 2;
+ assertFalse(goog.structs.some(col, f));
+}
+
+function testSomeSet2() {
+ var THIS_OBJ = {};
+ var limit = 0;
+ var col = new goog.structs.Set([0, 1, 2]);
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('undefined', typeof key);
+ assertEquals(THIS_OBJ, this);
+ return v > limit;
+ }
+ assertTrue(goog.structs.some(col, f, THIS_OBJ));
+ limit = 2;
+ assertFalse(goog.structs.some(col, f, THIS_OBJ));
+}
+
+function testSomeNodeList() {
+ var tagName = 'P';
+ var col = getAll();
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ return v.tagName == tagName;
+ }
+ assertTrue(goog.structs.some(col, f));
+ tagName = 'MARQUEE';
+ assertFalse(goog.structs.some(col, f));
+}
+
+function testSomeNodeList2() {
+ var THIS_OBJ = {};
+ var tagName = 'P';
+ var col = getAll();
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ return v.tagName == tagName;
+ }
+ assertTrue(goog.structs.some(col, f, THIS_OBJ));
+ tagName = 'MARQUEE';
+ assertFalse(goog.structs.some(col, f, THIS_OBJ));
+}
+
+// Every
+
+function testEvery() {
+ var RV = {};
+ var obj = {
+ every: function(g) {
+ assertEquals(f, g);
+ assertEquals(this, obj);
+ return RV;
+ }
+ };
+ function f() {}
+ assertEquals(RV, goog.structs.every(obj, f));
+}
+
+function testEvery2() {
+ var THIS_OBJ = {};
+ var RV = {};
+ var obj = {
+ every: function(g, obj2) {
+ assertEquals(f, g);
+ assertEquals(this, obj);
+ assertEquals(THIS_OBJ, obj2);
+ return RV;
+ }
+ };
+ function f() {}
+ assertEquals(RV, goog.structs.every(obj, f, THIS_OBJ));
+}
+
+function testEveryArrayLike() {
+ var limit = -1;
+ var col = [0, 1, 2];
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ return v > limit;
+ }
+ assertTrue(goog.structs.every(col, f));
+ limit = 1;
+ assertFalse(goog.structs.every(col, f));
+}
+
+function testEveryArrayLike2() {
+ var THIS_OBJ = {};
+ var limit = -1;
+ var col = [0, 1, 2];
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ return v > limit;
+ }
+ assertTrue(goog.structs.every(col, f, THIS_OBJ));
+ limit = 1;
+ assertFalse(goog.structs.every(col, f, THIS_OBJ));
+}
+
+function testEveryString() {
+ var limit = -1;
+ var col = '012';
+ function f(v, i, col2) {
+ // for some reason the strings are equal but identical???
+ assertEquals(String(col), String(col2));
+ assertEquals('number', typeof i);
+ return Number(v) > limit;
+ }
+ assertTrue(goog.structs.every(col, f));
+ limit = 1;
+ assertFalse(goog.structs.every(col, f));
+}
+
+function testEveryString2() {
+ var THIS_OBJ = {};
+ var limit = -1;
+ var col = '012';
+ function f(v, i, col2) {
+ // for some reason the strings are equal but identical???
+ assertEquals(String(col), String(col2));
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ return Number(v) > limit;
+ }
+ assertTrue(goog.structs.every(col, f, THIS_OBJ));
+ limit = 1;
+ assertFalse(goog.structs.every(col, f, THIS_OBJ));
+}
+
+function testEveryMap() {
+ var limit = -1;
+ var col = new goog.structs.Map({a: 0, b: 1, c: 2});
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('string', typeof key);
+ return v > limit;
+ }
+ assertObjectEquals(true, goog.structs.every(col, f));
+ limit = 1;
+ assertFalse(goog.structs.every(col, f));
+}
+
+function testEveryMap2() {
+ var THIS_OBJ = {};
+ var limit = -1;
+ var col = new goog.structs.Map({a: 0, b: 1, c: 2});
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('string', typeof key);
+ assertEquals(THIS_OBJ, this);
+ return v > limit;
+ }
+ assertObjectEquals(true, goog.structs.every(col, f, THIS_OBJ));
+ limit = 1;
+ assertFalse(goog.structs.every(col, f, THIS_OBJ));
+}
+
+function testEverySet() {
+ var limit = -1;
+ var col = new goog.structs.Set([0, 1, 2]);
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('undefined', typeof key);
+ return v > limit;
+ }
+ assertTrue(goog.structs.every(col, f));
+ limit = 1;
+ assertFalse(goog.structs.every(col, f));
+}
+
+function testEverySet2() {
+ var THIS_OBJ = {};
+ var limit = -1;
+ var col = new goog.structs.Set([0, 1, 2]);
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('undefined', typeof key);
+ assertEquals(THIS_OBJ, this);
+ return v > limit;
+ }
+ assertTrue(goog.structs.every(col, f, THIS_OBJ));
+ limit = 1;
+ assertFalse(goog.structs.every(col, f, THIS_OBJ));
+}
+
+function testEveryNodeList() {
+ var nodeType = 1; // ELEMENT
+ var col = getAll();
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ return v.nodeType == nodeType;
+ }
+ assertTrue(goog.structs.every(col, f));
+ nodeType = 3; // TEXT
+ assertFalse(goog.structs.every(col, f));
+}
+
+function testEveryNodeList2() {
+ var THIS_OBJ = {};
+ var nodeType = 1; // ELEMENT
+ var col = getAll();
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ return v.nodeType == nodeType;
+ }
+ assertTrue(goog.structs.every(col, f, THIS_OBJ));
+ nodeType = 3; // TEXT
+ assertFalse(goog.structs.every(col, f, THIS_OBJ));
+}
+
+// For each
+
+function testForEach() {
+ var called = false;
+ var obj = {
+ forEach: function(g) {
+ assertEquals(f, g);
+ assertEquals(this, obj);
+ called = true;
+ }
+ };
+ function f() {}
+ goog.structs.forEach(obj, f);
+ assertTrue(called);
+}
+
+function testForEach2() {
+ var called = false;
+ var THIS_OBJ = {};
+ var obj = {
+ forEach: function(g, obj2) {
+ assertEquals(f, g);
+ assertEquals(this, obj);
+ assertEquals(THIS_OBJ, obj2);
+ called = true;
+ }
+ };
+ function f() {}
+ goog.structs.forEach(obj, f, THIS_OBJ);
+ assertTrue(called);
+}
+
+function testForEachArrayLike() {
+ var col = [0, 1, 2];
+ var values = [];
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ values.push(v * v);
+ }
+ goog.structs.forEach(col, f)
+ assertArrayEquals([0, 1, 4], values);
+}
+
+function testForEachArrayLike2() {
+ var THIS_OBJ = {};
+ var col = [0, 1, 2];
+ var values = [];
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ values.push(v * v);
+ }
+ goog.structs.forEach(col, f, THIS_OBJ);
+ assertArrayEquals([0, 1, 4], values);
+}
+
+function testForEachString() {
+ var col = '012';
+ var values = [];
+ function f(v, i, col2) {
+ // for some reason the strings are equal but identical???
+ assertEquals(String(col), String(col2));
+ assertEquals('number', typeof i);
+ values.push(Number(v) * Number(v));
+ }
+ goog.structs.forEach(col, f);
+ assertArrayEquals([0, 1, 4], values);
+}
+
+function testForEachString2() {
+ var THIS_OBJ = {};
+ var col = '012';
+ var values = [];
+ function f(v, i, col2) {
+ // for some reason the strings are equal but identical???
+ assertEquals(String(col), String(col2));
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ values.push(Number(v) * Number(v));
+ }
+ goog.structs.forEach(col, f, THIS_OBJ);
+ assertArrayEquals([0, 1, 4], values);
+}
+
+function testForEachMap() {
+ var col = new goog.structs.Map({a: 0, b: 1, c: 2});
+ var values = [];
+ var keys = [];
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('string', typeof key);
+ values.push(v * v);
+ keys.push(key);
+ }
+ goog.structs.forEach(col, f);
+ assertArrayEquals([0, 1, 4], values);
+ assertArrayEquals(['a', 'b', 'c'], keys);
+}
+
+function testForEachMap2() {
+ var THIS_OBJ = {};
+ var col = new goog.structs.Map({a: 0, b: 1, c: 2});
+ var values = [];
+ var keys = [];
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('string', typeof key);
+ assertEquals(THIS_OBJ, this);
+ values.push(v * v);
+ keys.push(key);
+ }
+ goog.structs.forEach(col, f, THIS_OBJ);
+ assertArrayEquals([0, 1, 4], values);
+ assertArrayEquals(['a', 'b', 'c'], keys);
+}
+
+function testForEachSet() {
+ var col = new goog.structs.Set([0, 1, 2]);
+ var values = [];
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('undefined', typeof key);
+ values.push(v * v);
+ }
+ goog.structs.forEach(col, f);
+ assertArrayEquals([0, 1, 4], values);
+}
+
+function testForEachSet2() {
+ var THIS_OBJ = {};
+ var col = new goog.structs.Set([0, 1, 2]);
+ var values = [];
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('undefined', typeof key);
+ assertEquals(THIS_OBJ, this);
+ values.push(v * v);
+ }
+ goog.structs.forEach(col, f, THIS_OBJ);
+ assertArrayEquals([0, 1, 4], values);
+}
+
+function testForEachNodeList() {
+ var values = [];
+ var col = getAll();
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ values.push(v.tagName);
+ }
+ goog.structs.forEach(col, f);
+ assertEquals('HRPPPPPPPPH1', values.join(''));
+}
+
+function testForEachNodeList2() {
+ var THIS_OBJ = {};
+ var values = [];
+ var col = getAll();
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ values.push(v.tagName);
+ }
+ goog.structs.forEach(col, f, THIS_OBJ);
+ assertEquals('HRPPPPPPPPH1', values.join(''));
+}
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/treenode.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/treenode.js.svn-base
new file mode 100644
index 0000000..4d67ed4
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/treenode.js.svn-base
@@ -0,0 +1,427 @@
+// Copyright 2010 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Generic tree node data structure with arbitrary number of child
+ * nodes.
+ *
+ */
+
+goog.provide('goog.structs.TreeNode');
+
+goog.require('goog.array');
+goog.require('goog.asserts');
+goog.require('goog.structs.Node');
+
+
+
+/**
+ * Generic tree node data structure with arbitrary number of child nodes.
+ * It is possible to create a dynamic tree structure by overriding
+ * {@link #getParent} and {@link #getChildren} in a subclass. All other getters
+ * will automatically work.
+ *
+ * @param {*} key Key.
+ * @param {*} value Value.
+ * @constructor
+ * @extends {goog.structs.Node}
+ */
+goog.structs.TreeNode = function(key, value) {
+ goog.structs.Node.call(this, key, value);
+};
+goog.inherits(goog.structs.TreeNode, goog.structs.Node);
+
+
+/**
+ * Constant for empty array to avoid unnecessary allocations.
+ * @private
+ */
+goog.structs.TreeNode.EMPTY_ARRAY_ = [];
+
+
+/**
+ * Reference to the parent node or null if it has no parent.
+ * @type {goog.structs.TreeNode}
+ * @private
+ */
+goog.structs.TreeNode.prototype.parent_ = null;
+
+
+/**
+ * Child nodes or null in case of leaf node.
+ * @type {Array.<!goog.structs.TreeNode>}
+ * @private
+ */
+goog.structs.TreeNode.prototype.children_ = null;
+
+
+/**
+ * @return {!goog.structs.TreeNode} Clone of the tree node without its parent
+ * and child nodes. The key and the value are copied by reference.
+ */
+goog.structs.TreeNode.prototype.clone = function() {
+ return new goog.structs.TreeNode(this.getKey(), this.getValue());
+};
+
+
+/**
+ * @return {!goog.structs.TreeNode} Clone of the subtree with this node as root.
+ */
+goog.structs.TreeNode.prototype.deepClone = function() {
+ var clone = this.clone();
+ this.forEachChild(function(child) {
+ clone.addChild(child.deepClone());
+ });
+ return clone;
+};
+
+
+/**
+ * @return {goog.structs.TreeNode} Parent node or null if it has no parent.
+ */
+goog.structs.TreeNode.prototype.getParent = function() {
+ return this.parent_;
+};
+
+
+/**
+ * @return {boolean} Whether the node is a leaf node.
+ */
+goog.structs.TreeNode.prototype.isLeaf = function() {
+ return !this.getChildCount();
+};
+
+
+/**
+ * Tells if the node is the last child of its parent. This method helps how to
+ * connect the tree nodes with lines: L shapes should be used before the last
+ * children and |- shapes before the rest. Schematic tree visualization:
+ *
+ * <pre>
+ * Node1
+ * |-Node2
+ * | L-Node3
+ * | |-Node4
+ * | L-Node5
+ * L-Node6
+ * </pre>
+ *
+ * @return {boolean} Whether the node has parent and is the last child of it.
+ */
+goog.structs.TreeNode.prototype.isLastChild = function() {
+ var parent = this.getParent();
+ return Boolean(parent && this == goog.array.peek(parent.getChildren()));
+};
+
+
+/**
+ * @return {!Array.<!goog.structs.TreeNode>} Immutable child nodes.
+ */
+goog.structs.TreeNode.prototype.getChildren = function() {
+ return this.children_ || goog.structs.TreeNode.EMPTY_ARRAY_;
+};
+
+
+/**
+ * Gets the child node of this node at the given index.
+ * @param {number} index Child index.
+ * @return {goog.structs.TreeNode} The node at the given index or null if not
+ * found.
+ */
+goog.structs.TreeNode.prototype.getChildAt = function(index) {
+ return this.getChildren()[index] || null;
+};
+
+
+/**
+ * @return {number} The number of children.
+ */
+goog.structs.TreeNode.prototype.getChildCount = function() {
+ return this.getChildren().length;
+};
+
+
+/**
+ * @return {number} The number of ancestors of the node.
+ */
+goog.structs.TreeNode.prototype.getDepth = function() {
+ var depth = 0;
+ var node = this;
+ while (node.getParent()) {
+ depth++;
+ node = node.getParent();
+ }
+ return depth;
+};
+
+
+/**
+ * @return {!Array.<!goog.structs.TreeNode>} All ancestor nodes in bottom-up
+ * order.
+ */
+goog.structs.TreeNode.prototype.getAncestors = function() {
+ var ancestors = [];
+ var node = this.getParent();
+ while (node) {
+ ancestors.push(node);
+ node = node.getParent();
+ }
+ return ancestors;
+};
+
+
+/**
+ * @return {!goog.structs.TreeNode} The root of the tree structure, i.e. the
+ * farthest ancestor of the node or the node itself if it has no parents.
+ */
+goog.structs.TreeNode.prototype.getRoot = function() {
+ var root = this;
+ while (root.getParent()) {
+ root = root.getParent();
+ }
+ return root;
+};
+
+
+/**
+ * Builds a nested array structure from the node keys in this node's subtree to
+ * facilitate testing tree operations that change the hierarchy.
+ * @return {!Array} The structure of this node's descendants as nested array
+ * of node keys. The number of unclosed opening brackets up to a particular
+ * node is proportional to the indentation of that node in the graphical
+ * representation of the tree. Example:
+ * <pre>
+ * this
+ * |- child1
+ * | L- grandchild
+ * L- child2
+ * </pre>
+ * is represented as ['child1', ['grandchild'], 'child2'].
+ */
+goog.structs.TreeNode.prototype.getSubtreeKeys = function() {
+ var ret = [];
+ this.forEachChild(function(child) {
+ ret.push(child.getKey());
+ if (!child.isLeaf()) {
+ ret.push(child.getSubtreeKeys());
+ }
+ });
+ return ret;
+};
+
+
+/**
+ * Tells whether this node is the ancestor of the given node.
+ * @param {!goog.structs.TreeNode} node A node.
+ * @return {boolean} Whether this node is the ancestor of {@code node}.
+ */
+goog.structs.TreeNode.prototype.contains = function(node) {
+ var current = node;
+ do {
+ current = current.getParent();
+ } while (current && current != this);
+ return Boolean(current);
+};
+
+
+/**
+ * Finds the deepest common ancestor of the given nodes. The concept of
+ * ancestor is not strict in this case, it includes the node itself.
+ * @param {...!goog.structs.TreeNode} var_args The nodes.
+ * @return {goog.structs.TreeNode} The common ancestor of the nodes or null if
+ * they are from different trees.
+ */
+goog.structs.TreeNode.findCommonAncestor = function(var_args) {
+ var ret = arguments[0];
+ if (!ret) {
+ return null;
+ }
+
+ var retDepth = ret.getDepth();
+ for (var i = 1; i < arguments.length; i++) {
+ var node = arguments[i];
+ var depth = node.getDepth();
+ while (node != ret) {
+ if (depth <= retDepth) {
+ ret = ret.getParent();
+ retDepth--;
+ }
+ if (depth > retDepth) {
+ node = node.getParent();
+ depth--;
+ }
+ }
+ }
+
+ return ret;
+};
+
+
+/**
+ * Traverses all child nodes.
+ * @param {function(!goog.structs.TreeNode, number,
+ * !Array.<!goog.structs.TreeNode>)} f Callback function. It takes the
+ * node, its index and the array of all child nodes as arguments.
+ * @param {Object=} opt_this The object to be used as the value of {@code this}
+ * within {@code f}.
+ */
+goog.structs.TreeNode.prototype.forEachChild = function(f, opt_this) {
+ goog.array.forEach(this.getChildren(), f, opt_this);
+};
+
+
+/**
+ * Traverses all child nodes recursively in preorder.
+ * @param {function(!goog.structs.TreeNode)} f Callback function. It takes the
+ * node as argument.
+ * @param {Object=} opt_this The object to be used as the value of {@code this}
+ * within {@code f}.
+ */
+goog.structs.TreeNode.prototype.forEachDescendant = function(f, opt_this) {
+ goog.array.forEach(this.getChildren(), function(child) {
+ f.call(opt_this, child);
+ child.forEachDescendant(f, opt_this);
+ });
+};
+
+
+/**
+ * Traverses the subtree with the possibility to skip branches. Starts with
+ * this node, and visits the descendant nodes depth-first, in preorder.
+ * @param {function(!goog.structs.TreeNode): (boolean|undefined)} f Callback
+ * function. It takes the node as argument. The children of this node will
+ * be visited if the callback returns true or undefined, and will be
+ * skipped if the callback returns false.
+ * @param {Object=} opt_this The object to be used as the value of {@code this}
+ * within {@code f}.
+ */
+goog.structs.TreeNode.prototype.traverse = function(f, opt_this) {
+ if (f.call(opt_this, this) !== false) {
+ goog.array.forEach(this.getChildren(), function(child) {
+ child.traverse(f, opt_this);
+ });
+ }
+};
+
+
+/**
+ * Sets the parent node of this node. The callers must ensure that the parent
+ * node and only that has this node among its children.
+ * @param {goog.structs.TreeNode} parent The parent to set. If null, the node
+ * will be detached from the tree.
+ * @protected
+ */
+goog.structs.TreeNode.prototype.setParent = function(parent) {
+ this.parent_ = parent;
+};
+
+
+/**
+ * Appends a child node to this node.
+ * @param {!goog.structs.TreeNode} child Orphan child node.
+ */
+goog.structs.TreeNode.prototype.addChild = function(child) {
+ this.addChildAt(child, this.children_ ? this.children_.length : 0);
+};
+
+
+/**
+ * Inserts a child node at the given index.
+ * @param {!goog.structs.TreeNode} child Orphan child node.
+ * @param {number} index The position to insert at.
+ */
+goog.structs.TreeNode.prototype.addChildAt = function(child, index) {
+ goog.asserts.assert(!child.getParent());
+ child.setParent(this);
+ this.children_ = this.children_ || [];
+ goog.asserts.assert(index >= 0 && index <= this.children_.length);
+ goog.array.insertAt(this.children_, child, index);
+};
+
+
+/**
+ * Replaces a child node at the given index.
+ * @param {!goog.structs.TreeNode} newChild Child node to set. It must not have
+ * parent node.
+ * @param {number} index Valid index of the old child to replace.
+ * @return {!goog.structs.TreeNode} The original child node, detached from its
+ * parent.
+ */
+goog.structs.TreeNode.prototype.replaceChildAt = function(newChild, index) {
+ goog.asserts.assert(!newChild.getParent(),
+ 'newChild must not have parent node');
+ var children = this.getChildren();
+ var oldChild = children[index];
+ goog.asserts.assert(oldChild, 'Invalid child or child index is given.');
+ oldChild.setParent(null);
+ children[index] = newChild;
+ newChild.setParent(this);
+ return oldChild;
+};
+
+
+/**
+ * Replaces the given child node.
+ * @param {!goog.structs.TreeNode} newChild New node to replace
+ * {@code oldChild}. It must not have parent node.
+ * @param {!goog.structs.TreeNode} oldChild Existing child node to be replaced.
+ * @return {!goog.structs.TreeNode} The replaced child node detached from its
+ * parent.
+ */
+goog.structs.TreeNode.prototype.replaceChild = function(newChild, oldChild) {
+ return this.replaceChildAt(newChild,
+ goog.array.indexOf(this.getChildren(), oldChild));
+};
+
+
+/**
+ * Removes the child node at the given index.
+ * @param {number} index The position to remove from.
+ * @return {goog.structs.TreeNode} The removed node if any.
+ */
+goog.structs.TreeNode.prototype.removeChildAt = function(index) {
+ var child = this.children_ && this.children_[index];
+ if (child) {
+ child.setParent(null);
+ goog.array.removeAt(this.children_, index);
+ if (this.children_.length == 0) {
+ delete this.children_;
+ }
+ return child;
+ }
+ return null;
+};
+
+
+/**
+ * Removes the given child node of this node.
+ * @param {goog.structs.TreeNode} child The node to remove.
+ * @return {goog.structs.TreeNode} The removed node if any.
+ */
+goog.structs.TreeNode.prototype.removeChild = function(child) {
+ return this.removeChildAt(goog.array.indexOf(this.getChildren(), child));
+};
+
+
+/**
+ * Removes all child nodes of this node.
+ */
+goog.structs.TreeNode.prototype.removeChildren = function() {
+ if (this.children_) {
+ goog.array.forEach(this.children_, function(child) {
+ child.setParent(null);
+ });
+ }
+ delete this.children_;
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/treenode_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/treenode_test.html.svn-base
new file mode 100644
index 0000000..c858b29
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/treenode_test.html.svn-base
@@ -0,0 +1,370 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2010 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<!--
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs.TreeNode</title>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.array');
+ goog.require('goog.structs.TreeNode');
+ goog.require('goog.testing.jsunit');
+</script>
+</head>
+<body>
+<script>
+
+function testConstructor() {
+ var node = new goog.structs.TreeNode('key', 'value');
+ assertEquals('key', 'key', node.getKey());
+ assertEquals('value', 'value', node.getValue());
+ assertNull('parent', node.getParent());
+ assertArrayEquals('children', [], node.getChildren());
+ assertTrue('leaf', node.isLeaf());
+}
+
+function testClone() {
+ var node1 = new goog.structs.TreeNode(1, '1');
+ var node2 = new goog.structs.TreeNode(2, '2');
+ var node3 = new goog.structs.TreeNode(3, '3');
+ node1.addChild(node2);
+ node2.addChild(node3);
+
+ var clone = node2.clone();
+ assertEquals('key', 2, clone.getKey());
+ assertEquals('value', '2', clone.getValue());
+ assertNull('parent', clone.getParent());
+ assertArrayEquals('children', [], clone.getChildren());
+}
+
+function testDeepClone() {
+ var node1 = new goog.structs.TreeNode(1, '1');
+ var node2 = new goog.structs.TreeNode(2, '2');
+ var node3 = new goog.structs.TreeNode(3, '3');
+ node1.addChild(node2);
+ node2.addChild(node3);
+
+ var clone = node2.deepClone();
+ assertEquals('key', 2, clone.getKey());
+ assertEquals('value', '2', clone.getValue());
+ assertNull('parent', clone.getParent());
+ assertEquals('number of children', 1, clone.getChildren().length);
+ assertEquals('first child key', 3, clone.getChildAt(0).getKey());
+ assertNotEquals('first child has been cloned', node3, clone.getChildAt(0));
+}
+
+function testGetParent() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ node1.addChild(node2);
+ assertEquals('parent', node1, node2.getParent());
+ assertNull('orphan', node1.getParent());
+}
+
+function testIsLeaf() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ node1.addChild(node2);
+ assertFalse('not leaf', node1.isLeaf());
+ assertTrue('leaf', node2.isLeaf());
+}
+
+function testIsLastChild() {
+ var node1 = new goog.structs.TreeNode(1, '1');
+ var node2 = new goog.structs.TreeNode(2, '2');
+ var node3 = new goog.structs.TreeNode(3, '3');
+ node1.addChild(node2);
+ node1.addChild(node3);
+ assertFalse('root', node1.isLastChild());
+ assertFalse('first child out of the two', node2.isLastChild());
+ assertTrue('second child out of the two', node3.isLastChild());
+}
+
+function testGetChildren() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ node1.addChild(node2);
+ assertArrayEquals('1 child', [node2], node1.getChildren());
+ assertArrayEquals('no children', [], node2.getChildren());
+}
+
+function testGetChildAt() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ node1.addChild(node2);
+ assertNull('index too low', node1.getChildAt(-1));
+ assertEquals('first child', node2, node1.getChildAt(0));
+ assertNull('index too high', node1.getChildAt(1));
+ assertNull('no children', node2.getChildAt(0));
+}
+
+function testGetChildCount() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ node1.addChild(node2);
+ assertEquals('child count of root node', 1, node1.getChildCount());
+ assertEquals('child count of leaf node', 0, node2.getChildCount());
+}
+
+function testGetDepth() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ var node3 = new goog.structs.TreeNode(3, null);
+ node1.addChild(node2);
+ node2.addChild(node3);
+ assertEquals('no parent', 0, node1.getDepth());
+ assertEquals('1 ancestor', 1, node2.getDepth());
+ assertEquals('2 ancestors', 2, node3.getDepth());
+}
+
+function testGetAncestors() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ var node3 = new goog.structs.TreeNode(3, null);
+ node1.addChild(node2);
+ node2.addChild(node3);
+ assertArrayEquals('no ancestors', [], node1.getAncestors());
+ assertArrayEquals('2 ancestors', [node2, node1], node3.getAncestors());
+}
+
+function testGetRoot() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ node1.addChild(node2);
+ assertEquals('no ancestors', node1, node1.getRoot());
+ assertEquals('has ancestors', node1, node2.getRoot());
+}
+
+function testGetSubtreeKeys() {
+ var root = new goog.structs.TreeNode('root', null);
+ var child1 = new goog.structs.TreeNode('child1', null);
+ var child2 = new goog.structs.TreeNode('child2', null);
+ var grandchild = new goog.structs.TreeNode('grandchild', null);
+ root.addChild(child1);
+ root.addChild(child2);
+ child1.addChild(grandchild);
+ assertArrayEquals('node hierarchy', ['child1', ['grandchild'], 'child2'],
+ root.getSubtreeKeys());
+}
+
+function testContains() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ var node3 = new goog.structs.TreeNode(3, null);
+ var node4 = new goog.structs.TreeNode(4, null);
+ node1.addChild(node2);
+ node2.addChild(node3);
+ node2.addChild(node4);
+
+ assertTrue('parent', node1.contains(node2));
+ assertTrue('grandparent', node1.contains(node3));
+ assertFalse('child', node2.contains(node1));
+ assertFalse('grandchild', node3.contains(node1));
+ assertFalse('sibling', node3.contains(node4));
+}
+
+function testFindCommonAncestor() {
+ var findCommonAncestor = goog.structs.TreeNode.findCommonAncestor;
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ var node3 = new goog.structs.TreeNode(3, null);
+ var node4 = new goog.structs.TreeNode(4, null);
+ var node5 = new goog.structs.TreeNode(5, null);
+ node1.addChild(node2);
+ node2.addChild(node3);
+ node1.addChild(node4);
+
+ assertNull('0 nodes', findCommonAncestor());
+ assertEquals('1 node', node2, findCommonAncestor(node2));
+ assertEquals('same nodes', node3, findCommonAncestor(node3, node3));
+ assertEquals('node and child node', node2, findCommonAncestor(node2, node3));
+ assertEquals('node and parent node', node1, findCommonAncestor(node2, node1));
+ assertEquals('siblings', node1, findCommonAncestor(node2, node4));
+ assertEquals('all nodes', node1,
+ findCommonAncestor(node2, node3, node4, node1));
+ assertNull('disconnected nodes', findCommonAncestor(node3, node5));
+}
+
+function testForEachChild() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ var node3 = new goog.structs.TreeNode(3, null);
+ node1.addChild(node2);
+ node1.addChild(node3);
+
+ var thisContext = {};
+ var visitedNodes = [];
+ var indices = [];
+ node1.forEachChild(function(node, index, children) {
+ assertEquals('value of this', thisContext, this);
+ visitedNodes.push(node);
+ indices.push(index);
+ assertArrayEquals('children argument', [node2, node3], children);
+ }, thisContext);
+ assertArrayEquals('visited nodes', [node2, node3], visitedNodes);
+ assertArrayEquals('index of visited nodes', [0, 1], indices);
+}
+
+function testForEachDescendant() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ var node3 = new goog.structs.TreeNode(3, null);
+ var node4 = new goog.structs.TreeNode(4, null);
+ node1.addChild(node2);
+ node2.addChild(node3);
+ node2.addChild(node4);
+
+ var thisContext = {};
+ var visitedNodes = [];
+ node1.forEachDescendant(function(node) {
+ assertEquals('value of this', thisContext, this);
+ visitedNodes.push(node);
+ }, thisContext);
+ assertArrayEquals('visited nodes', [node2, node3, node4], visitedNodes);
+}
+
+function testTraverse() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ var node3 = new goog.structs.TreeNode(3, null);
+ var node4 = new goog.structs.TreeNode(4, null);
+ node1.addChild(node2);
+ node2.addChild(node3);
+ node2.addChild(node4);
+
+ var thisContext = {};
+ var visitedNodes = [];
+ node1.traverse(function(node) {
+ assertEquals('value of this', thisContext, this);
+ visitedNodes.push(node);
+ }, thisContext);
+ assertArrayEquals('callback returns nothing => all nodes are visited',
+ [node1, node2, node3, node4], visitedNodes);
+
+ visitedNodes = [];
+ node1.traverse(function(node) {
+ visitedNodes.push(node);
+ return node != node2; // Cut off at node2.
+ });
+ assertArrayEquals('children of node2 are skipped',
+ [node1, node2], visitedNodes);
+}
+
+function testAddChild() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ var node3 = new goog.structs.TreeNode(3, null);
+ assertArrayEquals('0 children', [], node1.getChildren());
+ node1.addChild(node2);
+ assertArrayEquals('1 child', [node2], node1.getChildren());
+ assertEquals('parent is set', node1, node2.getParent());
+ node1.addChild(node3);
+ assertArrayEquals('2 children', [node2, node3], node1.getChildren());
+}
+
+function testAddChildAt() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ var node3 = new goog.structs.TreeNode(3, null);
+ var node4 = new goog.structs.TreeNode(4, null);
+ var node5 = new goog.structs.TreeNode(5, null);
+ node1.addChildAt(node2, 0);
+ assertArrayEquals('add first child', [node2], node1.getChildren());
+ assertEquals('parent is set', node1, node2.getParent());
+ node1.addChildAt(node3, 0);
+ assertArrayEquals('add to the front', [node3, node2],
+ node1.getChildren());
+ node1.addChildAt(node4, 1);
+ assertArrayEquals('add to the middle', [node3, node4, node2],
+ node1.getChildren());
+ node1.addChildAt(node5, 3);
+ assertArrayEquals('add to the end', [node3, node4, node2, node5],
+ node1.getChildren());
+}
+
+function testReplaceChildAt() {
+ var root = new goog.structs.TreeNode(0, null);
+ var node1 = new goog.structs.TreeNode(1, null);
+ root.addChild(node1);
+
+ var node2 = new goog.structs.TreeNode(2, null);
+ assertEquals('original node', node1, root.replaceChildAt(node2, 0));
+ assertEquals('parent is set', root, node2.getParent());
+ assertArrayEquals('children are updated', [node2], root.getChildren());
+ assertNull('old child node is detached', node1.getParent());
+}
+
+function testReplaceChild() {
+ var root = new goog.structs.TreeNode(0, null);
+ var node1 = new goog.structs.TreeNode(1, null);
+ root.addChild(node1);
+
+ var node2 = new goog.structs.TreeNode(2, null);
+ assertEquals('original node', node1, root.replaceChild(node2, node1));
+ assertEquals('parent is set', root, node2.getParent());
+ assertArrayEquals('children are updated', [node2], root.getChildren());
+ assertNull('old child node is detached', node1.getParent());
+}
+
+function testRemoveChildAt() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ var node3 = new goog.structs.TreeNode(3, null);
+ node1.addChild(node2);
+ node1.addChild(node3);
+
+ assertNull('index too low', node1.removeChildAt(-1));
+ assertNull('index too high', node1.removeChildAt(2));
+ assertArrayEquals('node1 is intact', [node2, node3], node1.getChildren());
+
+ assertEquals('remove first child', node2, node1.removeChildAt(0));
+ assertArrayEquals('remove from the front', [node3], node1.getChildren());
+ assertNull('parent is unset', node2.getParent());
+
+ assertEquals('remove last child', node3, node1.removeChildAt(0));
+ assertArrayEquals('remove last child', [], node1.getChildren());
+ assertTrue('node1 became leaf', node1.isLeaf());
+}
+
+function testRemoveChild() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ var node3 = new goog.structs.TreeNode(3, null);
+ node1.addChild(node2);
+ node1.addChild(node3);
+
+ assertNull('remove null', node1.removeChild(null));
+ assertNull('remove non-child', node1.removeChild(node1));
+ assertArrayEquals('node1 is intact', [node2, node3], node1.getChildren());
+
+ assertEquals('remove node3, return value', node3, node1.removeChild(node3));
+ assertArrayEquals('node is removed', [node2], node1.getChildren());
+}
+
+function testRemoveChildren() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ var node3 = new goog.structs.TreeNode(3, null);
+ node1.addChild(node2);
+ node1.addChild(node3);
+
+ node2.removeChildren();
+ assertArrayEquals('removing a leaf node\'s children has no effect', [],
+ node2.getChildren());
+ assertEquals('node still has parent', node1, node2.getParent());
+
+ node1.removeChildren();
+ assertArrayEquals('children have been removed', [], node1.getChildren());
+ assertNull('children\'s parents have been unset', node2.getParent());
+}
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/trie.js.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/trie.js.svn-base
new file mode 100644
index 0000000..bf365b0
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/trie.js.svn-base
@@ -0,0 +1,368 @@
+// Copyright 2007 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Datastructure: Trie.
+ *
+ *
+ * This file provides the implementation of a trie data structure. A trie is a
+ * data structure that stores key/value pairs in a prefix tree. See:
+ * http://en.wikipedia.org/wiki/Trie
+ */
+
+
+goog.provide('goog.structs.Trie');
+
+goog.require('goog.object');
+goog.require('goog.structs');
+
+
+
+/**
+ * Class for a Trie datastructure. Trie data structures are made out of trees
+ * of Trie classes.
+ *
+ * @param {Object=} opt_trie Optional goog.structs.Trie or Object to initialize
+ * trie with.
+ * @constructor
+ */
+goog.structs.Trie = function(opt_trie) {
+ /**
+ * This trie's child nodes.
+ * @private
+ * @type {Object.<goog.structs.Trie>}
+ */
+ this.childNodes_ = {};
+
+ if (opt_trie) {
+ this.setAll(opt_trie);
+ }
+};
+
+
+/**
+ * This trie's value. For the base trie, this will be the value of the
+ * empty key, if defined.
+ * @private
+ * @type {*}
+ */
+goog.structs.Trie.prototype.value_ = undefined;
+
+
+/**
+ * Sets the given key/value pair in the trie. O(L), where L is the length
+ * of the key.
+ * @param {string} key The key.
+ * @param {*} value The value.
+ */
+goog.structs.Trie.prototype.set = function(key, value) {
+ this.setOrAdd_(key, value, false);
+};
+
+
+/**
+ * Adds the given key/value pair in the trie. Throw an exception if the key
+ * already exists in the trie. O(L), where L is the length of the key.
+ * @param {string} key The key.
+ * @param {*} value The value.
+ */
+goog.structs.Trie.prototype.add = function(key, value) {
+ this.setOrAdd_(key, value, true);
+};
+
+
+/**
+ * Helper function for set and add. Adds the given key/value pair to
+ * the trie, or, if the key already exists, sets the value of the key. If
+ * opt_add is true, then throws an exception if the key already has a value in
+ * the trie. O(L), where L is the length of the key.
+ * @param {string} key The key.
+ * @param {*} value The value.
+ * @param {boolean=} opt_add Throw exception if key is already in the trie.
+ * @private
+ */
+goog.structs.Trie.prototype.setOrAdd_ = function(key, value, opt_add) {
+ var node = this;
+ for (var characterPosition = 0; characterPosition < key.length;
+ characterPosition++) {
+ var currentCharacter = key.charAt(characterPosition);
+ if (!node.childNodes_[currentCharacter]) {
+ node.childNodes_[currentCharacter] = new goog.structs.Trie();
+ }
+ node = node.childNodes_[currentCharacter];
+ }
+ if (opt_add && node.value_ !== undefined) {
+ throw Error('The collection already contains the key "' + key + '"');
+ } else {
+ node.value_ = value;
+ }
+};
+
+
+/**
+ * Adds multiple key/value pairs from another goog.structs.Trie or Object.
+ * O(N) where N is the number of nodes in the trie.
+ * @param {Object|goog.structs.Trie} trie Object containing the data to add.
+ */
+goog.structs.Trie.prototype.setAll = function(trie) {
+ var keys = goog.structs.getKeys(trie);
+ var values = goog.structs.getValues(trie);
+
+ for (var i = 0; i < keys.length; i++) {
+ this.set(keys[i], values[i]);
+ }
+};
+
+
+/**
+ * Retrieves a value from the trie given a key. O(L), where L is the length of
+ * the key.
+ * @param {string} key The key to retrieve from the trie.
+ * @return {*} The value of the key in the trie, or undefined if the trie does
+ * not contain this key.
+ */
+goog.structs.Trie.prototype.get = function(key) {
+ var node = this;
+ for (var characterPosition = 0; characterPosition < key.length;
+ characterPosition++) {
+ var currentCharacter = key.charAt(characterPosition);
+ if (!node.childNodes_[currentCharacter]) {
+ return undefined;
+ }
+ node = node.childNodes_[currentCharacter];
+ }
+ return node.value_;
+};
+
+
+/**
+ * Retrieves all values from the trie that correspond to prefixes of the given
+ * input key. O(L), where L is the length of the key.
+ *
+ * @param {string} key The key to use for lookup. The given key as well as all
+ * prefixes of the key are retrieved.
+ * @param {?number=} opt_keyStartIndex Optional position in key to start lookup
+ * from. Defaults to 0 if not specified.
+ * @return {Object} Map of end index of matching prefixes and corresponding
+ * values. Empty if no match found.
+ */
+goog.structs.Trie.prototype.getKeyAndPrefixes = function(key,
+ opt_keyStartIndex) {
+ var node = this;
+ var matches = {};
+ var characterPosition = opt_keyStartIndex || 0;
+
+ if (node.value_ !== undefined) {
+ matches[characterPosition] = node.value_;
+ }
+
+ for (; characterPosition < key.length; characterPosition++) {
+ var currentCharacter = key.charAt(characterPosition);
+ if (!(currentCharacter in node.childNodes_)) {
+ break;
+ }
+ node = node.childNodes_[currentCharacter];
+ if (node.value_ !== undefined) {
+ matches[characterPosition] = node.value_;
+ }
+ }
+
+ return matches;
+};
+
+
+/**
+ * Gets the values of the trie. Not returned in any reliable order. O(N) where
+ * N is the number of nodes in the trie. Calls getValuesInternal_.
+ * @return {Array} The values in the trie.
+ */
+goog.structs.Trie.prototype.getValues = function() {
+ var allValues = [];
+ this.getValuesInternal_(allValues);
+ return allValues;
+};
+
+
+/**
+ * Gets the values of the trie. Not returned in any reliable order. O(N) where
+ * N is the number of nodes in the trie. Builds the values as it goes.
+ * @param {Array.<string>} allValues Array to place values into.
+ * @private
+ */
+goog.structs.Trie.prototype.getValuesInternal_ = function(allValues) {
+ if (this.value_ !== undefined) {
+ allValues.push(this.value_);
+ }
+ for (var childNode in this.childNodes_) {
+ this.childNodes_[childNode].getValuesInternal_(allValues);
+ }
+};
+
+
+/**
+ * Gets the keys of the trie. Not returned in any reliable order. O(N) where
+ * N is the number of nodes in the trie (or prefix subtree).
+ * @param {string=} opt_prefix Find only keys with this optional prefix.
+ * @return {Array} The keys in the trie.
+ */
+goog.structs.Trie.prototype.getKeys = function(opt_prefix) {
+ var allKeys = [];
+ if (opt_prefix) {
+ // Traverse to the given prefix, then call getKeysInternal_ to dump the
+ // keys below that point.
+ var node = this;
+ for (var characterPosition = 0; characterPosition < opt_prefix.length;
+ characterPosition++) {
+ var currentCharacter = opt_prefix.charAt(characterPosition);
+ if (!node.childNodes_[currentCharacter]) {
+ return [];
+ }
+ node = node.childNodes_[currentCharacter];
+ }
+ node.getKeysInternal_(opt_prefix, allKeys);
+ } else {
+ this.getKeysInternal_('', allKeys);
+ }
+ return allKeys;
+};
+
+
+/**
+ * Private method to get keys from the trie. Builds the keys as it goes.
+ * @param {string} keySoFar The partial key (prefix) traversed so far.
+ * @param {Array} allKeys The partially built array of keys seen so far.
+ * @private
+ */
+goog.structs.Trie.prototype.getKeysInternal_ = function(keySoFar, allKeys) {
+ if (this.value_ !== undefined) {
+ allKeys.push(keySoFar);
+ }
+ for (var childNode in this.childNodes_) {
+ this.childNodes_[childNode].getKeysInternal_(keySoFar + childNode, allKeys);
+ }
+};
+
+
+/**
+ * Checks to see if a certain key is in the trie. O(L), where L is the length
+ * of the key.
+ * @param {string} key A key that may be in the trie.
+ * @return {boolean} Whether the trie contains key.
+ */
+goog.structs.Trie.prototype.containsKey = function(key) {
+ return this.get(key) !== undefined;
+};
+
+
+/**
+ * Checks to see if a certain value is in the trie. Worst case is O(N) where
+ * N is the number of nodes in the trie.
+ * @param {*} value A value that may be in the trie.
+ * @return {boolean} Whether the trie contains the value.
+ */
+goog.structs.Trie.prototype.containsValue = function(value) {
+ if (this.value_ === value) {
+ return true;
+ }
+ for (var childNode in this.childNodes_) {
+ if (this.childNodes_[childNode].containsValue(value)) {
+ return true;
+ }
+ }
+ return false;
+};
+
+
+/**
+ * Completely empties a trie of all keys and values. ~O(1)
+ */
+goog.structs.Trie.prototype.clear = function() {
+ this.childNodes_ = {};
+ this.value_ = undefined;
+};
+
+
+/**
+ * Removes a key from the trie or throws an exception if the key is not in the
+ * trie. O(L), where L is the length of the key.
+ * @param {string} key A key that should be removed from the trie.
+ * @return {*} The value whose key was removed.
+ */
+goog.structs.Trie.prototype.remove = function(key) {
+ var node = this;
+ var parents = [];
+ for (var characterPosition = 0; characterPosition < key.length;
+ characterPosition++) {
+ var currentCharacter = key.charAt(characterPosition);
+ if (!node.childNodes_[currentCharacter]) {
+ throw Error('The collection does not have the key "' + key + '"');
+ }
+
+ // Archive the current parent and child name (key in childNodes_) so that
+ // we may remove the following node and its parents if they are empty.
+ parents.push([node, currentCharacter]);
+
+ node = node.childNodes_[currentCharacter];
+ }
+ var oldValue = node.value_;
+ delete node.value_;
+
+ while (parents.length > 0) {
+ var currentParentAndCharacter = parents.pop();
+ var currentParent = currentParentAndCharacter[0];
+ var currentCharacter = currentParentAndCharacter[1];
+ if (goog.object.isEmpty(
+ currentParent.childNodes_[currentCharacter].childNodes_)) {
+ // If we have no child nodes, then remove this node.
+ delete currentParent.childNodes_[currentCharacter];
+ } else {
+ // No point of traversing back any further, since we can't remove this
+ // path.
+ break;
+ }
+ }
+ return oldValue;
+};
+
+
+/**
+ * Clones a trie and returns a new trie. O(N), where N is the number of nodes
+ * in the trie.
+ * @return {goog.structs.Trie} A new goog.structs.Trie with the same key value
+ * pairs.
+ */
+goog.structs.Trie.prototype.clone = function() {
+ return new goog.structs.Trie(this);
+};
+
+
+/**
+ * Returns the number of key value pairs in the trie. O(N), where N is the
+ * number of nodes in the trie.
+ * TODO: This could be optimized by storing a weight (count below) in every
+ * node.
+ * @return {number} The number of pairs.
+ */
+goog.structs.Trie.prototype.getCount = function() {
+ return goog.structs.getCount(this.getValues());
+};
+
+
+/**
+ * Returns true if this trie contains no elements. ~O(1).
+ * @return {boolean} True iff this trie contains no elements.
+ */
+goog.structs.Trie.prototype.isEmpty = function() {
+ return this.value_ === undefined && goog.structs.isEmpty(this.childNodes_);
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/trie_test.html.svn-base b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/trie_test.html.svn-base
new file mode 100644
index 0000000..3b180a5
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/.svn/text-base/trie_test.html.svn-base
@@ -0,0 +1,378 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2007 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<!--
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs.Trie</title>
+</script>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.object');
+ goog.require('goog.structs');
+ goog.require('goog.structs.Trie');
+ goog.require('goog.testing.jsunit');
+</script>
+</head>
+<body>
+<script>
+
+function makeTrie() {
+ var trie = new goog.structs.Trie();
+ trie.add('hello', 1);
+ trie.add('hi', 'howdy');
+ trie.add('', 'an empty string key');
+ trie.add('empty value', '');
+ trie.add('zero', 0);
+ trie.add('object', {});
+ trie.add('null', null);
+ trie.add('hello, world', 2);
+ trie.add('world', {});
+ return trie;
+}
+
+function checkTrie(trie) {
+ assertEquals('get, should be 1', trie.get('hello'), 1);
+ assertEquals('get, should be "howdy"', trie.get('hi'), 'howdy');
+ assertEquals('get, should be "an empty string key"', trie.get(''),
+ 'an empty string key');
+ assertEquals('get, should be ""', trie.get('empty value'), '');
+ assertEquals('get, should be ""', typeof trie.get('empty value'), 'string');
+ assertEquals('get, should be an object', typeof trie.get('object'), 'object');
+ assertEquals('get, should be 0', trie.get('zero'), 0);
+ assertEquals('get "null", should be null', trie.get('null'), null);
+ assertEquals('get, should be 2', trie.get('hello, world'), 2);
+ assertEquals('get, should be an object', typeof trie.get('world'), 'object');
+}
+
+function testTrieFormation() {
+ var t = makeTrie();
+ checkTrie(t);
+}
+
+function testFailureOfMultipleAdds() {
+ var t = new goog.structs.Trie();
+ t.add('hello', 'testing');
+ assertThrows('Error should be thrown when same key added twice.', function() {
+ t.add('hello', 'test');
+ });
+
+ t = new goog.structs.Trie();
+ t.add('null', null);
+ assertThrows('Error should be thrown when same key added twice.', function() {
+ t.add('null', 'hi!');
+ });
+
+ t = new goog.structs.Trie();
+ t.add('null', 'blah');
+ assertThrows('Error should be thrown when same key added twice.', function() {
+ t.add('null', null);
+ });
+}
+
+function testTrieClone() {
+ var trieOne = makeTrie();
+ var trieTwo = new goog.structs.Trie(trieOne);
+ checkTrie(trieTwo);
+}
+
+function testTrieFromObject() {
+ var someObject = {'hello' : 1,
+ 'hi' : 'howdy',
+ '' : 'an empty string key',
+ 'empty value' : '',
+ 'object' : {},
+ 'zero' : 0,
+ 'null' : null,
+ 'hello, world' : 2,
+ 'world' : {}};
+ var trie = new goog.structs.Trie(someObject);
+ checkTrie(trie);
+}
+
+function testTrieGetValues() {
+ var trie = makeTrie();
+ var values = trie.getValues();
+ assertTrue('getValues, should contain "howdy"',
+ goog.object.contains(values, 'howdy'));
+ assertTrue('getValues, should contain 1', goog.object.contains(values, 1));
+ assertTrue('getValues, should contain 0', goog.object.contains(values, 0));
+ assertTrue('getValues, should contain ""', goog.object.contains(values, ''));
+ assertTrue('getValues, should contain null',
+ goog.object.contains(values, null));
+ assertEquals('goog.structs.getCount(getValues()) should be 9',
+ goog.structs.getCount(values), 9);
+}
+
+function testTrieGetKeys() {
+ var trie = makeTrie();
+ var keys = trie.getKeys();
+ assertTrue('getKeys, should contain "hello"',
+ goog.object.contains(keys, 'hello'));
+ assertTrue('getKeys, should contain "empty value"',
+ goog.object.contains(keys, 'empty value'));
+ assertTrue('getKeys, should contain ""', goog.object.contains(keys, ''));
+ assertTrue('getKeys, should contain "zero"',
+ goog.object.contains(keys, 'zero'));
+ assertEquals('goog.structs.getCount(getKeys()) should be 9',
+ goog.structs.getCount(keys), 9);
+}
+
+
+function testTrieCount() {
+ var trieOne = makeTrie();
+ var trieTwo = new goog.structs.Trie();
+ assertEquals('count, should be 9', trieOne.getCount(), 9);
+ assertEquals('count, should be 0', trieTwo.getCount(), 0);
+}
+
+function testRemoveKeyFromTrie() {
+ var trie = new goog.structs.Trie();
+ trie.add('key1', 'value1');
+ trie.add('key2', 'value2');
+ trie.add('ke', 'value3');
+ trie.add('zero', 0);
+ trie.remove('key2');
+ assertEquals('get "key1", should be "value1"', trie.get('key1'), 'value1');
+ assertUndefined('get "key2", should be undefined', trie.get('key2'));
+ trie.remove('zero');
+ assertUndefined('get "zero", should be undefined', trie.get('zero'));
+ trie.remove('ke');
+ assertUndefined('get "ke", should be undefined', trie.get('ke'));
+ assertEquals('get "key1", should be "value1"', trie.get('key1'), 'value1');
+ trie.add('a', 'value4');
+ assertTrue('testing internal structure, a should be a child',
+ 'a' in trie.childNodes_);
+ trie.remove('a');
+ assertFalse('testing internal structure, a should no longer be a child',
+ 'a' in trie.childNodes_);
+
+ trie.add('xyza', 'value');
+ trie.remove('xyza', 'value');
+ assertFalse('Should not have "x"', 'x' in trie.childNodes_);
+
+ trie.add('xyza', null);
+ assertTrue('Should have "x"', 'x' in trie.childNodes_);
+ trie.remove('xyza');
+ assertFalse('Should not have "x"', 'x' in trie.childNodes_);
+
+ trie.add('xyza', 'value');
+ trie.add('xb', 'value');
+ trie.remove('xyza');
+ assertTrue('get "x" should be defined', 'x' in trie.childNodes_);
+ assertFalse('get "y" should be undefined',
+ 'y' in trie.childNodes_['x'].childNodes_);
+}
+
+function testRemoveKeyFromTrieWithNulls() {
+ var trie = new goog.structs.Trie();
+ trie.add('key1', null);
+ trie.add('key2', 'value2');
+ trie.add('ke', 'value3');
+ trie.add('zero', 0);
+ trie.remove('key2');
+ assertEquals('get "key1", should be null', trie.get('key1'), null);
+ assertUndefined('get "key2", should be undefined', trie.get('key2'));
+ trie.remove('zero');
+ assertUndefined('get "zero", should be undefined', trie.get('zero'));
+ trie.remove('ke');
+ assertUndefined('get "ke", should be undefined', trie.get('ke'));
+ assertEquals('get "key1", should be null', trie.get('key1'), null);
+ trie.add('a', 'value4');
+ assertTrue('testing internal structure, a should be a child',
+ 'a' in trie.childNodes_);
+ trie.remove('a');
+ assertFalse('testing internal structure, a should no longer be a child',
+ 'a' in trie.childNodes_);
+
+ trie.add('xyza', null);
+ trie.add('xb', 'value');
+ trie.remove('xyza');
+ assertTrue('Should have "x"', 'x' in trie.childNodes_);
+ assertFalse('Should not have "y"',
+ 'y' in trie.childNodes_['x'].childNodes_);
+}
+
+function testRemoveKeyException() {
+ var trie = new goog.structs.Trie();
+ trie.add('abcdefg', 'value');
+ trie.add('abcz', 'value');
+ trie.add('abc', 'value');
+
+ assertThrows('Remove should throw an error on removal of non-existent key',
+ function() {
+ trie.remove('abcdefge');
+ });
+}
+
+function testTrieIsEmpty() {
+ var trieOne = new goog.structs.Trie();
+ var trieTwo = makeTrie();
+ assertTrue('isEmpty, should be empty', trieOne.isEmpty());
+ assertFalse('isEmpty, should not be empty', trieTwo.isEmpty());
+ trieOne.add('', 1);
+ assertFalse('isEmpty, should not be empty', trieTwo.isEmpty());
+ trieOne.remove('');
+ assertTrue('isEmpty, should be empty', trieOne.isEmpty());
+ trieOne.add('', 1);
+ trieOne.add('a', 1);
+ trieOne.remove('a');
+ assertFalse('isEmpty, should not be empty', trieOne.isEmpty());
+ trieOne.remove('');
+ assertTrue('isEmpty, should be empty', trieOne.isEmpty());
+ trieOne.add('', 1);
+ trieOne.add('a', 1);
+ trieOne.remove('');
+ assertFalse('isEmpty, should not be empty', trieOne.isEmpty());
+ trieOne.remove('a');
+ assertTrue('isEmpty, should be empty', trieOne.isEmpty());
+}
+
+function testTrieClear() {
+ var trie = new goog.structs.Trie();
+ trie.add('key1', 'value1');
+ trie.add('key2', 'value2');
+ trie.add('key3', null);
+ trie.clear();
+ assertUndefined('get key1, should be undefined', trie.get('key1'));
+ assertUndefined('get key2, should be undefined', trie.get('key2'));
+ assertUndefined('get key3, should be undefined', trie.get('key3'));
+}
+
+function testTrieContainsKey() {
+ var trie = makeTrie();
+ assertTrue('containsKey, should contain "hello"', trie.containsKey('hello'));
+ assertTrue('containsKey, should contain "hi"', trie.containsKey('hi'));
+ assertTrue('containsKey, should contain ""', trie.containsKey(''));
+ assertTrue('containsKey, should contain "empty value"',
+ trie.containsKey('empty value'));
+ assertTrue('containsKey, should contain "object"',
+ trie.containsKey('object'));
+ assertTrue('containsKey, should contain "zero"', trie.containsKey('zero'));
+ assertTrue('containsKey, should contain "null"', trie.containsKey('null'));
+ assertFalse('containsKey, should not contain "blah"',
+ trie.containsKey('blah'));
+ trie.remove('');
+ trie.remove('hi');
+ trie.remove('zero');
+ trie.remove('null');
+ assertFalse('containsKey, should not contain "zero"',
+ trie.containsKey('zero'));
+ assertFalse('containsKey, should not contain ""', trie.containsKey(''));
+ assertFalse('containsKey, should not contain "hi"', trie.containsKey('hi'));
+ assertFalse('containsKey, should not contain "null"',
+ trie.containsKey('null'));
+}
+
+function testTrieContainsValue() {
+ var trie = makeTrie();
+ assertTrue('containsValue, should be true, should contain 1',
+ trie.containsValue(1));
+ assertTrue('containsValue, should be true, should contain "howdy"',
+ trie.containsValue('howdy'));
+ assertTrue('containsValue, should be true, should contain ""',
+ trie.containsValue(''));
+ assertTrue('containsValue, should be true, should contain 0',
+ trie.containsValue(0));
+ assertTrue('containsValue, should be true, should contain null',
+ trie.containsValue(null));
+ assertTrue('containsValue, should be true, should ' +
+ 'contain "an empty string key"',
+ trie.containsValue('an empty string key'));
+ assertFalse('containsValue, should be false, should not contain "blah"',
+ trie.containsValue('blah'));
+ trie.remove('empty value');
+ trie.remove('zero');
+ assertFalse('containsValue, should be false, should not contain 0',
+ trie.containsValue(0));
+ assertFalse('containsValue, should be false, should not contain ""',
+ trie.containsValue(''));
+}
+
+function testTrieHandlingOfEmptyStrings() {
+ var trie = new goog.structs.Trie();
+ assertEquals('get, should be undefined', trie.get(''), undefined);
+ assertFalse('containsValue, should be false', trie.containsValue(''));
+ assertFalse('containsKey, should be false', trie.containsKey(''));
+ trie.add('', 'test');
+ trie.add('test2', '');
+ assertTrue('containsValue, should be true', trie.containsValue(''));
+ assertTrue('containsKey, should be true', trie.containsKey(''));
+ assertEquals('get, should be "test"', trie.get(''), 'test');
+ assertEquals('get, should be ""', trie.get('test2'), '');
+ trie.remove('');
+ trie.remove('test2');
+ assertEquals('get, should be undefined', trie.get(''), undefined);
+ assertFalse('containsValue, should be false', trie.containsValue(''));
+ assertFalse('containsKey, should be false', trie.containsKey(''));
+}
+
+function testPrefixOptionOnGetKeys() {
+ var trie = new goog.structs.Trie();
+ trie.add('abcdefg', 'one');
+ trie.add('abcdefghijk', 'two');
+ trie.add('abcde', 'three');
+ trie.add('abcq', null);
+ trie.add('abc', 'four');
+ trie.add('xyz', 'five');
+ assertEquals('getKeys, should be 1', trie.getKeys('xy').length, 1);
+ assertEquals('getKeys, should be 1', trie.getKeys('xyz').length, 1);
+ assertEquals('getKeys, should be 1', trie.getKeys('x').length, 1);
+ assertEquals('getKeys, should be 4', trie.getKeys('abc').length, 5);
+ assertEquals('getKeys, should be 2', trie.getKeys('abcdef').length, 2);
+ assertEquals('getKeys, should be 0', trie.getKeys('abcdefgi').length, 0);
+}
+
+function testGetKeyAndPrefixes() {
+ var trie = makeTrie();
+ // Note: trie has one of its keys as ''
+ assertEquals('getKeyAndPrefixes, should be 2',
+ 2,
+ goog.object.getCount(trie.getKeyAndPrefixes('world')));
+ assertEquals('getKeyAndPrefixes, should be 2',
+ 2,
+ goog.object.getCount(trie.getKeyAndPrefixes('hello')));
+ assertEquals('getKeyAndPrefixes, should be 2',
+ 2,
+ goog.object.getCount(trie.getKeyAndPrefixes('hello,')));
+ assertEquals('getKeyAndPrefixes, should be 3',
+ 3,
+ goog.object.getCount(trie.getKeyAndPrefixes('hello, world')));
+ assertEquals('getKeyAndPrefixes, should be 1',
+ 1,
+ goog.object.getCount(trie.getKeyAndPrefixes('hell')));
+}
+
+function testGetKeyAndPrefixesStartIndex() {
+ var trie = new goog.structs.Trie();
+ trie.add('abcdefg', 'one');
+ trie.add('bcdefg', 'two');
+ trie.add('abcdefghijk', 'three');
+ trie.add('abcde', 'four');
+ trie.add('abcq', null);
+ trie.add('q', null);
+ trie.add('abc', 'five');
+ trie.add('xyz', 'six');
+ assertEquals('getKeyAndPrefixes, should be 3',
+ 3,
+ goog.object.getCount(trie.getKeyAndPrefixes('abcdefg', 0)));
+ assertEquals('getKeyAndPrefixes, should be 1',
+ 1,
+ goog.object.getCount(trie.getKeyAndPrefixes('abcdefg', 1)));
+ assertEquals('getKeyAndPrefixes, should be 1',
+ 1,
+ goog.object.getCount(trie.getKeyAndPrefixes('abcq', 3)));
+ assertEquals('getKeyAndPrefixes, should be 0',
+ 0,
+ goog.object.getCount(trie.getKeyAndPrefixes('abcd', 3)));
+}
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/avltree.js b/contexts/data/lib/closure-library/closure/goog/structs/avltree.js
new file mode 100644
index 0000000..306ab2a
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/avltree.js
@@ -0,0 +1,772 @@
+// Copyright 2007 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Datastructure: AvlTree.
+ *
+ *
+ * This file provides the implementation of an AVL-Tree datastructure. The tree
+ * maintains a set of unique values in a sorted order. The values can be
+ * accessed efficiently in their sorted order since the tree enforces an O(logn)
+ * maximum height. See http://en.wikipedia.org/wiki/Avl_tree for more detail.
+ *
+ * The big-O notation for all operations are below:
+ * <pre>
+ * Method big-O
+ * ----------------------------------------------------------------------------
+ * - add O(logn)
+ * - remove O(logn)
+ * - clear O(1)
+ * - contains O(logn)
+ * - getCount O(1)
+ * - getMinimum O(1), or O(logn) when optional root is specified
+ * - getMaximum O(1), or O(logn) when optional root is specified
+ * - getHeight O(1)
+ * - getValues O(n)
+ * - inOrderTraverse O(logn + k), where k is number of traversed nodes
+ * - reverseOrderTraverse O(logn + k), where k is number of traversed nodes
+ * </pre>
+ */
+
+
+goog.provide('goog.structs.AvlTree');
+goog.provide('goog.structs.AvlTree.Node');
+
+goog.require('goog.structs');
+goog.require('goog.structs.Collection');
+
+
+
+/**
+ * Constructs an AVL-Tree, which uses the specified comparator to order its
+ * values. The values can be accessed efficiently in their sorted order since
+ * the tree enforces a O(logn) maximum height.
+ *
+ * @param {Function=} opt_comparator Function used to order the tree's nodes.
+ * @constructor
+ * @implements {goog.structs.Collection}
+ */
+goog.structs.AvlTree = function(opt_comparator) {
+ this.comparator_ = opt_comparator ||
+ goog.structs.AvlTree.DEFAULT_COMPARATOR_;
+};
+
+
+/**
+ * String comparison function used to compare values in the tree. This function
+ * is used by default if no comparator is specified in the tree's constructor.
+ *
+ * @param {string} a The first string.
+ * @param {string} b The second string.
+ * @return {number} -1 if a < b, 1 if a > b, 0 if a = b.
+ * @private
+ */
+goog.structs.AvlTree.DEFAULT_COMPARATOR_ = function(a, b) {
+ if (String(a) < String(b)) {
+ return -1;
+ } else if (String(a) > String(b)) {
+ return 1;
+ }
+ return 0;
+};
+
+
+/**
+ * Pointer to the root node of the tree.
+ *
+ * @type {goog.structs.AvlTree.Node}
+ * @private
+ */
+goog.structs.AvlTree.prototype.root_ = null;
+
+
+/**
+ * Comparison function used to compare values in the tree. This function should
+ * take two values, a and b, and return x where:
+ * <pre>
+ * x < 0 if a < b,
+ * x > 0 if a > b,
+ * x = 0 otherwise
+ * </pre>
+ *
+ * @type {Function}
+ * @private
+ */
+goog.structs.AvlTree.prototype.comparator_ = null;
+
+
+/**
+ * Pointer to the node with the smallest value in the tree.
+ *
+ * @type {goog.structs.AvlTree.Node}
+ * @private
+ */
+goog.structs.AvlTree.prototype.minNode_ = null;
+
+
+/**
+ * Pointer to the node with the largest value in the tree.
+ *
+ * @type {goog.structs.AvlTree.Node}
+ * @private
+ */
+goog.structs.AvlTree.prototype.maxNode_ = null;
+
+
+/**
+ * Keeps track of the number of nodes in the tree.
+ *
+ * @type {number}
+ * @private
+ */
+goog.structs.AvlTree.prototype.count_ = 0;
+
+
+/**
+ * Inserts a node into the tree with the specified value if the tree does
+ * not already contain a node with the specified value. If the value is
+ * inserted, the tree is balanced to enforce the AVL-Tree height property.
+ *
+ * @param {*} value Value to insert into the tree.
+ * @return {boolean} Whether value was inserted into the tree.
+ */
+goog.structs.AvlTree.prototype.add = function(value) {
+ // If the tree is empty, create a root node with the specified value
+ if (this.root_ == null) {
+ this.root_ = new goog.structs.AvlTree.Node(value);
+ this.minNode_ = this.root_;
+ this.maxNode_ = this.root_;
+ this.count_ = 1;
+ return true;
+ }
+
+ // Assume a node is not added and change status when one is
+ var retStatus = false;
+
+ // Depth traverse the tree and insert the value if we reach a null node
+ this.traverse_(function(node) {
+ var retNode = null;
+ if (this.comparator_(node.value, value) > 0) {
+ retNode = node.left;
+ if (node.left == null) {
+ var newNode = new goog.structs.AvlTree.Node(value, node);
+ node.left = newNode;
+ if (node == this.minNode_) {
+ this.minNode_ = newNode;
+ }
+ retStatus = true; // Value was added to tree
+ this.balance_(node); // Maintain the AVL-tree balance
+ }
+ } else if (this.comparator_(node.value, value) < 0) {
+ retNode = node.right;
+ if (node.right == null) {
+ var newNode = new goog.structs.AvlTree.Node(value, node);
+ node.right = newNode;
+ if (node == this.maxNode_) {
+ this.maxNode_ = newNode;
+ }
+ retStatus = true; // Value was added to tree
+ this.balance_(node); // Maintain the AVL-tree balance
+ }
+ }
+ return retNode; // If null, we'll stop traversing the tree
+ });
+
+ // If a node was added, increment count
+ if (retStatus) {
+ this.count_ += 1;
+ }
+
+ // Return true if a node was added, false otherwise
+ return retStatus;
+};
+
+
+/**
+ * Removes a node from the tree with the specified value if the tree contains a
+ * node with this value. If a node is removed the tree is balanced to enforce
+ * the AVL-Tree height property. The value of the removed node is returned.
+ *
+ * @param {*} value Value to find and remove from the tree.
+ * @return {*} The value of the removed node or null if the value was not in
+ * the tree.
+ */
+goog.structs.AvlTree.prototype.remove = function(value) {
+ // Assume the value is not removed and set the value when it is removed
+ var retValue = null;
+
+ // Depth traverse the tree and remove the value if we find it
+ this.traverse_(function(node) {
+ var retNode = null;
+ if (this.comparator_(node.value, value) > 0) {
+ retNode = node.left;
+ } else if (this.comparator_(node.value, value) < 0) {
+ retNode = node.right;
+ } else {
+ retValue = node.value;
+ this.removeNode_(node);
+ }
+ return retNode; // If null, we'll stop traversing the tree
+ });
+
+ // If a node was removed, decrement count.
+ if (retValue) {
+ // Had traverse_() cleared the tree, set to 0.
+ this.count_ = this.root_ ? this.count_ - 1 : 0;
+ }
+
+ // Return the value that was removed, null if the value was not in the tree
+ return retValue;
+};
+
+
+/**
+ * Removes all nodes from the tree.
+ */
+goog.structs.AvlTree.prototype.clear = function() {
+ this.root_ = null;
+ this.minNode_ = null;
+ this.maxNode_ = null;
+ this.count_ = 0;
+};
+
+
+/**
+ * Returns true if the tree contains a node with the specified value, false
+ * otherwise.
+ *
+ * @param {*} value Value to find in the tree.
+ * @return {boolean} Whether the tree contains a node with the specified value.
+ */
+goog.structs.AvlTree.prototype.contains = function(value) {
+ // Assume the value is not in the tree and set this value if it is found
+ var isContained = false;
+
+ // Depth traverse the tree and set isContained if we find the node
+ this.traverse_(function(node) {
+ var retNode = null;
+ if (this.comparator_(node.value, value) > 0) {
+ retNode = node.left;
+ } else if (this.comparator_(node.value, value) < 0) {
+ retNode = node.right;
+ } else {
+ isContained = true;
+ }
+ return retNode; // If null, we'll stop traversing the tree
+ });
+
+ // Return true if the value is contained in the tree, false otherwise
+ return isContained;
+};
+
+
+/**
+ * Returns the number of values stored in the tree.
+ *
+ * @return {number} The number of values stored in the tree.
+ */
+goog.structs.AvlTree.prototype.getCount = function() {
+ return this.count_;
+};
+
+
+/**
+ * Returns the value u, such that u is contained in the tree and u < v, for all
+ * values v in the tree where v != u.
+ *
+ * @return {*} The minimum value contained in the tree.
+ */
+goog.structs.AvlTree.prototype.getMinimum = function() {
+ return this.getMinNode_().value;
+};
+
+
+/**
+ * Returns the value u, such that u is contained in the tree and u > v, for all
+ * values v in the tree where v != u.
+ *
+ * @return {*} The maximum value contained in the tree.
+ */
+goog.structs.AvlTree.prototype.getMaximum = function() {
+ return this.getMaxNode_().value;
+};
+
+
+/**
+ * Returns the height of the tree (the maximum depth). This height should
+ * always be <= 1.4405*(Math.log(n+2)/Math.log(2))-1.3277, where n is the
+ * number of nodes in the tree.
+ *
+ * @return {number} The height of the tree.
+ */
+goog.structs.AvlTree.prototype.getHeight = function() {
+ return this.root_ ? this.root_.height : 0;
+};
+
+
+/**
+ * Inserts the values stored in the tree into a new Array and returns the Array.
+ *
+ * @return {Array} An array containing all of the trees values in sorted order.
+ */
+goog.structs.AvlTree.prototype.getValues = function() {
+ var ret = [];
+ this.inOrderTraverse(function(value) {
+ ret.push(value);
+ });
+ return ret;
+};
+
+
+/**
+ * Performs an in-order traversal of the tree and calls {@code func} with each
+ * traversed node, optionally starting from the smallest node with a value >= to
+ * the specified start value. The traversal ends after traversing the tree's
+ * maximum node or when {@code func} returns a value that evaluates to true.
+ *
+ * @param {Function} func Function to call on each traversed node.
+ * @param {Object=} opt_startValue If specified, traversal will begin on the
+ * node with the smallest value >= opt_startValue.
+ */
+goog.structs.AvlTree.prototype.inOrderTraverse =
+ function(func, opt_startValue) {
+ // If our tree is empty, return immediately
+ if (!this.root_) {
+ return;
+ }
+
+ // Depth traverse the tree to find node to begin in-order traversal from
+ var startNode;
+ if (opt_startValue) {
+ this.traverse_(function(node) {
+ var retNode = null;
+ if (this.comparator_(node.value, opt_startValue) > 0) {
+ retNode = node.left;
+ startNode = node;
+ } else if (this.comparator_(node.value, opt_startValue) < 0) {
+ retNode = node.right;
+ } else {
+ startNode = node;
+ }
+ return retNode; // If null, we'll stop traversing the tree
+ });
+ } else {
+ startNode = this.getMinNode_();
+ }
+
+ // Traverse the tree and call func on each traversed node's value
+ var node = startNode, prev = startNode.left ? startNode.left : startNode;
+ while (node != null) {
+ if (node.left != null && node.left != prev && node.right != prev) {
+ node = node.left;
+ } else {
+ if (node.right != prev) {
+ if (func(node.value)) {
+ return;
+ }
+ }
+ var temp = node;
+ node = node.right != null && node.right != prev ?
+ node.right :
+ node.parent;
+ prev = temp;
+ }
+ }
+};
+
+
+/**
+ * Performs a reverse-order traversal of the tree and calls {@code func} with
+ * each traversed node, optionally starting from the largest node with a value
+ * <= to the specified start value. The traversal ends after traversing the
+ * tree's minimum node or when func returns a value that evaluates to true.
+ *
+ * @param {Function} func Function to call on each traversed node.
+ * @param {Object=} opt_startValue If specified, traversal will begin on the
+ * node with the largest value <= opt_startValue.
+ */
+goog.structs.AvlTree.prototype.reverseOrderTraverse =
+ function(func, opt_startValue) {
+ // If our tree is empty, return immediately
+ if (!this.root_) {
+ return;
+ }
+
+ // Depth traverse the tree to find node to begin reverse-order traversal from
+ var startNode;
+ if (opt_startValue) {
+ this.traverse_(goog.bind(function(node) {
+ var retNode = null;
+ if (this.comparator_(node.value, opt_startValue) > 0) {
+ retNode = node.left;
+ } else if (this.comparator_(node.value, opt_startValue) < 0) {
+ retNode = node.right;
+ startNode = node;
+ } else {
+ startNode = node;
+ }
+ return retNode; // If null, we'll stop traversing the tree
+ }, this));
+ } else {
+ startNode = this.getMaxNode_();
+ }
+
+ // Traverse the tree and call func on each traversed node's value
+ var node = startNode, prev = startNode.right ? startNode.right : startNode;
+ while (node != null) {
+ if (node.right != null && node.right != prev && node.left != prev) {
+ node = node.right;
+ } else {
+ if (node.left != prev) {
+ if (func(node.value)) {
+ return;
+ }
+ }
+ var temp = node;
+ node = node.left != null && node.left != prev ?
+ node.left :
+ node.parent;
+ prev = temp;
+ }
+ }
+};
+
+
+/**
+ * Performs a traversal defined by the supplied {@code traversalFunc}. The first
+ * call to {@code traversalFunc} is passed the root or the optionally specified
+ * startNode. After that, calls {@code traversalFunc} with the node returned
+ * by the previous call to {@code traversalFunc} until {@code traversalFunc}
+ * returns null or the optionally specified endNode. The first call to
+ * traversalFunc is passed the root or the optionally specified startNode.
+ *
+ * @param {Function} traversalFunc Function used to traverse the tree. Takes a
+ * node as a parameter and returns a node.
+ * @param {goog.structs.AvlTree.Node=} opt_startNode The node at which the
+ * traversal begins.
+ * @param {goog.structs.AvlTree.Node=} opt_endNode The node at which the
+ * traversal ends.
+ * @private
+ */
+goog.structs.AvlTree.prototype.traverse_ =
+ function(traversalFunc, opt_startNode, opt_endNode) {
+ var node = opt_startNode ? opt_startNode : this.root_;
+ var endNode = opt_endNode ? opt_endNode : null;
+ while (node && node != endNode) {
+ node = traversalFunc.call(this, node);
+ }
+};
+
+
+/**
+ * Ensures that the specified node and all its ancestors are balanced. If they
+ * are not, performs left and right tree rotations to achieve a balanced
+ * tree. This method assumes that at most 2 rotations are necessary to balance
+ * the tree (which is true for AVL-trees that are balanced after each node is
+ * added or removed).
+ *
+ * @param {goog.structs.AvlTree.Node} node Node to begin balance from.
+ * @private
+ */
+goog.structs.AvlTree.prototype.balance_ = function(node) {
+
+ this.traverse_(function(node) {
+ // Calculate the left and right node's heights
+ var lh = node.left ? node.left.height : 0;
+ var rh = node.right ? node.right.height : 0;
+
+ // Rotate tree rooted at this node if it is not AVL-tree balanced
+ if (lh - rh > 1) {
+ if (node.left.right && (!node.left.left ||
+ node.left.left.height < node.left.right.height)) {
+ this.leftRotate_(node.left);
+ }
+ this.rightRotate_(node);
+ } else if (rh - lh > 1) {
+ if (node.right.left && (!node.right.right ||
+ node.right.right.height < node.right.left.height)) {
+ this.rightRotate_(node.right);
+ }
+ this.leftRotate_(node);
+ }
+
+ // Recalculate the left and right node's heights
+ lh = node.left ? node.left.height : 0;
+ rh = node.right ? node.right.height : 0;
+
+ // Set this node's height
+ node.height = Math.max(lh, rh) + 1;
+
+ // Traverse up tree and balance parent
+ return node.parent;
+ }, node);
+
+};
+
+
+/**
+ * Performs a left tree rotation on the specified node.
+ *
+ * @param {goog.structs.AvlTree.Node} node Pivot node to rotate from.
+ * @private
+ */
+goog.structs.AvlTree.prototype.leftRotate_ = function(node) {
+ // Re-assign parent-child references for the parent of the node being removed
+ if (node.isLeftChild()) {
+ node.parent.left = node.right;
+ node.right.parent = node.parent;
+ } else if (node.isRightChild()) {
+ node.parent.right = node.right;
+ node.right.parent = node.parent;
+ } else {
+ this.root_ = node.right;
+ this.root_.parent = null;
+ }
+
+ // Re-assign parent-child references for the child of the node being removed
+ var temp = node.right;
+ node.right = node.right.left;
+ if (node.right != null) node.right.parent = node;
+ temp.left = node;
+ node.parent = temp;
+};
+
+
+/**
+ * Performs a right tree rotation on the specified node.
+ *
+ * @param {goog.structs.AvlTree.Node} node Pivot node to rotate from.
+ * @private
+ */
+goog.structs.AvlTree.prototype.rightRotate_ = function(node) {
+ // Re-assign parent-child references for the parent of the node being removed
+ if (node.isLeftChild()) {
+ node.parent.left = node.left;
+ node.left.parent = node.parent;
+ } else if (node.isRightChild()) {
+ node.parent.right = node.left;
+ node.left.parent = node.parent;
+ } else {
+ this.root_ = node.left;
+ this.root_.parent = null;
+ }
+
+ // Re-assign parent-child references for the child of the node being removed
+ var temp = node.left;
+ node.left = node.left.right;
+ if (node.left != null) node.left.parent = node;
+ temp.right = node;
+ node.parent = temp;
+};
+
+
+/**
+ * Removes the specified node from the tree and ensures the tree still
+ * maintains the AVL-tree balance.
+ *
+ * @param {goog.structs.AvlTree.Node} node The node to be removed.
+ * @private
+ */
+goog.structs.AvlTree.prototype.removeNode_ = function(node) {
+ // Perform normal binary tree node removal, but balance the tree, starting
+ // from where we removed the node
+ if (node.left != null || node.right != null) {
+ var b = null; // Node to begin balance from
+ var r; // Node to replace the node being removed
+ if (node.left != null) {
+ r = this.getMaxNode_(node.left);
+ if (r != node.left) {
+ r.parent.right = r.left;
+ if (r.left) r.left.parent = r.parent;
+ r.left = node.left;
+ r.left.parent = r;
+ b = r.parent;
+ }
+ r.parent = node.parent;
+ r.right = node.right;
+ if (r.right) r.right.parent = r;
+ if (node == this.maxNode_) this.maxNode_ = r;
+ } else {
+ r = this.getMinNode_(node.right);
+ if (r != node.right) {
+ r.parent.left = r.right;
+ if (r.right) r.right.parent = r.parent;
+ r.right = node.right;
+ r.right.parent = r;
+ b = r.parent;
+ }
+ r.parent = node.parent;
+ r.left = node.left;
+ if (r.left) r.left.parent = r;
+ if (node == this.minNode_) this.minNode_ = r;
+ }
+
+ // Update the parent of the node being removed to point to its replace
+ if (node.isLeftChild()) {
+ node.parent.left = r;
+ } else if (node.isRightChild()) {
+ node.parent.right = r;
+ } else {
+ this.root_ = r;
+ }
+
+ // Balance the tree
+ this.balance_(b ? b : r);
+ } else {
+ // If the node is a leaf, remove it and balance starting from its parent
+ if (node.isLeftChild()) {
+ this.special = 1;
+ node.parent.left = null;
+ if (node == this.minNode_) this.minNode_ = node.parent;
+ this.balance_(node.parent);
+ } else if (node.isRightChild()) {
+ node.parent.right = null;
+ if (node == this.maxNode_) this.maxNode_ = node.parent;
+ this.balance_(node.parent);
+ } else {
+ this.clear();
+ }
+ }
+};
+
+
+/**
+ * Returns the node with the smallest value in tree, optionally rooted at
+ * {@code opt_rootNode}.
+ *
+ * @param {goog.structs.AvlTree.Node=} opt_rootNode Optional root node.
+ * @return {goog.structs.AvlTree.Node} The node with the smallest value in
+ * the tree.
+ * @private
+ */
+goog.structs.AvlTree.prototype.getMinNode_ = function(opt_rootNode) {
+ if (!opt_rootNode) {
+ return this.minNode_;
+ }
+
+ var minNode = opt_rootNode;
+ this.traverse_(function(node) {
+ var retNode = null;
+ if (node.left) {
+ minNode = node.left;
+ retNode = node.left;
+ }
+ return retNode; // If null, we'll stop traversing the tree
+ }, opt_rootNode);
+
+ return minNode;
+};
+
+
+/**
+ * Returns the node with the largest value in tree, optionally rooted at
+ * opt_rootNode.
+ *
+ * @param {goog.structs.AvlTree.Node=} opt_rootNode Optional root node.
+ * @return {goog.structs.AvlTree.Node} The node with the largest value in
+ * the tree.
+ * @private
+ */
+goog.structs.AvlTree.prototype.getMaxNode_ = function(opt_rootNode) {
+ if (!opt_rootNode) {
+ return this.maxNode_;
+ }
+
+ var maxNode = opt_rootNode;
+ this.traverse_(function(node) {
+ var retNode = null;
+ if (node.right) {
+ maxNode = node.right;
+ retNode = node.right;
+ }
+ return retNode; // If null, we'll stop traversing the tree
+ }, opt_rootNode);
+
+ return maxNode;
+};
+
+
+
+/**
+ * Constructs an AVL-Tree node with the specified value. If no parent is
+ * specified, the node's parent is assumed to be null. The node's height
+ * defaults to 1 and its children default to null.
+ *
+ * @param {*} value Value to store in the node.
+ * @param {goog.structs.AvlTree.Node=} opt_parent Optional parent node.
+ * @constructor
+ */
+goog.structs.AvlTree.Node = function(value, opt_parent) {
+ /**
+ * The value stored by the node.
+ *
+ * @type {*}
+ */
+ this.value = value;
+
+ /**
+ * The node's parent. Null if the node is the root.
+ *
+ * @type {goog.structs.AvlTree.Node}
+ */
+ this.parent = opt_parent ? opt_parent : null;
+};
+
+
+/**
+ * The node's left child. Null if the node does not have a left child.
+ *
+ * @type {goog.structs.AvlTree.Node?}
+ */
+goog.structs.AvlTree.Node.prototype.left = null;
+
+
+/**
+ * The node's right child. Null if the node does not have a right child.
+ *
+ * @type {goog.structs.AvlTree.Node?}
+ */
+goog.structs.AvlTree.Node.prototype.right = null;
+
+
+/**
+ * The height of the tree rooted at this node.
+ *
+ * @type {number}
+ */
+goog.structs.AvlTree.Node.prototype.height = 1;
+
+
+/**
+ * Returns true iff the specified node has a parent and is the right child of
+ * its parent.
+ *
+ * @return {boolean} Whether the specified node has a parent and is the right
+ * child of its parent.
+ */
+goog.structs.AvlTree.Node.prototype.isRightChild = function() {
+ return !!this.parent && this.parent.right == this;
+};
+
+
+/**
+ * Returns true iff the specified node has a parent and is the left child of
+ * its parent.
+ *
+ * @return {boolean} Whether the specified node has a parent and is the left
+ * child of its parent.
+ */
+goog.structs.AvlTree.Node.prototype.isLeftChild = function() {
+ return !!this.parent && this.parent.left == this;
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/avltree_test.html b/contexts/data/lib/closure-library/closure/goog/structs/avltree_test.html
new file mode 100644
index 0000000..144047d
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/avltree_test.html
@@ -0,0 +1,251 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2007 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs.AvlTree</title>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.structs');
+ goog.require('goog.structs.AvlTree');
+ goog.require('goog.testing.jsunit');
+</script>
+</head>
+<body>
+<script>
+
+ /**
+ * This test verifies that we can insert strings into the AvlTree and have
+ * them be stored and sorted correctly by the default comparator.
+ */
+ function testInsertsWithDefaultComparator() {
+ var tree = new goog.structs.AvlTree();
+ var values = ['bill', 'blake', 'elliot', 'jacob', 'john', 'myles', 'ted'];
+
+ // Insert strings into tree out of order
+ tree.add(values[4]);
+ tree.add(values[3]);
+ tree.add(values[0]);
+ tree.add(values[6]);
+ tree.add(values[5]);
+ tree.add(values[1]);
+ tree.add(values[2]);
+
+ // Verify strings are stored in sorted order
+ var i = 0;
+ tree.inOrderTraverse(function(value) {
+ assertEquals(values[i], value);
+ i += 1;
+ });
+ assertEquals(i, values.length);
+ };
+
+ /**
+ * This test verifies that we can insert strings into and remove strings from
+ * the AvlTree and have the only the non-removed values be stored and sorted
+ * correctly by the default comparator.
+ */
+ function testRemovesWithDefaultComparator() {
+ var tree = new goog.structs.AvlTree();
+ var values = ['bill', 'blake', 'elliot', 'jacob', 'john', 'myles', 'ted'];
+
+ // Insert strings into tree out of order
+ tree.add('frodo');
+ tree.add(values[4]);
+ tree.add(values[3]);
+ tree.add(values[0]);
+ tree.add(values[6]);
+ tree.add('samwise');
+ tree.add(values[5]);
+ tree.add(values[1]);
+ tree.add(values[2]);
+ tree.add('pippin');
+
+ // Remove strings from tree
+ assertEquals(tree.remove('samwise'), 'samwise');
+ assertEquals(tree.remove('pippin'), 'pippin');
+ assertEquals(tree.remove('frodo'), 'frodo');
+ assertEquals(tree.remove('merry'), null);
+
+
+ // Verify strings are stored in sorted order
+ var i = 0;
+ tree.inOrderTraverse(function(value) {
+ assertEquals(values[i], value);
+ i += 1;
+ });
+ assertEquals(i, values.length);
+ };
+
+ /**
+ * This test verifies that we can insert values into and remove values from
+ * the AvlTree and have them be stored and sorted correctly by a custom
+ * comparator.
+ */
+ function testInsertsAndRemovesWithCustomComparator() {
+ var tree = new goog.structs.AvlTree(function(a, b) {
+ return a - b;
+ });
+
+ var NUM_TO_INSERT = 37;
+ var valuesToRemove = [1, 0, 6, 7, 36];
+
+ // Insert ints into tree out of order
+ var values = [];
+ for (var i = 0; i < NUM_TO_INSERT; i += 1) {
+ tree.add(i);
+ values.push(i);
+ }
+
+ for (var i = 0; i < valuesToRemove.length; i += 1) {
+ assertEquals(tree.remove(valuesToRemove[i]), valuesToRemove[i]);
+ goog.array.remove(values, valuesToRemove[i]);
+ }
+ assertEquals(tree.remove(-1), null);
+ assertEquals(tree.remove(37), null);
+
+ // Verify strings are stored in sorted order
+ var i = 0;
+ tree.inOrderTraverse(function(value) {
+ assertEquals(values[i], value);
+ i += 1;
+ });
+ assertEquals(i, values.length);
+ };
+
+ /**
+ * This test verifies that we can insert values into and remove values from
+ * the AvlTree and have it maintain the AVL-Tree upperbound on its height.
+ */
+ function testAvlTreeHeight() {
+ var tree = new goog.structs.AvlTree(function(a, b) {
+ return a - b;
+ });
+
+ var NUM_TO_INSERT = 2000;
+ var NUM_TO_REMOVE = 500;
+
+ // Insert ints into tree out of order
+ for (var i = 0; i < NUM_TO_INSERT; i += 1) {
+ tree.add(i);
+ }
+
+ // Remove valuse
+ for (var i = 0; i < NUM_TO_REMOVE; i += 1) {
+ tree.remove(i);
+ }
+
+ assertTrue(tree.getHeight() <= 1.4405 *
+ (Math.log(NUM_TO_INSERT - NUM_TO_REMOVE + 2) / Math.log(2)) - 1.3277);
+ };
+
+ /**
+ * This test verifies that we can insert values into and remove values from
+ * the AvlTree and have its contains method correctly determine the values it
+ * is contains.
+ */
+ function testAvlTreeContains() {
+ var tree = new goog.structs.AvlTree();
+ var values = ['bill', 'blake', 'elliot', 'jacob', 'john', 'myles', 'ted'];
+
+ // Insert strings into tree out of order
+ tree.add('frodo');
+ tree.add(values[4]);
+ tree.add(values[3]);
+ tree.add(values[0]);
+ tree.add(values[6]);
+ tree.add('samwise');
+ tree.add(values[5]);
+ tree.add(values[1]);
+ tree.add(values[2]);
+ tree.add('pippin');
+
+ // Remove strings from tree
+ assertEquals(tree.remove('samwise'), 'samwise');
+ assertEquals(tree.remove('pippin'), 'pippin');
+ assertEquals(tree.remove('frodo'), 'frodo');
+
+ for (var i = 0; i < values.length; i += 1) {
+ assertTrue(tree.contains(values[i]));
+ }
+ assertFalse(tree.contains('samwise'));
+ assertFalse(tree.contains('pippin'));
+ assertFalse(tree.contains('frodo'));
+ };
+
+ /**
+ * This test verifies that we can insert values into and remove values from
+ * the AvlTree and have its minValue and maxValue routines return the correct
+ * min and max values contained by the tree.
+ */
+ function testMinAndMaxValues() {
+ var tree = new goog.structs.AvlTree(function(a, b) {
+ return a - b;
+ });
+
+ var NUM_TO_INSERT = 2000;
+ var NUM_TO_REMOVE = 500;
+
+ // Insert ints into tree out of order
+ for (var i = 0; i < NUM_TO_INSERT; i += 1) {
+ tree.add(i);
+ }
+
+ // Remove valuse
+ for (var i = 0; i < NUM_TO_REMOVE; i += 1) {
+ tree.remove(i);
+ }
+
+ assertEquals(tree.getMinimum(), NUM_TO_REMOVE);
+ assertEquals(tree.getMaximum(), NUM_TO_INSERT - 1);
+ };
+
+ /**
+ * This test verifies that we can insert values into and remove values from
+ * the AvlTree and traverse the tree in reverse order using the
+ * reverseOrderTraverse routine.
+ */
+ function testReverseOrderTraverse() {
+ var tree = new goog.structs.AvlTree(function(a, b) {
+ return a - b;
+ });
+
+ var NUM_TO_INSERT = 2000;
+ var NUM_TO_REMOVE = 500;
+
+ // Insert ints into tree out of order
+ for (var i = 0; i < NUM_TO_INSERT; i += 1) {
+ tree.add(i);
+ }
+
+ // Remove valuse
+ for (var i = 0; i < NUM_TO_REMOVE; i += 1) {
+ tree.remove(i);
+ }
+
+ var i = NUM_TO_INSERT - 1;
+ tree.reverseOrderTraverse(function(value) {
+ assertEquals(value, i);
+ i -= 1;
+ });
+ assertEquals(i, NUM_TO_REMOVE - 1);
+ };
+
+ /**
+ * Verifies correct behavior of getCount(). See http://b/4347755
+ */
+ function testGetCountBehavior() {
+ var tree = new goog.structs.AvlTree();
+ tree.add(1);
+ tree.remove(1);
+ assertEquals(0, tree.getCount());
+ }
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/circularbuffer.js b/contexts/data/lib/closure-library/closure/goog/structs/circularbuffer.js
new file mode 100644
index 0000000..2964559
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/circularbuffer.js
@@ -0,0 +1,219 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+
+/**
+ * @fileoverview Datastructure: Circular Buffer.
+ *
+ * Implements a buffer with a maximum size. New entries override the oldest
+ * entries when the maximum size has been reached.
+ *
+ */
+
+
+goog.provide('goog.structs.CircularBuffer');
+
+
+
+/**
+ * Class for CircularBuffer.
+ * @param {number=} opt_maxSize The maximum size of the buffer.
+ * @constructor
+ */
+goog.structs.CircularBuffer = function(opt_maxSize) {
+ /**
+ * Maximum size of the the circular array structure.
+ * @type {number}
+ * @private
+ */
+ this.maxSize_ = opt_maxSize || 100;
+
+ /**
+ * Underlying array for the CircularBuffer.
+ * @type {Array}
+ * @private
+ */
+ this.buff_ = [];
+};
+
+
+/**
+ * Index of the next element in the circular array structure.
+ * @type {number}
+ * @private
+ */
+goog.structs.CircularBuffer.prototype.nextPtr_ = 0;
+
+
+/**
+ * Adds an item to the buffer. May remove the oldest item if the buffer is at
+ * max size.
+ * @param {*} item The item to add.
+ */
+goog.structs.CircularBuffer.prototype.add = function(item) {
+ this.buff_[this.nextPtr_] = item;
+ this.nextPtr_ = (this.nextPtr_ + 1) % this.maxSize_;
+};
+
+
+/**
+ * Returns the item at the specified index.
+ * @param {number} index The index of the item. The index of an item can change
+ * after calls to {@code add()} if the buffer is at maximum size.
+ * @return {*} The item at the specified index.
+ */
+goog.structs.CircularBuffer.prototype.get = function(index) {
+ index = this.normalizeIndex_(index);
+ return this.buff_[index];
+};
+
+
+/**
+ * Sets the item at the specified index.
+ * @param {number} index The index of the item. The index of an item can change
+ * after calls to {@code add()} if the buffer is at maximum size.
+ * @param {*} item The item to add.
+ */
+goog.structs.CircularBuffer.prototype.set = function(index, item) {
+ index = this.normalizeIndex_(index);
+ this.buff_[index] = item;
+};
+
+
+/**
+ * Returns the current number of items in the buffer.
+ * @return {number} The current number of items in the buffer.
+ */
+goog.structs.CircularBuffer.prototype.getCount = function() {
+ return this.buff_.length;
+};
+
+
+/**
+ * @return {boolean} Whether the buffer is empty.
+ */
+goog.structs.CircularBuffer.prototype.isEmpty = function() {
+ return this.buff_.length == 0;
+};
+
+
+/**
+ * Empties the current buffer.
+ */
+goog.structs.CircularBuffer.prototype.clear = function() {
+ this.buff_.length = 0;
+ this.nextPtr_ = 0;
+};
+
+
+/**
+ * @return {Array} The values in the buffer.
+ */
+goog.structs.CircularBuffer.prototype.getValues = function() {
+ // getNewestValues returns all the values if the maxCount parameter is the
+ // count
+ return this.getNewestValues(this.getCount());
+};
+
+
+/**
+ * Returns the newest values in the buffer up to {@code count}.
+ * @param {number} maxCount The maximum number of values to get. Should be a
+ * positive number.
+ * @return {Array} The newest values in the buffer up to {@code count}.
+ */
+goog.structs.CircularBuffer.prototype.getNewestValues = function(maxCount) {
+ var l = this.getCount();
+ var start = this.getCount() - maxCount;
+ var rv = [];
+ for (var i = start; i < l; i++) {
+ rv[i] = this.get(i);
+ }
+ return rv;
+};
+
+
+/**
+ * @return {Array} The indexes in the buffer.
+ */
+goog.structs.CircularBuffer.prototype.getKeys = function() {
+ var rv = [];
+ var l = this.getCount();
+ for (var i = 0; i < l; i++) {
+ rv[i] = i;
+ }
+ return rv;
+};
+
+
+/**
+ * Whether the buffer contains the key/index.
+ * @param {number} key The key/index to check for.
+ * @return {boolean} Whether the buffer contains the key/index.
+ */
+goog.structs.CircularBuffer.prototype.containsKey = function(key) {
+ return key < this.getCount();
+};
+
+
+/**
+ * Whether the buffer contains the given value.
+ * @param {*} value The value to check for.
+ * @return {boolean} Whether the buffer contains the given value.
+ */
+goog.structs.CircularBuffer.prototype.containsValue = function(value) {
+ var l = this.getCount();
+ for (var i = 0; i < l; i++) {
+ if (this.get(i) == value) {
+ return true;
+ }
+ }
+ return false;
+};
+
+
+/**
+ * Returns the last item inserted into the buffer.
+ * @return {*} The last item inserted into the buffer, or null if the buffer is
+ * empty.
+ */
+goog.structs.CircularBuffer.prototype.getLast = function() {
+ if (this.getCount() == 0) {
+ return null;
+ }
+ return this.get(this.getCount() - 1);
+};
+
+
+/**
+ * Helper function to convert an index in the number space of oldest to
+ * newest items in the array to the position that the element will be at in the
+ * underlying array.
+ * @param {number} index The index of the item in a list ordered from oldest to
+ * newest.
+ * @return {number} The index of the item in the CircularBuffer's underlying
+ * array.
+ * @private
+ */
+goog.structs.CircularBuffer.prototype.normalizeIndex_ = function(index) {
+ if (index >= this.buff_.length) {
+ throw Error('Out of bounds exception');
+ }
+
+ if (this.buff_.length < this.maxSize_) {
+ return index;
+ }
+
+ return (this.nextPtr_ + Number(index)) % this.maxSize_;
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/circularbuffer_test.html b/contexts/data/lib/closure-library/closure/goog/structs/circularbuffer_test.html
new file mode 100644
index 0000000..8d891c8
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/circularbuffer_test.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2006 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs</title>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.structs.CircularBuffer');
+ goog.require('goog.testing.jsunit');
+</script>
+</head>
+<body>
+<script>
+
+function testCircularBuffer() {
+ var buff = new goog.structs.CircularBuffer(2);
+ buff.add('first');
+ assertEquals(1, buff.getCount());
+ assertEquals('first', buff.get(0));
+ assertEquals('first', buff.getLast());
+ buff.add('second');
+ assertEquals(2, buff.getCount());
+ assertEquals('first', buff.get(0));
+ assertEquals('second', buff.get(1));
+ assertEquals('second', buff.getLast());
+ buff.add('third');
+ assertEquals(2, buff.getCount());
+ assertEquals('second', buff.get(0));
+ assertEquals('third', buff.get(1));
+ assertEquals('third', buff.getLast());
+}
+
+function testIsEmpty() {
+ var buff = new goog.structs.CircularBuffer(2);
+ assertTrue('initially empty', buff.isEmpty());
+ buff.add('first');
+ assertFalse('not empty after add empty', buff.isEmpty());
+}
+
+function testClear() {
+ var buff = new goog.structs.CircularBuffer(2);
+ buff.add('first');
+ buff.clear();
+ assertTrue('should be empty after clear', buff.isEmpty());
+
+}
+
+function testGetValues() {
+ var buff = new goog.structs.CircularBuffer(2);
+ buff.add('first');
+ buff.add('second');
+ assertEquals('firstsecond', buff.getValues().join(''));
+}
+
+function testGetNewestVtalues() {
+ var buff = new goog.structs.CircularBuffer(5);
+ buff.add('first');
+ buff.add('second');
+ buff.add('third');
+ buff.add('fourth');
+ buff.add('fifth');
+ assertEquals('fourthfifth', buff.getNewestValues(2).join(''));
+}
+
+
+function testGetKeys() {
+ var buff = new goog.structs.CircularBuffer(2);
+ buff.add('first');
+ buff.add('second');
+ assertEquals('01', buff.getKeys().join(''));
+}
+
+function testContainsValue() {
+ var buff = new goog.structs.CircularBuffer(2);
+ buff.add('first');
+ buff.add('second');
+ assertTrue(buff.containsValue('first'));
+ assertTrue(buff.containsValue('second'));
+ assertFalse(buff.containsValue('third'));
+}
+
+function testContainsKey() {
+ var buff = new goog.structs.CircularBuffer(3);
+ buff.add('first');
+ buff.add('second');
+ buff.add('third');
+ assertTrue(buff.containsKey(0));
+ assertTrue(buff.containsKey('0'));
+ assertTrue(buff.containsKey(1));
+ assertTrue(buff.containsKey('1'));
+ assertTrue(buff.containsKey(2));
+ assertTrue(buff.containsKey('2'));
+ assertFalse(buff.containsKey(3));
+ assertFalse(buff.containsKey('3'));
+}
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/collection.js b/contexts/data/lib/closure-library/closure/goog/structs/collection.js
new file mode 100644
index 0000000..8ba8cb3
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/collection.js
@@ -0,0 +1,54 @@
+// Copyright 2011 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Defines the collection interface.
+ *
+ */
+
+goog.provide('goog.structs.Collection');
+
+
+
+/**
+ * An interface for a collection of values.
+ * @interface
+ */
+goog.structs.Collection = function() {};
+
+
+/**
+ * @param {*} value Value to add to the collection.
+ */
+goog.structs.Collection.prototype.add;
+
+
+/**
+ * @param {*} value Value to remove from the collection.
+ */
+goog.structs.Collection.prototype.remove;
+
+
+/**
+ * @param {*} value Value to find in the tree.
+ * @return {boolean} Whether the collection contains the specified value.
+ */
+goog.structs.Collection.prototype.contains;
+
+
+/**
+ * @return {number} The number of values stored in the collection.
+ */
+goog.structs.Collection.prototype.getCount;
+
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/collection_test.html b/contexts/data/lib/closure-library/closure/goog/structs/collection_test.html
new file mode 100644
index 0000000..1ce9932
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/collection_test.html
@@ -0,0 +1,57 @@
+<!doctype html>
+<html>
+<!--
+Copyright 2011 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+ <head>
+ <title>Closure Unit Tests - goog.structs.Collection</title>
+ <script src="../base.js"></script>
+ <script>
+ goog.require('goog.structs.AvlTree');
+ goog.require('goog.structs.Collection');
+ goog.require('goog.structs.Set');
+ goog.require('goog.testing.jsunit');
+ </script>
+ </head>
+ <body>
+ <script>
+
+function testSet() {
+ var set = new goog.structs.Set();
+ exerciseCollection(set)
+}
+
+function testAvlTree() {
+ var tree = new goog.structs.AvlTree();
+ exerciseCollection(tree)
+}
+
+// Simple exercise of a collection object.
+function exerciseCollection(collection) {
+ assertEquals(0, collection.getCount());
+
+ for (var i = 1; i <= 10; i++) {
+ assertFalse(collection.contains(i));
+ collection.add(i);
+ assertTrue(collection.contains(i));
+ assertEquals(i, collection.getCount());
+ }
+
+ assertEquals(10, collection.getCount());
+
+ for (var i = 10; i > 0; i--) {
+ assertTrue(collection.contains(i));
+ collection.remove(i);
+ assertFalse(collection.contains(i));
+ assertEquals(i - 1, collection.getCount());
+ }
+
+ assertEquals(0, collection.getCount());
+}
+
+ </script>
+ </body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/heap.js b/contexts/data/lib/closure-library/closure/goog/structs/heap.js
new file mode 100644
index 0000000..98c7695
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/heap.js
@@ -0,0 +1,333 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Datastructure: Heap.
+ *
+ *
+ * This file provides the implementation of a Heap datastructure. Smaller keys
+ * rise to the top.
+ *
+ * The big-O notation for all operations are below:
+ * <pre>
+ * Method big-O
+ * ----------------------------------------------------------------------------
+ * - insert O(logn)
+ * - remove O(logn)
+ * - peek O(1)
+ * - contains O(n)
+ * </pre>
+ */
+// TODO(user): Should this rely on natural ordering via some Comparable
+// interface?
+
+
+goog.provide('goog.structs.Heap');
+
+goog.require('goog.array');
+goog.require('goog.object');
+goog.require('goog.structs.Node');
+
+
+
+/**
+ * Class for a Heap datastructure.
+ *
+ * @param {goog.structs.Heap|Object=} opt_heap Optional goog.structs.Heap or
+ * Object to initialize heap with.
+ * @constructor
+ */
+goog.structs.Heap = function(opt_heap) {
+ /**
+ * The nodes of the heap.
+ * @private
+ * @type {Array.<goog.structs.Node>}
+ */
+ this.nodes_ = [];
+
+ if (opt_heap) {
+ this.insertAll(opt_heap);
+ }
+};
+
+
+/**
+ * Insert the given value into the heap with the given key.
+ * @param {*} key The key.
+ * @param {*} value The value.
+ */
+goog.structs.Heap.prototype.insert = function(key, value) {
+ var node = new goog.structs.Node(key, value);
+ var nodes = this.nodes_;
+ nodes.push(node);
+ this.moveUp_(nodes.length - 1);
+};
+
+
+/**
+ * Adds multiple key-value pairs from another goog.structs.Heap or Object
+ * @param {goog.structs.Heap|Object} heap Object containing the data to add.
+ */
+goog.structs.Heap.prototype.insertAll = function(heap) {
+ var keys, values;
+ if (heap instanceof goog.structs.Heap) {
+ keys = heap.getKeys();
+ values = heap.getValues();
+
+ // If it is a heap and the current heap is empty, I can realy on the fact
+ // that the keys/values are in the correct order to put in the underlying
+ // structure.
+ if (heap.getCount() <= 0) {
+ var nodes = this.nodes_;
+ for (var i = 0; i < keys.length; i++) {
+ nodes.push(new goog.structs.Node(keys[i], values[i]));
+ }
+ return;
+ }
+ } else {
+ keys = goog.object.getKeys(heap);
+ values = goog.object.getValues(heap);
+ }
+
+ for (var i = 0; i < keys.length; i++) {
+ this.insert(keys[i], values[i]);
+ }
+};
+
+
+/**
+ * Retrieves and removes the root value of this heap.
+ * @return {*} The value removed from the root of the heap. Returns
+ * undefined if the heap is empty.
+ */
+goog.structs.Heap.prototype.remove = function() {
+ var nodes = this.nodes_;
+ var count = nodes.length;
+ var rootNode = nodes[0];
+ if (count <= 0) {
+ return undefined;
+ } else if (count == 1) {
+ goog.array.clear(nodes);
+ } else {
+ nodes[0] = nodes.pop();
+ this.moveDown_(0);
+ }
+ return rootNode.getValue();
+};
+
+
+/**
+ * Retrieves but does not remove the root value of this heap.
+ * @return {*} The value at the root of the heap. Returns
+ * undefined if the heap is empty.
+ */
+goog.structs.Heap.prototype.peek = function() {
+ var nodes = this.nodes_;
+ if (nodes.length == 0) {
+ return undefined;
+ }
+ return nodes[0].getValue();
+};
+
+
+/**
+ * Retrieves but does not remove the key of the root node of this heap.
+ * @return {*} The key at the root of the heap. Returns undefined if the
+ * heap is empty.
+ */
+goog.structs.Heap.prototype.peekKey = function() {
+ return this.nodes_[0] && this.nodes_[0].getKey();
+};
+
+
+/**
+ * Moves the node at the given index down to its proper place in the heap.
+ * @param {number} index The index of the node to move down.
+ * @private
+ */
+goog.structs.Heap.prototype.moveDown_ = function(index) {
+ var nodes = this.nodes_;
+ var count = nodes.length;
+
+ // Save the node being moved down.
+ var node = nodes[index];
+ // While the current node has a child.
+ while (index < (count >> 1)) {
+ var leftChildIndex = this.getLeftChildIndex_(index);
+ var rightChildIndex = this.getRightChildIndex_(index);
+
+ // Determine the index of the smaller child.
+ var smallerChildIndex = rightChildIndex < count &&
+ nodes[rightChildIndex].getKey() < nodes[leftChildIndex].getKey() ?
+ rightChildIndex : leftChildIndex;
+
+ // If the node being moved down is smaller than its children, the node
+ // has found the correct index it should be at.
+ if (nodes[smallerChildIndex].getKey() > node.getKey()) {
+ break;
+ }
+
+ // If not, then take the smaller child as the current node.
+ nodes[index] = nodes[smallerChildIndex];
+ index = smallerChildIndex;
+ }
+ nodes[index] = node;
+};
+
+
+/**
+ * Moves the node at the given index up to its proper place in the heap.
+ * @param {number} index The index of the node to move up.
+ * @private
+ */
+goog.structs.Heap.prototype.moveUp_ = function(index) {
+ var nodes = this.nodes_;
+ var node = nodes[index];
+
+ // While the node being moved up is not at the root.
+ while (index > 0) {
+ // If the parent is less than the node being moved up, move the parent down.
+ var parentIndex = this.getParentIndex_(index);
+ if (nodes[parentIndex].getKey() > node.getKey()) {
+ nodes[index] = nodes[parentIndex];
+ index = parentIndex;
+ } else {
+ break;
+ }
+ }
+ nodes[index] = node;
+};
+
+
+/**
+ * Gets the index of the left child of the node at the given index.
+ * @param {number} index The index of the node to get the left child for.
+ * @return {number} The index of the left child.
+ * @private
+ */
+goog.structs.Heap.prototype.getLeftChildIndex_ = function(index) {
+ return index * 2 + 1;
+};
+
+
+/**
+ * Gets the index of the right child of the node at the given index.
+ * @param {number} index The index of the node to get the right child for.
+ * @return {number} The index of the right child.
+ * @private
+ */
+goog.structs.Heap.prototype.getRightChildIndex_ = function(index) {
+ return index * 2 + 2;
+};
+
+
+/**
+ * Gets the index of the parent of the node at the given index.
+ * @param {number} index The index of the node to get the parent for.
+ * @return {number} The index of the parent.
+ * @private
+ */
+goog.structs.Heap.prototype.getParentIndex_ = function(index) {
+ return (index - 1) >> 1;
+};
+
+
+/**
+ * Gets the values of the heap.
+ * @return {Array} The values in the heap.
+ */
+goog.structs.Heap.prototype.getValues = function() {
+ var nodes = this.nodes_;
+ var rv = [];
+ var l = nodes.length;
+ for (var i = 0; i < l; i++) {
+ rv.push(nodes[i].getValue());
+ }
+ return rv;
+};
+
+
+/**
+ * Gets the keys of the heap.
+ * @return {Array} The keys in the heap.
+ */
+goog.structs.Heap.prototype.getKeys = function() {
+ var nodes = this.nodes_;
+ var rv = [];
+ var l = nodes.length;
+ for (var i = 0; i < l; i++) {
+ rv.push(nodes[i].getKey());
+ }
+ return rv;
+};
+
+
+/**
+ * Whether the heap contains the given value.
+ * @param {Object} val The value to check for.
+ * @return {boolean} Whether the heap contains the value.
+ */
+goog.structs.Heap.prototype.containsValue = function(val) {
+ return goog.array.some(this.nodes_, function(node) {
+ return node.getValue() == val;
+ });
+};
+
+
+/**
+ * Whether the heap contains the given key.
+ * @param {Object} key The key to check for.
+ * @return {boolean} Whether the heap contains the key.
+ */
+goog.structs.Heap.prototype.containsKey = function(key) {
+ return goog.array.some(this.nodes_, function(node) {
+ return node.getKey() == key;
+ });
+};
+
+
+/**
+ * Clones a heap and returns a new heap
+ * @return {goog.structs.Heap} A new goog.structs.Heap with the same key-value
+ * pairs.
+ */
+goog.structs.Heap.prototype.clone = function() {
+ return new goog.structs.Heap(this);
+};
+
+
+/**
+ * The number of key-value pairs in the map
+ * @return {number} The number of pairs.
+ */
+goog.structs.Heap.prototype.getCount = function() {
+ return this.nodes_.length;
+};
+
+
+/**
+ * Returns true if this heap contains no elements.
+ * @return {boolean} Whether this heap contains no elements.
+ */
+goog.structs.Heap.prototype.isEmpty = function() {
+ return goog.array.isEmpty(this.nodes_);
+};
+
+
+/**
+ * Removes all elements from the heap.
+ */
+goog.structs.Heap.prototype.clear = function() {
+ goog.array.clear(this.nodes_);
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/heap_test.html b/contexts/data/lib/closure-library/closure/goog/structs/heap_test.html
new file mode 100644
index 0000000..de7e093
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/heap_test.html
@@ -0,0 +1,220 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2006 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs.Heap</title>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.structs');
+ goog.require('goog.structs.Heap');
+ goog.require('goog.testing.jsunit');
+</script>
+</head>
+<body>
+<script>
+
+function getHeap() {
+ var h = new goog.structs.Heap();
+ h.insert(0, 'a');
+ h.insert(1, 'b');
+ h.insert(2, 'c');
+ h.insert(3, 'd');
+ return h;
+}
+
+
+function getHeap2() {
+ var h = new goog.structs.Heap();
+ h.insert(1, 'b');
+ h.insert(3, 'd');
+ h.insert(0, 'a');
+ h.insert(2, 'c');
+ return h;
+}
+
+
+function testGetCount1() {
+ var h = getHeap();
+ assertEquals('count, should be 4', h.getCount(), 4);
+ h.remove();
+ assertEquals('count, should be 3', h.getCount(), 3);
+}
+
+function testGetCount2() {
+ var h = getHeap();
+ h.remove();
+ h.remove();
+ h.remove();
+ h.remove();
+ assertEquals('count, should be 0', h.getCount(), 0);
+}
+
+
+function testKeys() {
+ var h = getHeap();
+ var keys = h.getKeys();
+ for (var i = 0; i < 4; i++) {
+ assertTrue('getKeys, key ' + i + ' found', goog.structs.contains(keys, i));
+ }
+ assertEquals('getKeys, Should be 4 keys', goog.structs.getCount(keys), 4);
+}
+
+
+function testValues() {
+ var h = getHeap();
+ var values = h.getValues();
+
+ assertTrue('getKeys, value "a" found', goog.structs.contains(values, 'a'));
+ assertTrue('getKeys, value "b" found', goog.structs.contains(values, 'b'));
+ assertTrue('getKeys, value "c" found', goog.structs.contains(values, 'c'));
+ assertTrue('getKeys, value "d" found', goog.structs.contains(values, 'd'));
+ assertEquals('getKeys, Should be 4 keys', goog.structs.getCount(values), 4);
+}
+
+
+function testContainsKey() {
+ var h = getHeap();
+
+ for (var i = 0; i < 4; i++) {
+ assertTrue('containsKey, key ' + i + ' found', h.containsKey(i));
+ }
+ assertFalse('containsKey, value 4 not found', h.containsKey(4));
+}
+
+
+function testContainsValue() {
+ var h = getHeap();
+
+ assertTrue('containsValue, value "a" found', h.containsValue('a'));
+ assertTrue('containsValue, value "b" found', h.containsValue('b'));
+ assertTrue('containsValue, value "c" found', h.containsValue('c'));
+ assertTrue('containsValue, value "d" found', h.containsValue('d'));
+ assertFalse('containsValue, value "e" not found', h.containsValue('e'));
+}
+
+
+function testClone() {
+ var h = getHeap();
+ var h2 = h.clone();
+ assertTrue('clone so it should not be empty', !h2.isEmpty());
+ assertTrue('clone so it should contain key 0', h2.containsKey(0));
+ assertTrue('clone so it should contain value "a"', h2.containsValue('a'));
+}
+
+
+function testClear() {
+ var h = getHeap();
+ h.clear();
+ assertTrue('cleared so it should be empty', h.isEmpty());
+}
+
+
+function testIsEmpty() {
+ var h = getHeap();
+ assertFalse('4 values so should not be empty', h.isEmpty());
+
+ h.remove();
+ h.remove();
+ h.remove();
+ assertFalse('1 values so should not be empty', h.isEmpty());
+
+ h.remove();
+ assertTrue('0 values so should be empty', h.isEmpty());
+}
+
+
+function testPeek1() {
+ var h = getHeap();
+ assertEquals('peek, Should be "a"', h.peek(), 'a');
+}
+
+
+function testPeek2() {
+ var h = getHeap2();
+ assertEquals('peek, Should be "a"', h.peek(), 'a');
+}
+
+
+function testPeek3() {
+ var h = getHeap();
+ h.clear();
+ assertEquals('peek, Should be "undefined"', h.peek(), undefined);
+}
+
+
+function testPeekKey1() {
+ var h = getHeap();
+ assertEquals('peekKey, Should be "0"', h.peekKey(), 0);
+}
+
+
+function testPeekKey2() {
+ var h = getHeap2();
+ assertEquals('peekKey, Should be "0"', h.peekKey(), 0);
+}
+
+
+function testPeekKey3() {
+ var h = getHeap();
+ h.clear();
+ assertEquals('peekKey, Should be "undefined"', h.peekKey(), undefined);
+}
+
+
+function testRemove1() {
+ var h = getHeap();
+
+ assertEquals('remove, Should be "a"', h.remove(), 'a');
+ assertEquals('remove, Should be "b"', h.remove(), 'b');
+ assertEquals('remove, Should be "c"', h.remove(), 'c');
+ assertEquals('remove, Should be "d"', h.remove(), 'd');
+}
+
+
+function testRemove2() {
+ var h = getHeap2();
+
+ assertEquals('remove, Should be "a"', h.remove(), 'a');
+ assertEquals('remove, Should be "b"', h.remove(), 'b');
+ assertEquals('remove, Should be "c"', h.remove(), 'c');
+ assertEquals('remove, Should be "d"', h.remove(), 'd');
+}
+
+
+function testInsertPeek1() {
+ var h = new goog.structs.Heap();
+
+ h.insert(3, 'd');
+ assertEquals('peek, Should be "d"', h.peek(), 'd');
+ h.insert(2, 'c');
+ assertEquals('peek, Should be "c"', h.peek(), 'c');
+ h.insert(1, 'b');
+ assertEquals('peek, Should be "b"', h.peek(), 'b');
+ h.insert(0, 'a');
+ assertEquals('peek, Should be "a"', h.peek(), 'a');
+}
+
+
+function testInsertPeek2() {
+ var h = new goog.structs.Heap();
+
+ h.insert(1, 'b');
+ assertEquals('peak, Should be "b"', h.peek(), 'b');
+ h.insert(3, 'd');
+ assertEquals('peak, Should be "b"', h.peek(), 'b');
+ h.insert(0, 'a');
+ assertEquals('peak, Should be "a"', h.peek(), 'a');
+ h.insert(2, 'c');
+ assertEquals('peak, Should be "a"', h.peek(), 'a');
+}
+
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/inversionmap.js b/contexts/data/lib/closure-library/closure/goog/structs/inversionmap.js
new file mode 100644
index 0000000..1c7c2e2
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/inversionmap.js
@@ -0,0 +1,159 @@
+// Copyright 2008 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Provides inversion and inversion map functionality for storing
+ * integer ranges and corresponding values.
+ *
+ */
+
+goog.provide('goog.structs.InversionMap');
+
+goog.require('goog.array');
+
+
+
+/**
+ * Maps ranges to values using goog.structs.Inversion.
+ * @param {Array.<number>} rangeArray An array of monotonically
+ * increasing integer values, with at least one instance.
+ * @param {Array.<*>} valueArray An array of corresponding values.
+ * Length must be the same as rangeArray.
+ * @param {boolean=} opt_delta If true, saves only delta from previous value.
+ * @constructor
+ */
+goog.structs.InversionMap = function(rangeArray, valueArray, opt_delta) {
+ if (rangeArray.length != valueArray.length) {
+ // rangeArray and valueArray has to match in number of entries.
+ return null;
+ }
+ this.storeInversion_(rangeArray, opt_delta);
+
+ /**
+ * @type {Array}
+ * @protected
+ */
+ this.values = valueArray;
+};
+
+
+/**
+ * @type {Array}
+ * @protected
+ */
+goog.structs.InversionMap.prototype.rangeArray;
+
+
+/**
+ * Stores the integers as ranges (half-open).
+ * If delta is true, the integers are delta from the previous value and
+ * will be restored to the absolute value.
+ * When used as a set, even indices are IN, and odd are OUT.
+ * @param {Array.<number?>} rangeArray An array of monotonically
+ * increasing integer values, with at least one instance.
+ * @param {boolean=} opt_delta If true, saves only delta from previous value.
+ * @private
+ */
+goog.structs.InversionMap.prototype.storeInversion_ = function(rangeArray,
+ opt_delta) {
+ this.rangeArray = rangeArray;
+
+ for (var i = 1; i < rangeArray.length; i++) {
+ if (rangeArray[i] == null) {
+ rangeArray[i] = rangeArray[i - 1] + 1;
+ } else if (opt_delta) {
+ rangeArray[i] += rangeArray[i - 1];
+ }
+ }
+};
+
+
+/**
+ * Splices a range -> value map into this inversion map.
+ * @param {Array.<number>} rangeArray An array of monotonically
+ * increasing integer values, with at least one instance.
+ * @param {Array.<*>} valueArray An array of corresponding values.
+ * Length must be the same as rangeArray.
+ * @param {boolean=} opt_delta If true, saves only delta from previous value.
+ */
+goog.structs.InversionMap.prototype.spliceInversion = function(
+ rangeArray, valueArray, opt_delta) {
+ // By building another inversion map, we build the arrays that we need
+ // to splice in.
+ var otherMap = new goog.structs.InversionMap(
+ rangeArray, valueArray, opt_delta);
+
+ // Figure out where to splice those arrays.
+ var startRange = otherMap.rangeArray[0];
+ var endRange =
+ (/** @type {number} */ goog.array.peek(otherMap.rangeArray));
+ var startSplice = this.getLeast(startRange);
+ var endSplice = this.getLeast(endRange);
+
+ // The inversion map works by storing the start points of ranges...
+ if (startRange != this.rangeArray[startSplice]) {
+ // ...if we're splicing in a start point that isn't already here,
+ // then we need to insert it after the insertion point.
+ startSplice++;
+ } // otherwise we overwrite the insertion point.
+
+ var spliceLength = endSplice - startSplice + 1;
+ goog.partial(goog.array.splice, this.rangeArray, startSplice,
+ spliceLength).apply(null, otherMap.rangeArray);
+ goog.partial(goog.array.splice, this.values, startSplice,
+ spliceLength).apply(null, otherMap.values);
+};
+
+
+/**
+ * Gets the value corresponding to a number from the inversion map.
+ * @param {number} intKey The number for which value needs to be retrieved
+ * from inversion map.
+ * @return {*} Value retrieved from inversion map; null if not found.
+ */
+goog.structs.InversionMap.prototype.at = function(intKey) {
+ var index = this.getLeast(intKey);
+ if (index < 0) {
+ return null;
+ }
+ return this.values[index];
+};
+
+
+/**
+ * Gets the largest index such that rangeArray[index] <= intKey from the
+ * inversion map.
+ * @param {number} intKey The probe for which rangeArray is searched.
+ * @return {number} Largest index such that rangeArray[index] <= intKey.
+ * @protected
+ */
+goog.structs.InversionMap.prototype.getLeast = function(intKey) {
+ var arr = this.rangeArray;
+ var low = 0;
+ var high = arr.length;
+ while (high - low > 8) {
+ var mid = (high + low) >> 1;
+ if (arr[mid] <= intKey) {
+ low = mid;
+ } else {
+ high = mid;
+ }
+ }
+ for (; low < high; ++low) {
+ if (intKey < arr[low]) {
+ break;
+ }
+ }
+ return low - 1;
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/inversionmap_test.html b/contexts/data/lib/closure-library/closure/goog/structs/inversionmap_test.html
new file mode 100644
index 0000000..d461edf
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/inversionmap_test.html
@@ -0,0 +1,157 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2008 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs.InversionMap</title>
+<script type="text/javascript" src="../base.js"></script>
+<script type="text/javascript">
+ goog.require('goog.structs.InversionMap');
+ goog.require('goog.testing.jsunit');
+</script>
+</head>
+<body>
+<script type="text/javascript">
+ function testInversionWithDelta() {
+ var alphabetNames = new goog.structs.InversionMap(
+ [ 0, 97, 1, 1, 1, 20, 1, 1, 1 ],
+ [ null,
+ 'LATIN SMALL LETTER A',
+ 'LATIN SMALL LETTER B',
+ 'LATIN SMALL LETTER C',
+ null,
+ 'LATIN SMALL LETTER X',
+ 'LATIN SMALL LETTER Y',
+ 'LATIN SMALL LETTER Z',
+ null ],
+ true);
+
+ assertEquals('LATIN SMALL LETTER A', alphabetNames.at(97));
+ assertEquals('LATIN SMALL LETTER Y', alphabetNames.at(121));
+ assertEquals(null, alphabetNames.at(140));
+ assertEquals(null, alphabetNames.at(0));
+ }
+
+ function testInversionWithoutDelta() {
+ var alphabetNames = new goog.structs.InversionMap(
+ [ 0, 97, 98, 99, 100, 120, 121, 122, 123 ],
+ [ null,
+ 'LATIN SMALL LETTER A',
+ 'LATIN SMALL LETTER B',
+ 'LATIN SMALL LETTER C',
+ null,
+ 'LATIN SMALL LETTER X',
+ 'LATIN SMALL LETTER Y',
+ 'LATIN SMALL LETTER Z',
+ null ],
+ false);
+
+ assertEquals('LATIN SMALL LETTER A', alphabetNames.at(97));
+ assertEquals('LATIN SMALL LETTER Y', alphabetNames.at(121));
+ assertEquals(null, alphabetNames.at(140));
+ assertEquals(null, alphabetNames.at(0));
+ }
+
+ function testInversionWithoutDeltaNoOpt() {
+ var alphabetNames = new goog.structs.InversionMap(
+ [ 0, 97, 98, 99, 100, 120, 121, 122, 123 ],
+ [ null,
+ 'LATIN SMALL LETTER A',
+ 'LATIN SMALL LETTER B',
+ 'LATIN SMALL LETTER C',
+ null,
+ 'LATIN SMALL LETTER X',
+ 'LATIN SMALL LETTER Y',
+ 'LATIN SMALL LETTER Z',
+ null ]);
+
+ assertEquals('LATIN SMALL LETTER A', alphabetNames.at(97));
+ assertEquals('LATIN SMALL LETTER Y', alphabetNames.at(121));
+ assertEquals(null, alphabetNames.at(140));
+ assertEquals(null, alphabetNames.at(0));
+ }
+
+ function testInversionMapSplice1() {
+ var alphabetNames = newAsciiMap();
+ alphabetNames.spliceInversion(
+ [ 99, 105, 114 ], [ 'XXX', 'YYY', 'ZZZ' ]);
+ assertEquals('LATIN SMALL LETTER B', alphabetNames.at(98));
+ assertEquals('XXX', alphabetNames.at(100));
+ assertEquals('ZZZ', alphabetNames.at(114));
+ assertEquals('ZZZ', alphabetNames.at(119));
+ assertEquals('LATIN SMALL LETTER X', alphabetNames.at(120));
+ }
+
+ function testInversionMapSplice2() {
+ var alphabetNames = newAsciiMap();
+ alphabetNames.spliceInversion(
+ [ 105, 114, 121 ], [ 'XXX', 'YYY', 'ZZZ' ]);
+ assertEquals(null, alphabetNames.at(104));
+ assertEquals('XXX', alphabetNames.at(105));
+ assertEquals('YYY', alphabetNames.at(120));
+ assertEquals('ZZZ', alphabetNames.at(121));
+ assertEquals('LATIN SMALL LETTER Z', alphabetNames.at(122));
+ }
+
+ function testInversionMapSplice3() {
+ var alphabetNames = newAsciiMap();
+ alphabetNames.spliceInversion(
+ [ 98, 99 ], [ 'CHANGED LETTER B', 'CHANGED LETTER C' ]);
+ assertEquals('LATIN SMALL LETTER A', alphabetNames.at(97));
+ assertEquals('CHANGED LETTER B', alphabetNames.at(98));
+ assertEquals('CHANGED LETTER C', alphabetNames.at(99));
+ assertEquals('LATIN SMALL LETTER D', alphabetNames.at(100));
+ assertEquals(null, alphabetNames.at(101));
+ }
+
+ function testInversionMapSplice4() {
+ var alphabetNames = newAsciiMap();
+ alphabetNames.spliceInversion(
+ [ 98, 1 ], [ 'CHANGED LETTER B', 'CHANGED LETTER C' ],
+ true /* delta mode */);
+ assertEquals('LATIN SMALL LETTER A', alphabetNames.at(97));
+ assertEquals('CHANGED LETTER B', alphabetNames.at(98));
+ assertEquals('CHANGED LETTER C', alphabetNames.at(99));
+ assertEquals('LATIN SMALL LETTER D', alphabetNames.at(100));
+ assertEquals(null, alphabetNames.at(101));
+ }
+
+ function testInversionMapSplice5() {
+ var map = new goog.structs.InversionMap(
+ [0, 97, 98, 99],
+ [null,
+ 'LATIN SMALL LETTER A',
+ 'LATIN SMALL LETTER B',
+ 'LATIN SMALL LETTER C']);
+ map.spliceInversion(
+ [98], ['CHANGED LETTER B']);
+ assertEquals('LATIN SMALL LETTER A', map.at(97));
+ assertEquals('CHANGED LETTER B', map.at(98));
+ assertEquals('LATIN SMALL LETTER C', map.at(99));
+
+ assertArrayEquals([0, 97, 98, 99], map.rangeArray);
+ }
+
+ function newAsciiMap() {
+ return new goog.structs.InversionMap(
+ [ 0, 97, 98, 99, 100, 101, 120, 121, 122, 123 ],
+ [ null,
+ 'LATIN SMALL LETTER A',
+ 'LATIN SMALL LETTER B',
+ 'LATIN SMALL LETTER C',
+ 'LATIN SMALL LETTER D',
+ null,
+ 'LATIN SMALL LETTER X',
+ 'LATIN SMALL LETTER Y',
+ 'LATIN SMALL LETTER Z',
+ null ]);
+ }
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/linkedmap.js b/contexts/data/lib/closure-library/closure/goog/structs/linkedmap.js
new file mode 100644
index 0000000..bfaf230
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/linkedmap.js
@@ -0,0 +1,472 @@
+// Copyright 2007 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview A LinkedMap data structure that is accessed using key/value
+ * pairs like an ordinary Map, but which guarantees a consistent iteration
+ * order over its entries. The iteration order is either insertion order (the
+ * default) or ordered from most recent to least recent use. By setting a fixed
+ * size, the LRU version of the LinkedMap makes an effective object cache. This
+ * data structure is similar to Java's LinkedHashMap.
+ *
+ */
+
+
+goog.provide('goog.structs.LinkedMap');
+
+goog.require('goog.structs.Map');
+
+
+
+/**
+ * Class for a LinkedMap datastructure, which combines O(1) map access for
+ * key/value pairs with a linked list for a consistent iteration order. Sample
+ * usage:
+ *
+ * <pre>
+ * var m = new LinkedMap();
+ * m.set('param1', 'A');
+ * m.set('param2', 'B');
+ * m.set('param3', 'C');
+ * alert(m.getKeys()); // param1, param2, param3
+ *
+ * var c = new LinkedMap(5, true);
+ * for (var i = 0; i < 10; i++) {
+ * c.set('entry' + i, false);
+ * }
+ * alert(c.getKeys()); // entry9, entry8, entry7, entry6, entry5
+ *
+ * c.set('entry5', true);
+ * c.set('entry1', false);
+ * alert(c.getKeys()); // entry1, entry5, entry9, entry8, entry7
+ * </pre>
+ *
+ * @param {number=} opt_maxCount The maximum number of objects to store in the
+ * LinkedMap. If unspecified or 0, there is no maximum.
+ * @param {boolean=} opt_cache When set, the LinkedMap stores items in order
+ * from most recently used to least recently used, instead of insertion
+ * order.
+ * @constructor
+ */
+goog.structs.LinkedMap = function(opt_maxCount, opt_cache) {
+ /**
+ * The maximum number of entries to allow, or null if there is no limit.
+ * @type {?number}
+ * @private
+ */
+ this.maxCount_ = opt_maxCount || null;
+
+ /**
+ * @type {boolean}
+ * @private
+ */
+ this.cache_ = !!opt_cache;
+
+ this.map_ = new goog.structs.Map();
+
+ this.head_ = new goog.structs.LinkedMap.Node_('', undefined);
+ this.head_.next = this.head_.prev = this.head_;
+};
+
+
+/**
+ * Finds a node and updates it to be the most recently used.
+ * @param {string} key The key of the node.
+ * @return {goog.structs.LinkedMap.Node_} The node or null if not found.
+ * @private
+ */
+goog.structs.LinkedMap.prototype.findAndMoveToTop_ = function(key) {
+ var node = /** @type {goog.structs.LinkedMap.Node_} */ (this.map_.get(key));
+ if (node) {
+ if (this.cache_) {
+ node.remove();
+ this.insert_(node);
+ }
+ }
+ return node;
+};
+
+
+/**
+ * Retrieves the value for a given key. If this is a caching LinkedMap, the
+ * entry will become the most recently used.
+ * @param {string} key The key to retrieve the value for.
+ * @param {*=} opt_val A default value that will be returned if the key is
+ * not found, defaults to undefined.
+ * @return {*} The retrieved value.
+ */
+goog.structs.LinkedMap.prototype.get = function(key, opt_val) {
+ var node = this.findAndMoveToTop_(key);
+ return node ? node.value : opt_val;
+};
+
+
+/**
+ * Retrieves the value for a given key without updating the entry to be the
+ * most recently used.
+ * @param {string} key The key to retrieve the value for.
+ * @param {*=} opt_val A default value that will be returned if the key is
+ * not found.
+ * @return {*} The retrieved value.
+ */
+goog.structs.LinkedMap.prototype.peekValue = function(key, opt_val) {
+ var node = this.map_.get(key);
+ return node ? node.value : opt_val;
+};
+
+
+/**
+ * Sets a value for a given key. If this is a caching LinkedMap, this entry
+ * will become the most recently used.
+ * @param {string} key The key to retrieve the value for.
+ * @param {*} value A default value that will be returned if the key is
+ * not found.
+ */
+goog.structs.LinkedMap.prototype.set = function(key, value) {
+ var node = this.findAndMoveToTop_(key);
+ if (node) {
+ node.value = value;
+ } else {
+ node = new goog.structs.LinkedMap.Node_(key, value);
+ this.map_.set(key, node);
+ this.insert_(node);
+ }
+};
+
+
+/**
+ * Returns the value of the first node without making any modifications.
+ * @return {*} The value of the first node or undefined if the map is empty.
+ */
+goog.structs.LinkedMap.prototype.peek = function() {
+ return this.head_.next.value;
+};
+
+
+/**
+ * Returns the value of the last node without making any modifications.
+ * @return {*} The value of the last node or undefined if the map is empty.
+ */
+goog.structs.LinkedMap.prototype.peekLast = function() {
+ return this.head_.prev.value;
+};
+
+
+/**
+ * Removes the first node from the list and returns its value.
+ * @return {*} The value of the popped node, or undefined if the map was empty.
+ */
+goog.structs.LinkedMap.prototype.shift = function() {
+ return this.popNode_(this.head_.next);
+};
+
+
+/**
+ * Removes the last node from the list and returns its value.
+ * @return {*} The value of the popped node, or undefined if the map was empty.
+ */
+goog.structs.LinkedMap.prototype.pop = function() {
+ return this.popNode_(this.head_.prev);
+};
+
+
+/**
+ * Removes a value from the LinkedMap based on its key.
+ * @param {string} key The key to remove.
+ * @return {boolean} True if the entry was removed, false if the key was not
+ * found.
+ */
+goog.structs.LinkedMap.prototype.remove = function(key) {
+ var node = /** @type {goog.structs.LinkedMap.Node_} */ (this.map_.get(key));
+ if (node) {
+ this.removeNode(node);
+ return true;
+ }
+ return false;
+};
+
+
+/**
+ * Removes a node from the {@code LinkedMap}. It can be overridden to do
+ * further cleanup such as disposing of the node value.
+ * @param {!goog.structs.LinkedMap.Node_} node The node to remove.
+ * @protected
+ */
+goog.structs.LinkedMap.prototype.removeNode = function(node) {
+ node.remove();
+ this.map_.remove(node.key);
+};
+
+
+/**
+ * @return {number} The number of items currently in the LinkedMap.
+ */
+goog.structs.LinkedMap.prototype.getCount = function() {
+ return this.map_.getCount();
+};
+
+
+/**
+ * @return {boolean} True if the cache is empty, false if it contains any items.
+ */
+goog.structs.LinkedMap.prototype.isEmpty = function() {
+ return this.map_.isEmpty();
+};
+
+
+/**
+ * Sets the maximum number of entries allowed in this object, truncating any
+ * excess objects if necessary.
+ * @param {number} maxCount The new maximum number of entries to allow.
+ */
+goog.structs.LinkedMap.prototype.setMaxCount = function(maxCount) {
+ this.maxCount_ = maxCount || null;
+ if (this.maxCount_ != null) {
+ this.truncate_(this.maxCount_);
+ }
+};
+
+
+/**
+ * @return {Array.<string>} The list of the keys in the appropriate order for
+ * this LinkedMap.
+ */
+goog.structs.LinkedMap.prototype.getKeys = function() {
+ return this.map(function(val, key) {
+ return key;
+ });
+};
+
+
+/**
+ * @return {!Array} The list of the values in the appropriate order for
+ * this LinkedMap.
+ */
+goog.structs.LinkedMap.prototype.getValues = function() {
+ return this.map(function(val, key) {
+ return val;
+ });
+};
+
+
+/**
+ * Tests whether a provided value is currently in the LinkedMap. This does not
+ * affect item ordering in cache-style LinkedMaps.
+ * @param {Object} value The value to check for.
+ * @return {boolean} Whether the value is in the LinkedMap.
+ */
+goog.structs.LinkedMap.prototype.contains = function(value) {
+ return this.some(function(el) {
+ return el == value;
+ });
+};
+
+
+/**
+ * Tests whether a provided key is currently in the LinkedMap. This does not
+ * affect item ordering in cache-style LinkedMaps.
+ * @param {string} key The key to check for.
+ * @return {boolean} Whether the key is in the LinkedMap.
+ */
+goog.structs.LinkedMap.prototype.containsKey = function(key) {
+ return this.map_.containsKey(key);
+};
+
+
+/**
+ * Removes all entries in this object.
+ */
+goog.structs.LinkedMap.prototype.clear = function() {
+ this.truncate_(0);
+};
+
+
+/**
+ * Calls a function on each item in the LinkedMap.
+ *
+ * @see goog.structs.forEach
+ * @param {Function} f The function to call for each item. The function takes
+ * three arguments: the value, the key, and the LinkedMap.
+ * @param {Object=} opt_obj The object context to use as "this" for the
+ * function.
+ */
+goog.structs.LinkedMap.prototype.forEach = function(f, opt_obj) {
+ for (var n = this.head_.next; n != this.head_; n = n.next) {
+ f.call(opt_obj, n.value, n.key, this);
+ }
+};
+
+
+/**
+ * Calls a function on each item in the LinkedMap and returns the results of
+ * those calls in an array.
+ *
+ * @see goog.structs.map
+ * @param {!Function} f The function to call for each item. The function takes
+ * three arguments: the value, the key, and the LinkedMap.
+ * @param {Object=} opt_obj The object context to use as "this" for the
+ * function.
+ * @return {!Array} The results of the function calls for each item in the
+ * LinkedMap.
+ */
+goog.structs.LinkedMap.prototype.map = function(f, opt_obj) {
+ var rv = [];
+ for (var n = this.head_.next; n != this.head_; n = n.next) {
+ rv.push(f.call(opt_obj, n.value, n.key, this));
+ }
+ return rv;
+};
+
+
+/**
+ * Calls a function on each item in the LinkedMap and returns true if any of
+ * those function calls returns a true-like value.
+ *
+ * @see goog.structs.some
+ * @param {Function} f The function to call for each item. The function takes
+ * three arguments: the value, the key, and the LinkedMap, and returns a
+ * boolean.
+ * @param {Object=} opt_obj The object context to use as "this" for the
+ * function.
+ * @return {boolean} Whether f evaluates to true for at least one item in the
+ * LinkedMap.
+ */
+goog.structs.LinkedMap.prototype.some = function(f, opt_obj) {
+ for (var n = this.head_.next; n != this.head_; n = n.next) {
+ if (f.call(opt_obj, n.value, n.key, this)) {
+ return true;
+ }
+ }
+ return false;
+};
+
+
+/**
+ * Calls a function on each item in the LinkedMap and returns true only if every
+ * function call returns a true-like value.
+ *
+ * @see goog.structs.some
+ * @param {Function} f The function to call for each item. The function takes
+ * three arguments: the value, the key, and the Cache, and returns a
+ * boolean.
+ * @param {Object=} opt_obj The object context to use as "this" for the
+ * function.
+ * @return {boolean} Whether f evaluates to true for every item in the Cache.
+ */
+goog.structs.LinkedMap.prototype.every = function(f, opt_obj) {
+ for (var n = this.head_.next; n != this.head_; n = n.next) {
+ if (!f.call(opt_obj, n.value, n.key, this)) {
+ return false;
+ }
+ }
+ return true;
+};
+
+
+/**
+ * Appends a node to the list. LinkedMap in cache mode adds new nodes to
+ * the head of the list, otherwise they are appended to the tail. If there is a
+ * maximum size, the list will be truncated if necessary.
+ *
+ * @param {goog.structs.LinkedMap.Node_} node The item to insert.
+ * @private
+ */
+goog.structs.LinkedMap.prototype.insert_ = function(node) {
+ if (this.cache_) {
+ node.next = this.head_.next;
+ node.prev = this.head_;
+
+ this.head_.next = node;
+ node.next.prev = node;
+ } else {
+ node.prev = this.head_.prev;
+ node.next = this.head_;
+
+ this.head_.prev = node;
+ node.prev.next = node;
+ }
+
+ if (this.maxCount_ != null) {
+ this.truncate_(this.maxCount_);
+ }
+};
+
+
+/**
+ * Removes elements from the LinkedMap if the given count has been exceeded.
+ * In cache mode removes nodes from the tail of the list. Otherwise removes
+ * nodes from the head.
+ * @param {number} count Number of elements to keep.
+ * @private
+ */
+goog.structs.LinkedMap.prototype.truncate_ = function(count) {
+ for (var i = this.map_.getCount(); i > count; i--) {
+ this.removeNode(this.cache_ ? this.head_.prev : this.head_.next);
+ }
+};
+
+
+/**
+ * Removes the node from the LinkedMap if it is not the head, and returns
+ * the node's value.
+ * @param {!goog.structs.LinkedMap.Node_} node The item to remove.
+ * @return {*} The value of the popped node.
+ * @private
+ */
+goog.structs.LinkedMap.prototype.popNode_ = function(node) {
+ if (this.head_ != node) {
+ this.removeNode(node);
+ }
+ return node.value;
+};
+
+
+
+/**
+ * Internal class for a doubly-linked list node containing a key/value pair.
+ * @param {string} key The key.
+ * @param {*} value The value.
+ * @constructor
+ * @private
+ */
+goog.structs.LinkedMap.Node_ = function(key, value) {
+ this.key = key;
+ this.value = value;
+};
+
+
+/**
+ * The next node in the list.
+ * @type {!goog.structs.LinkedMap.Node_}
+ */
+goog.structs.LinkedMap.Node_.prototype.next;
+
+
+/**
+ * The previous node in the list.
+ * @type {!goog.structs.LinkedMap.Node_}
+ */
+goog.structs.LinkedMap.Node_.prototype.prev;
+
+
+/**
+ * Causes this node to remove itself from the list.
+ */
+goog.structs.LinkedMap.Node_.prototype.remove = function() {
+ this.prev.next = this.next;
+ this.next.prev = this.prev;
+
+ delete this.prev;
+ delete this.next;
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/linkedmap_test.html b/contexts/data/lib/closure-library/closure/goog/structs/linkedmap_test.html
new file mode 100644
index 0000000..d20faac
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/linkedmap_test.html
@@ -0,0 +1,300 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2006 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs.LinkedMap</title>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.structs.LinkedMap');
+ goog.require('goog.testing.jsunit');
+ goog.require('goog.testing.recordFunction');
+</script>
+</head>
+<body>
+<script>
+
+function fillLinkedMap(m) {
+ m.set('a', 0);
+ m.set('b', 1);
+ m.set('c', 2);
+ m.set('d', 3);
+}
+
+var someObj = {};
+
+function testLinkedMap() {
+ var m = new goog.structs.LinkedMap();
+ fillLinkedMap(m);
+
+ assertArrayEquals(['a', 'b', 'c', 'd'], m.getKeys());
+ assertArrayEquals([0, 1, 2, 3], m.getValues());
+}
+
+function testMaxSizeLinkedMap() {
+ var m = new goog.structs.LinkedMap(3);
+ fillLinkedMap(m);
+
+ assertArrayEquals(['b', 'c', 'd'], m.getKeys());
+ assertArrayEquals([1, 2, 3], m.getValues());
+}
+
+function testLruLinkedMap() {
+ var m = new goog.structs.LinkedMap(undefined, true);
+ fillLinkedMap(m);
+
+ assertArrayEquals(['d', 'c', 'b', 'a'], m.getKeys());
+ assertArrayEquals([3, 2, 1, 0], m.getValues());
+
+ m.get('a');
+ assertArrayEquals(['a', 'd', 'c', 'b'], m.getKeys());
+ assertArrayEquals([0, 3, 2, 1], m.getValues());
+
+ m.set('b', 4);
+ assertArrayEquals(['b', 'a', 'd', 'c'], m.getKeys());
+ assertArrayEquals([4, 0, 3, 2], m.getValues());
+}
+
+function testMaxSizeLruLinkedMap() {
+ var m = new goog.structs.LinkedMap(3, true);
+ fillLinkedMap(m);
+
+ assertArrayEquals(['d', 'c', 'b'], m.getKeys());
+ assertArrayEquals([3, 2, 1], m.getValues());
+
+ m.get('c');
+ assertArrayEquals(['c', 'd', 'b'], m.getKeys());
+ assertArrayEquals([2, 3, 1], m.getValues());
+
+ m.set('d', 4);
+ assertArrayEquals(['d', 'c', 'b'], m.getKeys());
+ assertArrayEquals([4, 2, 1], m.getValues());
+}
+
+function testGetCount() {
+ var m = new goog.structs.LinkedMap();
+ assertEquals(0, m.getCount());
+ m.set('a', 0);
+ assertEquals(1, m.getCount());
+ m.set('a', 1);
+ assertEquals(1, m.getCount());
+ m.set('b', 2);
+ assertEquals(2, m.getCount());
+ m.remove('a');
+ assertEquals(1, m.getCount());
+}
+
+function testIsEmpty() {
+ var m = new goog.structs.LinkedMap();
+ assertTrue(m.isEmpty());
+ m.set('a', 0);
+ assertFalse(m.isEmpty());
+ m.remove('a');
+ assertTrue(m.isEmpty());
+}
+
+function testSetMaxCount() {
+ var m = new goog.structs.LinkedMap(3);
+ fillLinkedMap(m);
+ assertEquals(3, m.getCount());
+
+ m.setMaxCount(5);
+ m.set('e', 5);
+ m.set('f', 6);
+ m.set('g', 7);
+ assertEquals(5, m.getCount());
+
+ m.setMaxCount(4);
+ assertEquals(4, m.getCount());
+
+ m.setMaxCount(0);
+ m.set('h', 8);
+ m.set('i', 9);
+ m.set('j', 10);
+ assertEquals(7, m.getCount());
+}
+
+function testClear() {
+ var m = new goog.structs.LinkedMap();
+ fillLinkedMap(m);
+ m.clear();
+ assertTrue(m.isEmpty());
+}
+
+function testForEach() {
+ var m = new goog.structs.LinkedMap();
+ fillLinkedMap(m);
+
+ m.forEach(function(val, key, linkedMap) {
+ linkedMap.set(key, val * 2);
+ assertEquals('forEach should run in provided context.', someObj, this);
+ }, someObj);
+
+ assertArrayEquals(['a', 'b', 'c', 'd'], m.getKeys());
+ assertArrayEquals([0, 2, 4, 6], m.getValues());
+}
+
+function testMap() {
+ var m = new goog.structs.LinkedMap();
+ fillLinkedMap(m);
+
+ var result = m.map(function(val, key, linkedMap) {
+ assertEquals('The LinkedMap object should get passed in', m, linkedMap);
+ assertEquals('map should run in provided context', someObj, this);
+ return key + val;
+ }, someObj);
+
+ assertArrayEquals(['a0', 'b1', 'c2', 'd3'], result);
+}
+
+function testSome() {
+ var m = new goog.structs.LinkedMap();
+ fillLinkedMap(m);
+
+ var result = m.some(function(val, key, linkedMap) {
+ assertEquals('The LinkedMap object should get passed in', m, linkedMap);
+ assertEquals('map should run in provided context', someObj, this);
+ return val > 2;
+ }, someObj);
+
+ assertTrue(result);
+ assertFalse(m.some(function(val) {return val > 3}));
+
+ assertTrue(m.some(function(val, key) {return key == 'c';}));
+ assertFalse(m.some(function(val, key) {return key == 'e';}));
+}
+
+function testEvery() {
+ var m = new goog.structs.LinkedMap();
+ fillLinkedMap(m);
+
+ var result = m.every(function(val, key, linkedMap) {
+ assertEquals('The LinkedMap object should get passed in', m, linkedMap);
+ assertEquals('map should run in provided context', someObj, this);
+ return val < 5;
+ }, someObj);
+
+ assertTrue(result);
+ assertFalse(m.every(function(val) {return val < 2}));
+
+ assertTrue(m.every(function(val, key) {return key.length == 1;}));
+ assertFalse(m.every(function(val, key) {return key == 'b';}));
+}
+
+function testPeek() {
+ var m = new goog.structs.LinkedMap();
+ assertEquals(undefined, m.peek());
+ assertEquals(undefined, m.peekLast());
+
+ fillLinkedMap(m);
+ assertEquals(0, m.peek());
+
+ m.remove('a');
+ assertEquals(1, m.peek());
+
+ assertEquals(3, m.peekLast());
+
+ assertEquals(3, m.peekValue('d'));
+ assertEquals(1, m.peek());
+
+ m.remove('d');
+ assertEquals(2, m.peekLast());
+}
+
+function testPop() {
+ var m = new goog.structs.LinkedMap();
+ assertEquals(undefined, m.shift());
+ assertEquals(undefined, m.pop());
+
+ fillLinkedMap(m);
+ assertEquals(4, m.getCount());
+
+ assertEquals(0, m.shift());
+ assertEquals(1, m.peek());
+
+ assertEquals(3, m.pop());
+ assertEquals(2, m.peekLast());
+
+ assertEquals(2, m.getCount());
+}
+
+function testContains() {
+ var m = new goog.structs.LinkedMap();
+ fillLinkedMap(m);
+
+ assertTrue(m.contains(2));
+ assertFalse(m.contains(4));
+}
+
+function testContainsKey() {
+ var m = new goog.structs.LinkedMap();
+ fillLinkedMap(m);
+
+ assertTrue(m.containsKey('b'));
+ assertFalse(m.containsKey('elephant'));
+ assertFalse(m.containsKey('undefined'));
+}
+
+function testRemoveNodeCalls() {
+ var m = new goog.structs.LinkedMap(1);
+ m.removeNode = goog.testing.recordFunction(m.removeNode);
+
+ m.set('1', 1);
+ assertEquals('removeNode not called after adding an element', 0,
+ m.removeNode.getCallCount());
+ m.set('1', 2);
+ assertEquals('removeNode not called after updating an element', 0,
+ m.removeNode.getCallCount());
+ m.set('2', 2);
+ assertEquals('removeNode called after adding an overflowing element', 1,
+ m.removeNode.getCallCount());
+
+ m.remove('3');
+ assertEquals('removeNode not called after removing a non-existing element', 1,
+ m.removeNode.getCallCount());
+ m.remove('2');
+ assertEquals('removeNode called after removing an existing element', 2,
+ m.removeNode.getCallCount());
+
+ m.set('1', 1);
+ m.clear();
+ assertEquals('removeNode called after clearing the map', 3,
+ m.removeNode.getCallCount());
+ m.clear();
+ assertEquals('removeNode not called after clearing an empty map', 3,
+ m.removeNode.getCallCount());
+
+ m.set('1', 1);
+ m.pop();
+ assertEquals('removeNode called after calling pop', 4,
+ m.removeNode.getCallCount());
+ m.pop();
+ assertEquals('removeNode not called after calling pop on an empty map', 4,
+ m.removeNode.getCallCount());
+
+ m.set('1', 1);
+ m.shift();
+ assertEquals('removeNode called after calling shift', 5,
+ m.removeNode.getCallCount());
+ m.shift();
+ assertEquals('removeNode not called after calling shift on an empty map', 5,
+ m.removeNode.getCallCount());
+
+ m.setMaxCount(2);
+ m.set('1', 1);
+ m.set('2', 2);
+ assertEquals('removeNode not called after increasing the maximum map size', 5,
+ m.removeNode.getCallCount());
+ m.setMaxCount(1);
+ assertEquals('removeNode called after decreasing the maximum map size', 6,
+ m.removeNode.getCallCount());
+}
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/map.js b/contexts/data/lib/closure-library/closure/goog/structs/map.js
new file mode 100644
index 0000000..f48d81b
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/map.js
@@ -0,0 +1,448 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Datastructure: Hash Map.
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ * @author jonp@google.com (Jon Perlow) Optimized for IE6
+ *
+ * This file contains an implementation of a Map structure. It implements a lot
+ * of the methods used in goog.structs so those functions work on hashes. For
+ * convenience with common usage the methods accept any type for the key, though
+ * internally they will be cast to strings.
+ */
+
+
+goog.provide('goog.structs.Map');
+
+goog.require('goog.iter.Iterator');
+goog.require('goog.iter.StopIteration');
+goog.require('goog.object');
+goog.require('goog.structs');
+
+
+
+/**
+ * Class for Hash Map datastructure.
+ * @param {*=} opt_map Map or Object to initialize the map with.
+ * @param {...*} var_args If 2 or more arguments are present then they
+ * will be used as key-value pairs.
+ * @constructor
+ */
+goog.structs.Map = function(opt_map, var_args) {
+
+ /**
+ * Underlying JS object used to implement the map.
+ * @type {!Object}
+ * @private
+ */
+ this.map_ = {};
+
+ /**
+ * An array of keys. This is necessary for two reasons:
+ * 1. Iterating the keys using for (var key in this.map_) allocates an
+ * object for every key in IE which is really bad for IE6 GC perf.
+ * 2. Without a side data structure, we would need to escape all the keys
+ * as that would be the only way we could tell during iteration if the
+ * key was an internal key or a property of the object.
+ *
+ * This array can contain deleted keys so it's necessary to check the map
+ * as well to see if the key is still in the map (this doesn't require a
+ * memory allocation in IE).
+ * @type {!Array.<string>}
+ * @private
+ */
+ this.keys_ = [];
+
+ var argLength = arguments.length;
+
+ if (argLength > 1) {
+ if (argLength % 2) {
+ throw Error('Uneven number of arguments');
+ }
+ for (var i = 0; i < argLength; i += 2) {
+ this.set(arguments[i], arguments[i + 1]);
+ }
+ } else if (opt_map) {
+ this.addAll(/** @type {Object} */ (opt_map));
+ }
+};
+
+
+/**
+ * The number of key value pairs in the map.
+ * @private
+ * @type {number}
+ */
+goog.structs.Map.prototype.count_ = 0;
+
+
+/**
+ * Version used to detect changes while iterating.
+ * @private
+ * @type {number}
+ */
+goog.structs.Map.prototype.version_ = 0;
+
+
+/**
+ * @return {number} The number of key-value pairs in the map.
+ */
+goog.structs.Map.prototype.getCount = function() {
+ return this.count_;
+};
+
+
+/**
+ * Returns the values of the map.
+ * @return {!Array} The values in the map.
+ */
+goog.structs.Map.prototype.getValues = function() {
+ this.cleanupKeysArray_();
+
+ var rv = [];
+ for (var i = 0; i < this.keys_.length; i++) {
+ var key = this.keys_[i];
+ rv.push(this.map_[key]);
+ }
+ return rv;
+};
+
+
+/**
+ * Returns the keys of the map.
+ * @return {!Array.<string>} Array of string values.
+ */
+goog.structs.Map.prototype.getKeys = function() {
+ this.cleanupKeysArray_();
+ return /** @type {!Array.<string>} */ (this.keys_.concat());
+};
+
+
+/**
+ * Whether the map contains the given key.
+ * @param {*} key The key to check for.
+ * @return {boolean} Whether the map contains the key.
+ */
+goog.structs.Map.prototype.containsKey = function(key) {
+ return goog.structs.Map.hasKey_(this.map_, key);
+};
+
+
+/**
+ * Whether the map contains the given value. This is O(n).
+ * @param {*} val The value to check for.
+ * @return {boolean} Whether the map contains the value.
+ */
+goog.structs.Map.prototype.containsValue = function(val) {
+ for (var i = 0; i < this.keys_.length; i++) {
+ var key = this.keys_[i];
+ if (goog.structs.Map.hasKey_(this.map_, key) && this.map_[key] == val) {
+ return true;
+ }
+ }
+ return false;
+};
+
+
+/**
+ * Whether this map is equal to the argument map.
+ * @param {goog.structs.Map} otherMap The map against which to test equality.
+ * @param {function(*, *) : boolean=} opt_equalityFn Optional equality function
+ * to test equality of values. If not specified, this will test whether
+ * the values contained in each map are identical objects.
+ * @return {boolean} Whether the maps are equal.
+ */
+goog.structs.Map.prototype.equals = function(otherMap, opt_equalityFn) {
+ if (this === otherMap) {
+ return true;
+ }
+
+ if (this.count_ != otherMap.getCount()) {
+ return false;
+ }
+
+ var equalityFn = opt_equalityFn || goog.structs.Map.defaultEquals;
+
+ this.cleanupKeysArray_();
+ for (var key, i = 0; key = this.keys_[i]; i++) {
+ if (!equalityFn(this.get(key), otherMap.get(key))) {
+ return false;
+ }
+ }
+
+ return true;
+};
+
+
+/**
+ * Default equality test for values.
+ * @param {*} a The first value.
+ * @param {*} b The second value.
+ * @return {boolean} Whether a and b reference the same object.
+ */
+goog.structs.Map.defaultEquals = function(a, b) {
+ return a === b;
+};
+
+
+/**
+ * @return {boolean} Whether the map is empty.
+ */
+goog.structs.Map.prototype.isEmpty = function() {
+ return this.count_ == 0;
+};
+
+
+/**
+ * Removes all key-value pairs from the map.
+ */
+goog.structs.Map.prototype.clear = function() {
+ this.map_ = {};
+ this.keys_.length = 0;
+ this.count_ = 0;
+ this.version_ = 0;
+};
+
+
+/**
+ * Removes a key-value pair based on the key. This is O(logN) amortized due to
+ * updating the keys array whenever the count becomes half the size of the keys
+ * in the keys array.
+ * @param {*} key The key to remove.
+ * @return {boolean} Whether object was removed.
+ */
+goog.structs.Map.prototype.remove = function(key) {
+ if (goog.structs.Map.hasKey_(this.map_, key)) {
+ delete this.map_[key];
+ this.count_--;
+ this.version_++;
+
+ // clean up the keys array if the threshhold is hit
+ if (this.keys_.length > 2 * this.count_) {
+ this.cleanupKeysArray_();
+ }
+
+ return true;
+ }
+ return false;
+};
+
+
+/**
+ * Cleans up the temp keys array by removing entries that are no longer in the
+ * map.
+ * @private
+ */
+goog.structs.Map.prototype.cleanupKeysArray_ = function() {
+ if (this.count_ != this.keys_.length) {
+ // First remove keys that are no longer in the map.
+ var srcIndex = 0;
+ var destIndex = 0;
+ while (srcIndex < this.keys_.length) {
+ var key = this.keys_[srcIndex];
+ if (goog.structs.Map.hasKey_(this.map_, key)) {
+ this.keys_[destIndex++] = key;
+ }
+ srcIndex++;
+ }
+ this.keys_.length = destIndex;
+ }
+
+ if (this.count_ != this.keys_.length) {
+ // If the count still isn't correct, that means we have duplicates. This can
+ // happen when the same key is added and removed multiple times. Now we have
+ // to allocate one extra Object to remove the duplicates. This could have
+ // been done in the first pass, but in the common case, we can avoid
+ // allocating an extra object by only doing this when necessary.
+ var seen = {};
+ var srcIndex = 0;
+ var destIndex = 0;
+ while (srcIndex < this.keys_.length) {
+ var key = this.keys_[srcIndex];
+ if (!(goog.structs.Map.hasKey_(seen, key))) {
+ this.keys_[destIndex++] = key;
+ seen[key] = 1;
+ }
+ srcIndex++;
+ }
+ this.keys_.length = destIndex;
+ }
+};
+
+
+/**
+ * Returns the value for the given key. If the key is not found and the default
+ * value is not given this will return {@code undefined}.
+ * @param {*} key The key to get the value for.
+ * @param {*=} opt_val The value to return if no item is found for the given
+ * key, defaults to undefined.
+ * @return {*} The value for the given key.
+ */
+goog.structs.Map.prototype.get = function(key, opt_val) {
+ if (goog.structs.Map.hasKey_(this.map_, key)) {
+ return this.map_[key];
+ }
+ return opt_val;
+};
+
+
+/**
+ * Adds a key-value pair to the map.
+ * @param {*} key The key.
+ * @param {*} value The value to add.
+ */
+goog.structs.Map.prototype.set = function(key, value) {
+ if (!(goog.structs.Map.hasKey_(this.map_, key))) {
+ this.count_++;
+ this.keys_.push(key);
+ // Only change the version if we add a new key.
+ this.version_++;
+ }
+ this.map_[key] = value;
+};
+
+
+/**
+ * Adds multiple key-value pairs from another goog.structs.Map or Object.
+ * @param {Object} map Object containing the data to add.
+ */
+goog.structs.Map.prototype.addAll = function(map) {
+ var keys, values;
+ if (map instanceof goog.structs.Map) {
+ keys = map.getKeys();
+ values = map.getValues();
+ } else {
+ keys = goog.object.getKeys(map);
+ values = goog.object.getValues(map);
+ }
+ // we could use goog.array.forEach here but I don't want to introduce that
+ // dependency just for this.
+ for (var i = 0; i < keys.length; i++) {
+ this.set(keys[i], values[i]);
+ }
+};
+
+
+/**
+ * Clones a map and returns a new map.
+ * @return {!goog.structs.Map} A new map with the same key-value pairs.
+ */
+goog.structs.Map.prototype.clone = function() {
+ return new goog.structs.Map(this);
+};
+
+
+/**
+ * Returns a new map in which all the keys and values are interchanged
+ * (keys become values and values become keys). If multiple keys map to the
+ * same value, the chosen transposed value is implementation-dependent.
+ *
+ * It acts very similarly to {goog.object.transpose(Object)}.
+ *
+ * @return {!goog.structs.Map} The transposed map.
+ */
+goog.structs.Map.prototype.transpose = function() {
+ var transposed = new goog.structs.Map();
+ for (var i = 0; i < this.keys_.length; i++) {
+ var key = this.keys_[i];
+ var value = this.map_[key];
+ transposed.set(value, key);
+ }
+
+ return transposed;
+};
+
+
+/**
+ * @return {!Object} Object representation of the map.
+ */
+goog.structs.Map.prototype.toObject = function() {
+ this.cleanupKeysArray_();
+ var obj = {};
+ for (var i = 0; i < this.keys_.length; i++) {
+ var key = this.keys_[i];
+ obj[key] = this.map_[key];
+ }
+ return obj;
+};
+
+
+/**
+ * Returns an iterator that iterates over the keys in the map. Removal of keys
+ * while iterating might have undesired side effects.
+ * @return {!goog.iter.Iterator} An iterator over the keys in the map.
+ */
+goog.structs.Map.prototype.getKeyIterator = function() {
+ return this.__iterator__(true);
+};
+
+
+/**
+ * Returns an iterator that iterates over the values in the map. Removal of
+ * keys while iterating might have undesired side effects.
+ * @return {!goog.iter.Iterator} An iterator over the values in the map.
+ */
+goog.structs.Map.prototype.getValueIterator = function() {
+ return this.__iterator__(false);
+};
+
+
+/**
+ * Returns an iterator that iterates over the values or the keys in the map.
+ * This throws an exception if the map was mutated since the iterator was
+ * created.
+ * @param {boolean=} opt_keys True to iterate over the keys. False to iterate
+ * over the values. The default value is false.
+ * @return {!goog.iter.Iterator} An iterator over the values or keys in the map.
+ */
+goog.structs.Map.prototype.__iterator__ = function(opt_keys) {
+ // Clean up keys to minimize the risk of iterating over dead keys.
+ this.cleanupKeysArray_();
+
+ var i = 0;
+ var keys = this.keys_;
+ var map = this.map_;
+ var version = this.version_;
+ var selfObj = this;
+
+ var newIter = new goog.iter.Iterator;
+ newIter.next = function() {
+ while (true) {
+ if (version != selfObj.version_) {
+ throw Error('The map has changed since the iterator was created');
+ }
+ if (i >= keys.length) {
+ throw goog.iter.StopIteration;
+ }
+ var key = keys[i++];
+ return opt_keys ? key : map[key];
+ }
+ };
+ return newIter;
+};
+
+
+/**
+ * Safe way to test for hasOwnProperty. It even allows testing for
+ * 'hasOwnProperty'.
+ * @param {Object} obj The object to test for presence of the given key.
+ * @param {*} key The key to check for.
+ * @return {boolean} Whether the object has the key.
+ * @private
+ */
+goog.structs.Map.hasKey_ = function(obj, key) {
+ return Object.prototype.hasOwnProperty.call(obj, key);
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/map_test.html b/contexts/data/lib/closure-library/closure/goog/structs/map_test.html
new file mode 100644
index 0000000..a526a59
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/map_test.html
@@ -0,0 +1,430 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2006 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs.Map</title>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.iter');
+ goog.require('goog.structs');
+ goog.require('goog.structs.Map');
+ goog.require('goog.testing.jsunit');
+</script>
+</head>
+<body>
+<script>
+
+function stringifyMap(m) {
+ var keys = goog.structs.getKeys(m);
+ var s = '';
+ for (var i = 0; i < keys.length; i++) {
+ s += keys[i] + m[keys[i]];
+ }
+ return s;
+}
+
+function getMap() {
+ var m = new goog.structs.Map;
+ m.set('a', 0);
+ m.set('b', 1);
+ m.set('c', 2);
+ m.set('d', 3);
+ return m;
+}
+
+function testGetCount() {
+ var m = getMap();
+ assertEquals('count, should be 4', m.getCount(), 4);
+ m.remove('d');
+ assertEquals('count, should be 3', m.getCount(), 3);
+}
+
+function testKeys() {
+ var m = getMap();
+ assertEquals('getKeys, The keys should be a,b,c', m.getKeys().join(','),
+ 'a,b,c,d');
+}
+
+function testValues() {
+ var m = getMap();
+ assertEquals('getValues, The values should be 0,1,2',
+ m.getValues().join(','), '0,1,2,3');
+}
+
+function testContainsKey() {
+ var m = getMap();
+ assertTrue("containsKey, Should contain the 'a' key", m.containsKey('a'));
+ assertFalse("containsKey, Should not contain the 'e' key",
+ m.containsKey('e'));
+}
+
+function testClear() {
+ var m = getMap();
+ m.clear();
+ assertTrue('cleared so it should be empty', m.isEmpty());
+ assertTrue("cleared so it should not contain 'a' key", !m.containsKey('a'));
+}
+
+function testAddAll() {
+ var m = new goog.structs.Map;
+ m.addAll({a:0,b:1,c:2,d:3});
+ assertTrue('addAll so it should not be empty', !m.isEmpty());
+ assertTrue("addAll so it should contain 'c' key", m.containsKey('c'));
+
+ var m2 = new goog.structs.Map;
+ m2.addAll(m);
+ assertTrue('addAll so it should not be empty', !m2.isEmpty());
+ assertTrue("addAll so it should contain 'c' key", m2.containsKey('c'));
+}
+
+function testConstructor() {
+ var m = getMap();
+ var m2 = new goog.structs.Map(m);
+ assertTrue('constr with Map so it should not be empty', !m2.isEmpty());
+ assertTrue("constr with Map so it should contain 'c' key",
+ m2.containsKey('c'));
+}
+
+
+function testConstructorWithVarArgs() {
+ var m = new goog.structs.Map('a', 1);
+ assertTrue('constr with var_args so it should not be empty', !m.isEmpty());
+ assertEquals('constr with var_args', 1, m.get('a'));
+
+ m = new goog.structs.Map('a', 1, 'b', 2);
+ assertTrue('constr with var_args so it should not be empty', !m.isEmpty());
+ assertEquals('constr with var_args', 1, m.get('a'));
+ assertEquals('constr with var_args', 2, m.get('b'));
+
+ assertThrows('Odd number of arguments is not allowed', function() {
+ var m = new goog.structs.Map('a', 1, 'b');
+ });
+}
+
+function testClone() {
+ var m = getMap();
+ var m2 = m.clone();
+ assertTrue('clone so it should not be empty', !m2.isEmpty());
+ assertTrue("clone so it should contain 'c' key", m2.containsKey('c'));
+}
+
+
+function testRemove() {
+ var m = new goog.structs.Map();
+ for (var i = 0; i < 1000; i++) {
+ m.set(i, 'foo');
+ }
+
+ for (var i = 0; i < 1000; i++) {
+ assertTrue(m.keys_.length <= 2 * m.getCount());
+ m.remove(i);
+ }
+ assertTrue(m.isEmpty());
+ assertEquals('', m.getKeys().join(''));
+}
+
+
+function testForEach() {
+ var m = getMap();
+ var s = '';
+ goog.structs.forEach(m, function(val, key, m2) {
+ assertNotUndefined(key);
+ assertEquals(m, m2);
+ s += key + val;
+ });
+ assertEquals(s, 'a0b1c2d3');
+}
+
+function testFilter() {
+ var m = getMap();
+
+ var m2 = goog.structs.filter(m, function (val, key, m3) {
+ assertNotUndefined(key);
+ assertEquals(m, m3);
+ return val > 1;
+ });
+ assertEquals(stringifyMap(m2), 'c2d3');
+}
+
+
+function testMap() {
+ var m = getMap();
+ var m2 = goog.structs.map(m, function (val, key, m3) {
+ assertNotUndefined(key);
+ assertEquals(m, m3);
+ return val * val;
+ });
+ assertEquals(stringifyMap(m2), 'a0b1c4d9');
+}
+
+function testSome() {
+ var m = getMap();
+ var b = goog.structs.some(m, function (val, key, m2) {
+ assertNotUndefined(key);
+ assertEquals(m, m2);
+ return val > 1;
+ });
+ assertTrue(b);
+ var b = goog.structs.some(m, function (val, key, m2) {
+ assertNotUndefined(key);
+ assertEquals(m, m2);
+ return val > 100;
+ });
+ assertFalse(b);
+}
+
+function testEvery() {
+ var m = getMap();
+ var b = goog.structs.every(m, function (val, key, m2) {
+ assertNotUndefined(key);
+ assertEquals(m, m2);
+ return val >= 0;
+ });
+ assertTrue(b);
+ b = goog.structs.every(m, function (val, key, m2) {
+ assertNotUndefined(key);
+ assertEquals(m, m2);
+ return val > 1;
+ });
+ assertFalse(b);
+}
+
+function testContainsValue() {
+ var m = getMap();
+ assertTrue(m.containsValue(3));
+ assertFalse(m.containsValue(4));
+}
+
+function testObjectProperties() {
+ var m = new goog.structs.Map;
+
+ assertEquals(m.get('toString'), undefined);
+ assertEquals(m.get('valueOf'), undefined);
+ assertEquals(m.get('eval'), undefined);
+ assertEquals(m.get('toSource'), undefined);
+ assertEquals(m.get('prototype'), undefined);
+ assertEquals(m.get(':foo'), undefined);
+
+ m.set('toString', 'once');
+ m.set('valueOf', 'upon');
+ m.set('eval', 'a');
+ m.set('toSource', 'midnight');
+ m.set('prototype', 'dreary');
+ m.set('hasOwnProperty', 'dark');
+ m.set(':foo', 'happy');
+
+ assertEquals(m.get('toString'), 'once');
+ assertEquals(m.get('valueOf'), 'upon');
+ assertEquals(m.get('eval'), 'a');
+ assertEquals(m.get('toSource'), 'midnight');
+ assertEquals(m.get('prototype'), 'dreary');
+ assertEquals(m.get('hasOwnProperty'), 'dark');
+ assertEquals(m.get(':foo'), 'happy');
+
+ var keys = m.getKeys().join(',');
+ assertEquals(keys,
+ 'toString,valueOf,eval,toSource,prototype,hasOwnProperty,:foo');
+
+ var values = m.getValues().join(',');
+ assertEquals(values, 'once,upon,a,midnight,dreary,dark,happy');
+}
+
+function testDuplicateKeys() {
+ var m = new goog.structs.Map;
+
+ m.set('a', 1);
+ m.set('b', 2);
+ m.set('c', 3);
+ m.set('d', 4);
+ m.set('e', 5);
+ m.set('f', 6);
+ assertEquals(6, m.getKeys().length);
+ m.set('foo', 1);
+ assertEquals(7, m.getKeys().length);
+ m.remove('foo');
+ assertEquals(6, m.getKeys().length);
+ m.set('foo', 2);
+ assertEquals(7, m.getKeys().length);
+ m.remove('foo');
+ m.set('foo', 3);
+ m.remove('foo');
+ m.set('foo', 4);
+ assertEquals(7, m.getKeys().length);
+}
+
+function testGetKeyIterator() {
+ var m = new goog.structs.Map;
+ m.set('a', 1);
+ m.set('b', 2);
+ m.set('c', 3);
+ m.set('d', 4);
+ m.set('e', 5);
+
+ var iter = m.getKeyIterator();
+ assertEquals('Should contain the keys', 'abcde', goog.iter.join(iter, ''));
+
+ m.remove('b');
+ m.remove('d');
+ iter = m.getKeyIterator();
+ assertEquals('Should not contain the removed keys',
+ 'ace', goog.iter.join(iter, ''));
+}
+
+function testGetValueIterator() {
+ var m = new goog.structs.Map;
+ m.set('a', 1);
+ m.set('b', 2);
+ m.set('c', 3);
+ m.set('d', 4);
+ m.set('e', 5);
+
+ var iter = m.getValueIterator();
+ assertEquals('Should contain the values', '12345', goog.iter.join(iter, ''));
+
+ m.remove('b');
+ m.remove('d');
+ iter = m.getValueIterator();
+ assertEquals('Should not contain the removed keys',
+ '135', goog.iter.join(iter, ''));
+}
+
+function testDefaultIterator() {
+ // The default iterator should behave like the value iterator
+
+ var m = new goog.structs.Map;
+ m.set('a', 1);
+ m.set('b', 2);
+ m.set('c', 3);
+ m.set('d', 4);
+ m.set('e', 5);
+
+ assertEquals('Should contain the values', '12345', goog.iter.join(m, ''));
+
+ m.remove('b');
+ m.remove('d');
+ assertEquals('Should not contain the removed keys',
+ '135', goog.iter.join(m, ''));
+}
+
+function testMutatedIterator() {
+ var message = 'The map has changed since the iterator was created';
+
+ var m = new goog.structs.Map;
+ m.set('a', 1);
+ m.set('b', 2);
+ m.set('c', 3);
+ m.set('d', 4);
+
+ var iter = m.getValueIterator();
+ m.set('e', 5);
+ var ex = assertThrows('Expected an exception since the map has changed',
+ function() {
+ iter.next();
+ });
+ assertEquals(message, ex.message);
+
+ m = new goog.structs.Map;
+ m.set('a', 1);
+ m.set('b', 2);
+ m.set('c', 3);
+ m.set('d', 4);
+
+ iter = m.getValueIterator();
+ m.remove('d');
+ var ex = assertThrows('Expected an exception since the map has changed',
+ function() {
+ iter.next();
+ });
+ assertEquals(message, ex.message);
+
+ m = new goog.structs.Map;
+ m.set('a', 1);
+ m.set('b', 2);
+ m.set('c', 3);
+ m.set('d', 4);
+
+ iter = m.getValueIterator();
+ m.set('d', 5);
+ iter.next();
+ // Changing an existing value is OK.
+ iter.next();
+};
+
+function testTranspose() {
+ var m = new goog.structs.Map;
+ m.set('a', 1);
+ m.set('b', 2);
+ m.set('c', 3);
+ m.set('d', 4);
+ m.set('e', 5);
+
+ var transposed = m.transpose();
+ assertEquals('Should contain the keys', 'abcde',
+ goog.iter.join(transposed, ''));
+}
+
+function testToObject() {
+ Object.prototype.b = 0;
+ try {
+ var map = new goog.structs.Map();
+ map.set('a', 0);
+ var obj = map.toObject();
+ assertTrue('object representation has key "a"', obj.hasOwnProperty('a'));
+ assertFalse('object representation does not have key "b"',
+ obj.hasOwnProperty('b'));
+ assertEquals('value for key "a"', 0, obj['a']);
+ } finally {
+ delete Object.prototype.b;
+ }
+}
+
+function testEqualsWithSameObject() {
+ var map1 = getMap();
+ assertTrue('maps are the same object', map1.equals(map1));
+}
+
+function testEqualsWithDifferentSizeMaps() {
+ var map1 = getMap();
+ var map2 = new goog.structs.Map();
+
+ assertFalse('maps are different sizes', map1.equals(map2));
+}
+
+function testEqualsWithDefaultEqualityFn() {
+ var map1 = new goog.structs.Map();
+ var map2 = new goog.structs.Map();
+
+ assertTrue('maps are both empty', map1.equals(map2));
+
+ map1 = getMap();
+ map2 = getMap();
+ assertTrue('maps are the same', map1.equals(map2));
+
+ map2.set('d', '3');
+ assertFalse('maps have 3 and \'3\'', map1.equals(map2));
+}
+
+function testEqualsWithCustomEqualityFn() {
+ var map1 = new goog.structs.Map();
+ var map2 = new goog.structs.Map();
+
+ map1.set('a', 0);
+ map1.set('b', 1);
+
+ map2.set('a', '0');
+ map2.set('b', '1');
+
+ var equalsFn = function(a, b) { return a == b };
+
+ assertTrue('maps are equal with ==', map1.equals(map2, equalsFn));
+}
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/node.js b/contexts/data/lib/closure-library/closure/goog/structs/node.js
new file mode 100644
index 0000000..bc6a9fb
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/node.js
@@ -0,0 +1,74 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Generic immutable node object to be used in collections.
+ *
+ */
+
+
+goog.provide('goog.structs.Node');
+
+
+
+/**
+ * A generic immutable node. This can be used in various collections that
+ * require a node object for its item (such as a heap).
+ * @param {*} key Key.
+ * @param {*} value Vaue.
+ * @constructor
+ */
+goog.structs.Node = function(key, value) {
+ /**
+ * The key.
+ * @type {*}
+ * @private
+ */
+ this.key_ = key;
+
+ /**
+ * The value.
+ * @type {*}
+ * @private
+ */
+ this.value_ = value;
+};
+
+
+/**
+ * Gets the key.
+ * @return {*} The key.
+ */
+goog.structs.Node.prototype.getKey = function() {
+ return this.key_;
+};
+
+
+/**
+ * Gets the value.
+ * @return {*} The value.
+ */
+goog.structs.Node.prototype.getValue = function() {
+ return this.value_;
+};
+
+
+/**
+ * Clones a node and returns a new node.
+ * @return {goog.structs.Node} A new goog.structs.Node with the same key value
+ * pair.
+ */
+goog.structs.Node.prototype.clone = function() {
+ return new goog.structs.Node(this.key_, this.value_);
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/pool.js b/contexts/data/lib/closure-library/closure/goog/structs/pool.js
new file mode 100644
index 0000000..ba69dd0
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/pool.js
@@ -0,0 +1,381 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Datastructure: Pool.
+ *
+ *
+ * A generic class for handling pools of objects.
+ * When an object is released, it is attempted to be reused.
+ */
+
+
+goog.provide('goog.structs.Pool');
+
+goog.require('goog.Disposable');
+goog.require('goog.structs.Queue');
+goog.require('goog.structs.Set');
+
+
+
+/**
+ * A generic pool class. If min is greater than max, an error is thrown.
+ * @param {number=} opt_minCount Min. number of objects (Default: 1).
+ * @param {number=} opt_maxCount Max. number of objects (Default: 10).
+ * @constructor
+ * @extends {goog.Disposable}
+ */
+goog.structs.Pool = function(opt_minCount, opt_maxCount) {
+ goog.Disposable.call(this);
+
+ /**
+ * Minimum number of objects allowed
+ * @type {number}
+ * @private
+ */
+ this.minCount_ = opt_minCount || 0;
+
+ /**
+ * Maximum number of objects allowed
+ * @type {number}
+ * @private
+ */
+ this.maxCount_ = opt_maxCount || 10;
+
+ // Make sure that the max and min constraints are valid.
+ if (this.minCount_ > this.maxCount_) {
+ throw Error(goog.structs.Pool.ERROR_MIN_MAX_);
+ }
+
+ /**
+ * Set used to store objects that are currently in the pool and available
+ * to be used.
+ * @type {goog.structs.Queue}
+ * @private
+ */
+ this.freeQueue_ = new goog.structs.Queue();
+
+ /**
+ * Set used to store objects that are currently in the pool and in use.
+ * @type {goog.structs.Set}
+ * @private
+ */
+ this.inUseSet_ = new goog.structs.Set();
+
+ /**
+ * The minimum delay between objects being made available, in milliseconds. If
+ * this is 0, no minimum delay is enforced.
+ * @type {number}
+ * @protected
+ */
+ this.delay = 0;
+
+ /**
+ * The time of the last object being made available, in milliseconds since the
+ * epoch (i.e., the result of Date#toTime). If this is null, no access has
+ * occurred yet.
+ * @type {number?}
+ * @protected
+ */
+ this.lastAccess = null;
+
+ // Make sure that the minCount constraint is satisfied.
+ this.adjustForMinMax();
+
+
+ // TODO(user): Remove once JSCompiler's undefined properties warnings
+ // don't error for guarded properties.
+ var magicProps = {canBeReused: 0};
+};
+goog.inherits(goog.structs.Pool, goog.Disposable);
+
+
+/**
+ * Error to throw when the max/min constraint is attempted to be invalidated.
+ * I.e., when it is attempted for maxCount to be less than minCount.
+ * @type {string}
+ * @private
+ */
+goog.structs.Pool.ERROR_MIN_MAX_ =
+ '[goog.structs.Pool] Min can not be greater than max';
+
+
+/**
+ * Error to throw when the Pool is attempted to be disposed and it is asked to
+ * make sure that there are no objects that are in use (i.e., haven't been
+ * released).
+ * @type {string}
+ * @private
+ */
+goog.structs.Pool.ERROR_DISPOSE_UNRELEASED_OBJS_ =
+ '[goog.structs.Pool] Objects not released';
+
+
+/**
+ * Sets the minimum count of the pool.
+ * If min is greater than the max count of the pool, an error is thrown.
+ * @param {number} min The minimum count of the pool.
+ */
+goog.structs.Pool.prototype.setMinimumCount = function(min) {
+ // Check count constraints.
+ if (min > this.maxCount_) {
+ throw Error(goog.structs.Pool.ERROR_MIN_MAX_);
+ }
+ this.minCount_ = min;
+
+ // Adjust the objects in the pool as needed.
+ this.adjustForMinMax();
+};
+
+
+/**
+ * Sets the maximum count of the pool.
+ * If max is less than the max count of the pool, an error is thrown.
+ * @param {number} max The maximium count of the pool.
+ */
+goog.structs.Pool.prototype.setMaximumCount = function(max) {
+ // Check count constraints.
+ if (max < this.minCount_) {
+ throw Error(goog.structs.Pool.ERROR_MIN_MAX_);
+ }
+ this.maxCount_ = max;
+
+ // Adjust the objects in the pool as needed.
+ this.adjustForMinMax();
+};
+
+
+/**
+ * Sets the minimum delay between objects being returned by getObject, in
+ * milliseconds. This defaults to zero, meaning that no minimum delay is
+ * enforced and objects may be used as soon as they're available.
+ * @param {number} delay The minimum delay, in milliseconds.
+ */
+goog.structs.Pool.prototype.setDelay = function(delay) {
+ this.delay = delay;
+};
+
+
+/**
+ * @return {Object|undefined} A new object from the pool if there is one
+ * available, otherwise undefined.
+ */
+goog.structs.Pool.prototype.getObject = function() {
+ var time = goog.now();
+ if (goog.isDefAndNotNull(this.lastAccess) &&
+ time - this.lastAccess < this.delay) {
+ return undefined;
+ }
+
+ var obj = this.removeFreeObject_();
+ if (obj) {
+ this.lastAccess = time;
+ this.inUseSet_.add(obj);
+ }
+
+ return obj;
+};
+
+
+/**
+ * Returns an object to the pool of available objects so that it can be reused.
+ * @param {Object} obj The object to return to the pool of free objects.
+ * @return {boolean} Whether the object was found in the Pool's set of in-use
+ * objects (in other words, whether any action was taken).
+ */
+goog.structs.Pool.prototype.releaseObject = function(obj) {
+ if (this.inUseSet_.remove(obj)) {
+ this.addFreeObject(obj);
+ return true;
+ }
+ return false;
+};
+
+
+/**
+ * Removes a free object from the collection of objects that are free so that it
+ * can be used.
+ *
+ * NOTE: This method does not mark the returned object as in use.
+ *
+ * @return {Object|undefined} The object removed from the free collection, if
+ * there is one available. Otherwise, undefined.
+ * @private
+ */
+goog.structs.Pool.prototype.removeFreeObject_ = function() {
+ var obj;
+ while (this.getFreeCount() > 0) {
+ obj = /** @type {Object} */(this.freeQueue_.dequeue());
+
+ if (!this.objectCanBeReused(obj)) {
+ this.adjustForMinMax();
+ } else {
+ break;
+ }
+ }
+
+ if (!obj && this.getCount() < this.maxCount_) {
+ obj = this.createObject();
+ }
+
+ return obj;
+};
+
+
+/**
+ * Adds an object to the collection of objects that are free. If the object can
+ * not be added, then it is disposed.
+ *
+ * @param {Object} obj The object to add to collection of free objects.
+ */
+goog.structs.Pool.prototype.addFreeObject = function(obj) {
+ this.inUseSet_.remove(obj);
+ if (this.objectCanBeReused(obj) && this.getCount() < this.maxCount_) {
+ this.freeQueue_.enqueue(obj);
+ } else {
+ this.disposeObject(obj);
+ }
+};
+
+
+/**
+ * Adjusts the objects held in the pool to be within the min/max constraints.
+ *
+ * NOTE: It is possible that the number of objects in the pool will still be
+ * greater than the maximum count of objects allowed. This will be the case
+ * if no more free objects can be disposed of to get below the minimum count
+ * (i.e., all objects are in use).
+ */
+goog.structs.Pool.prototype.adjustForMinMax = function() {
+ var freeQueue = this.freeQueue_;
+
+ // Make sure the at least the minimum number of objects are created.
+ while (this.getCount() < this.minCount_) {
+ freeQueue.enqueue(this.createObject());
+ }
+
+ // Make sure no more than the maximum number of objects are created.
+ while (this.getCount() > this.maxCount_ && this.getFreeCount() > 0) {
+ this.disposeObject(/** @type {Object} */(freeQueue.dequeue()));
+ }
+};
+
+
+/**
+ * Should be overriden by sub-classes to return an instance of the object type
+ * that is expected in the pool.
+ * @return {Object} The created object.
+ */
+goog.structs.Pool.prototype.createObject = function() {
+ return {};
+};
+
+
+/**
+ * Should be overriden to dispose of an object. Default implementation is to
+ * remove all its members, which should render it useless. Calls the object's
+ * {@code dispose()} method, if available.
+ * @param {Object} obj The object to dispose.
+ */
+goog.structs.Pool.prototype.disposeObject = function(obj) {
+ if (typeof obj.dispose == 'function') {
+ obj.dispose();
+ } else {
+ for (var i in obj) {
+ obj[i] = null;
+ }
+ }
+};
+
+
+/**
+ * Should be overriden to determine whether an object has become unusable and
+ * should not be returned by getObject(). Calls the object's
+ * {@code canBeReused()} method, if available.
+ * @param {Object} obj The object to test.
+ * @return {boolean} Whether the object can be reused.
+ */
+goog.structs.Pool.prototype.objectCanBeReused = function(obj) {
+ if (typeof obj.canBeReused == 'function') {
+ return obj.canBeReused();
+ }
+ return true;
+};
+
+
+/**
+ * Returns true if the given object is in the pool.
+ * @param {Object} obj The object to check the pool for.
+ * @return {boolean} Whether the pool contains the object.
+ */
+goog.structs.Pool.prototype.contains = function(obj) {
+ return this.freeQueue_.contains(obj) || this.inUseSet_.contains(obj);
+};
+
+
+/**
+ * Returns the number of objects currently in the pool.
+ * @return {number} Number of objects currently in the pool.
+ */
+goog.structs.Pool.prototype.getCount = function() {
+ return this.freeQueue_.getCount() + this.inUseSet_.getCount();
+};
+
+
+/**
+ * Returns the number of objects currently in use in the pool.
+ * @return {number} Number of objects currently in use in the pool.
+ */
+goog.structs.Pool.prototype.getInUseCount = function() {
+ return this.inUseSet_.getCount();
+};
+
+
+/**
+ * Returns the number of objects currently free in the pool.
+ * @return {number} Number of objects currently free in the pool.
+ */
+goog.structs.Pool.prototype.getFreeCount = function() {
+ return this.freeQueue_.getCount();
+};
+
+
+/**
+ * Determines if the pool contains no objects.
+ * @return {boolean} Whether the pool contains no objects.
+ */
+goog.structs.Pool.prototype.isEmpty = function() {
+ return this.freeQueue_.isEmpty() && this.inUseSet_.isEmpty();
+};
+
+
+/**
+ * Disposes of the pool and all objects currently held in the pool.
+ * @override
+ * @protected
+ */
+goog.structs.Pool.prototype.disposeInternal = function() {
+ goog.structs.Pool.superClass_.disposeInternal.call(this);
+ if (this.getInUseCount() > 0) {
+ throw Error(goog.structs.Pool.ERROR_DISPOSE_UNRELEASED_OBJS_);
+ }
+ delete this.inUseSet_;
+
+ // Call disposeObject on each object held by the pool.
+ var freeQueue = this.freeQueue_;
+ while (!freeQueue.isEmpty()) {
+ this.disposeObject(/** @type {Object} */ (freeQueue.dequeue()));
+ }
+ delete this.freeQueue_;
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/pool_test.html b/contexts/data/lib/closure-library/closure/goog/structs/pool_test.html
new file mode 100644
index 0000000..461e70f
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/pool_test.html
@@ -0,0 +1,291 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2006 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs.Pool</title>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.structs');
+ goog.require('goog.structs.Pool');
+ goog.require('goog.testing.MockClock');
+ goog.require('goog.testing.jsunit');
+</script>
+</head>
+<body>
+<script>
+
+// Implementation of the Pool class with isObjectDead() always returning TRUE,
+// so that the the Pool will not reuse any objects.
+function NoObjectReusePool(opt_min, opt_max) {
+ goog.structs.Pool.call(this, opt_min, opt_max);
+};
+goog.inherits(NoObjectReusePool, goog.structs.Pool);
+
+NoObjectReusePool.prototype.objectCanBeReused = function(obj) {
+ return false;
+};
+
+
+function testExceedMax1() {
+ var p = new goog.structs.Pool(0, 3);
+ var obj1 = p.getObject();
+ var obj2 = p.getObject();
+ var obj3 = p.getObject();
+ var obj4 = p.getObject();
+ var obj5 = p.getObject();
+
+ assertNotUndefined(obj1);
+ assertNotUndefined(obj2);
+ assertNotUndefined(obj3);
+ assertUndefined(obj4);
+ assertUndefined(obj5);
+}
+
+
+function testExceedMax2() {
+ var p = new goog.structs.Pool(0, 1);
+ var obj1 = p.getObject();
+ var obj2 = p.getObject();
+ var obj3 = p.getObject();
+ var obj4 = p.getObject();
+ var obj5 = p.getObject();
+
+ assertNotUndefined(obj1);
+ assertUndefined(obj2);
+ assertUndefined(obj3);
+ assertUndefined(obj4);
+ assertUndefined(obj5);
+}
+
+
+function testExceedMax3() {
+ var p = new goog.structs.Pool(); // default: 10
+ var objs = [];
+
+ for (var i = 0; i < 12; i++) {
+ objs[i] = p.getObject();
+ }
+
+ for (var i = 0; i < 10; i++) {
+ assertNotNull('First 10 should be not null', objs[i]);
+ }
+
+ assertUndefined(objs[10]);
+ assertUndefined(objs[11]);
+}
+
+
+function testReleaseAndGet1() {
+ var p = new goog.structs.Pool(0, 10);
+ var o = p.getObject();
+ assertEquals(1, p.getCount());
+ assertEquals(1, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+ assertTrue('Result should be true', p.releaseObject(o));
+ assertEquals(1, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(1, p.getFreeCount());
+}
+
+
+function testReleaseAndGet2() {
+ var p = new NoObjectReusePool(0, 10);
+ var o = p.getObject();
+ assertEquals(1, p.getCount());
+ assertEquals(1, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+ assertTrue('Result should be true', p.releaseObject(o));
+ assertEquals(0, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+}
+
+
+function testReleaseAndGet3() {
+ var p = new goog.structs.Pool(0, 10);
+ var o1 = p.getObject();
+ var o2 = p.getObject();
+ var o3 = p.getObject();
+ var o4 = {};
+ assertEquals(3, p.getCount());
+ assertEquals(3, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+ assertTrue('Result should be true', p.releaseObject(o1));
+ assertTrue('Result should be true', p.releaseObject(o2));
+ assertFalse('Result should be false', p.releaseObject(o4));
+ assertEquals(3, p.getCount());
+ assertEquals(1, p.getInUseCount());
+ assertEquals(2, p.getFreeCount());
+}
+
+
+function testReleaseAndGet4() {
+ var p = new NoObjectReusePool(0, 10);
+ var o1 = p.getObject();
+ var o2 = p.getObject();
+ var o3 = p.getObject();
+ var o4 = {};
+ assertEquals(3, p.getCount());
+ assertEquals(3, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+ assertTrue('Result should be true', p.releaseObject(o1));
+ assertTrue('Result should be true', p.releaseObject(o2));
+ assertFalse('Result should be false', p.releaseObject(o4));
+ assertEquals(1, p.getCount());
+ assertEquals(1, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+}
+
+
+function testIsInPool1() {
+ var p = new goog.structs.Pool();
+ var o1 = p.getObject();
+ var o2 = p.getObject();
+ var o3 = p.getObject();
+ var o4 = {};
+ var o5 = {};
+ var o6 = o1;
+
+ assertTrue(p.contains(o1));
+ assertTrue(p.contains(o2));
+ assertTrue(p.contains(o3));
+ assertFalse(p.contains(o4));
+ assertFalse(p.contains(o5));
+ assertTrue(p.contains(o6));
+}
+
+
+function testSetMin1() {
+ var p = new goog.structs.Pool(0, 10);
+
+ assertEquals(0, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+
+ p.setMinimumCount(10);
+
+ assertEquals(10, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(10, p.getFreeCount());
+}
+
+
+function testSetMin2() {
+ var p = new goog.structs.Pool(0, 10);
+
+ assertEquals(0, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+
+ var o1 = p.getObject();
+
+ assertEquals(1, p.getCount());
+ assertEquals(1, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+
+ p.setMinimumCount(10);
+
+ assertEquals(10, p.getCount());
+ assertEquals(1, p.getInUseCount());
+ assertEquals(9, p.getFreeCount());
+}
+
+
+function testSetMax1() {
+ var p = new goog.structs.Pool(0, 10);
+
+ assertEquals(0, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+
+ var o1 = p.getObject();
+ var o2 = p.getObject();
+ var o3 = p.getObject();
+ var o4 = p.getObject();
+ var o5 = p.getObject();
+
+ assertEquals(5, p.getCount());
+ assertEquals(5, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+
+ assertTrue('Result should be true', p.releaseObject(o5));
+
+ assertEquals(5, p.getCount());
+ assertEquals(4, p.getInUseCount());
+ assertEquals(1, p.getFreeCount());
+
+ p.setMaximumCount(4);
+
+ assertEquals(4, p.getCount());
+ assertEquals(4, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+}
+
+
+function testInvalidMinMax1() {
+ var p = new goog.structs.Pool(0, 10);
+
+ assertEquals(0, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+
+ assertThrows(function() {
+ p.setMinimumCount(11);
+ });
+}
+
+
+function testInvalidMinMax2() {
+ var p = new goog.structs.Pool(5, 10);
+
+ assertEquals(5, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(5, p.getFreeCount());
+
+ assertThrows(function() {
+ p.setMaximumCount(4);
+ });
+}
+
+
+function testInvalidMinMax3() {
+ assertThrows(function() {
+ new goog.structs.Pool(10, 1);
+ });
+}
+
+
+function testRateLimiting() {
+ var clock = new goog.testing.MockClock();
+ clock.install();
+
+ var p = new goog.structs.Pool(0, 3);
+ p.setDelay(100);
+
+ assertNotUndefined(p.getObject());
+ assertUndefined(p.getObject());
+
+ clock.tick(100);
+ assertNotUndefined(p.getObject());
+ assertUndefined(p.getObject());
+
+ clock.tick(100);
+ assertNotUndefined(p.getObject());
+ assertUndefined(p.getObject());
+
+ clock.tick(100);
+ assertUndefined(p.getObject());
+
+ goog.dispose(clock);
+}
+
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/prioritypool.js b/contexts/data/lib/closure-library/closure/goog/structs/prioritypool.js
new file mode 100644
index 0000000..ce2af7f
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/prioritypool.js
@@ -0,0 +1,179 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Datastructure: Priority Pool.
+ *
+ *
+ * An extending of Pool that handles queueing and prioritization.
+ */
+
+
+goog.provide('goog.structs.PriorityPool');
+
+goog.require('goog.structs.Pool');
+goog.require('goog.structs.PriorityQueue');
+
+
+
+/**
+ * A generic pool class. If max is greater than min, an error is thrown.
+ * @param {number=} opt_minCount Min. number of objects (Default: 1).
+ * @param {number=} opt_maxCount Max. number of objects (Default: 10).
+ * @constructor
+ * @extends {goog.structs.Pool}
+ */
+goog.structs.PriorityPool = function(opt_minCount, opt_maxCount) {
+ /**
+ * Queue of requests for pool objects.
+ * @type {goog.structs.PriorityQueue}
+ * @private
+ */
+ this.requestQueue_ = new goog.structs.PriorityQueue();
+
+ // Must break convention of putting the super-class's constructor first. This
+ // is because the super-class constructor calls adjustForMinMax, which this
+ // class overrides. In this class's implementation, it assumes that there
+ // is a requestQueue_, and will error if not present.
+ goog.structs.Pool.call(this, opt_minCount, opt_maxCount);
+};
+goog.inherits(goog.structs.PriorityPool, goog.structs.Pool);
+
+
+/**
+ * The key for the most recent timeout created.
+ * @type {number|undefined}
+ * @private
+ */
+goog.structs.PriorityPool.prototype.delayTimeout_;
+
+
+/**
+ * Default priority for pool objects requests.
+ * @type {number}
+ * @private
+ */
+goog.structs.PriorityPool.DEFAULT_PRIORITY_ = 100;
+
+
+/** @override */
+goog.structs.PriorityPool.prototype.setDelay = function(delay) {
+ goog.base(this, 'setDelay', delay);
+
+ // If the pool hasn't been accessed yet, no need to do anything.
+ if (!goog.isDefAndNotNull(this.lastAccess)) {
+ return;
+ }
+
+ goog.global.clearTimeout(this.delayTimeout_);
+ this.delayTimeout_ = goog.global.setTimeout(
+ goog.bind(this.handleQueueRequests_, this),
+ this.delay + this.lastAccess - goog.now());
+
+ // Handle all requests.
+ this.handleQueueRequests_();
+};
+
+
+/**
+ * Get a new object from the the pool, if there is one available, otherwise
+ * return undefined.
+ * @param {Function=} opt_callback The function to callback when an object is
+ * available. This could be immediately. If this is not present, then an
+ * object is immediately returned if available, or undefined if not.
+ * @param {*=} opt_priority The priority of the request.
+ * @return {Object|undefined} The new object from the pool if there is one
+ * available and a callback is not given. Otherwise, undefined.
+ */
+goog.structs.PriorityPool.prototype.getObject = function(opt_callback,
+ opt_priority) {
+ if (!opt_callback) {
+ var result = goog.base(this, 'getObject');
+ if (result && this.delay) {
+ this.delayTimeout_ = goog.global.setTimeout(
+ goog.bind(this.handleQueueRequests_, this),
+ this.delay);
+ }
+ return result;
+ }
+
+ var priority = opt_priority || goog.structs.PriorityPool.DEFAULT_PRIORITY_;
+ this.requestQueue_.enqueue(priority, opt_callback);
+
+ // Handle all requests.
+ this.handleQueueRequests_();
+
+ return undefined;
+};
+
+
+/**
+ * Handles the request queue. Tries to fires off as many queued requests as
+ * possible.
+ * @private
+ */
+goog.structs.PriorityPool.prototype.handleQueueRequests_ = function() {
+ var requestQueue = this.requestQueue_;
+ while (requestQueue.getCount() > 0) {
+ var obj = this.getObject();
+
+ if (!obj) {
+ return;
+ } else {
+ var requestCallback = requestQueue.dequeue();
+ requestCallback.apply(this, [obj]);
+ }
+ }
+};
+
+
+/**
+ * Adds an object to the collection of objects that are free. If the object can
+ * not be added, then it is disposed.
+ *
+ * NOTE: This method does not remove the object from the in use collection.
+ *
+ * @param {Object} obj The object to add to the collection of free objects.
+ */
+goog.structs.PriorityPool.prototype.addFreeObject = function(obj) {
+ goog.structs.PriorityPool.superClass_.addFreeObject.call(this, obj);
+
+ // Handle all requests.
+ this.handleQueueRequests_();
+};
+
+
+/**
+ * Adjusts the objects held in the pool to be within the min/max constraints.
+ *
+ * NOTE: It is possible that the number of objects in the pool will still be
+ * greater than the maximum count of objects allowed. This will be the case
+ * if no more free objects can be disposed of to get below the minimum count
+ * (i.e., all objects are in use).
+ */
+goog.structs.PriorityPool.prototype.adjustForMinMax = function() {
+ goog.structs.PriorityPool.superClass_.adjustForMinMax.call(this);
+
+ // Handle all requests.
+ this.handleQueueRequests_();
+};
+
+
+/** @override */
+goog.structs.PriorityPool.prototype.disposeInternal = function() {
+ goog.structs.PriorityPool.superClass_.disposeInternal.call(this);
+ goog.global.clearTimeout(this.delayTimeout_);
+ this.requestQueue_.clear();
+ this.requestQueue_ = null;
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/prioritypool_test.html b/contexts/data/lib/closure-library/closure/goog/structs/prioritypool_test.html
new file mode 100644
index 0000000..7a0b367
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/prioritypool_test.html
@@ -0,0 +1,562 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2006 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs.PriorityPool</title>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.structs.PriorityPool');
+ goog.require('goog.testing.MockClock');
+ goog.require('goog.testing.jsunit');
+ goog.require('goog.structs');
+</script>
+</head>
+<body>
+<script>
+
+// Implementation of the Pool class with isObjectDead() always returning TRUE,
+// so that the the Pool will not reuse any objects.
+function NoObjectReusePriorityPool(opt_min, opt_max) {
+ goog.structs.PriorityPool.call(this, opt_min, opt_max);
+};
+goog.inherits(NoObjectReusePriorityPool, goog.structs.PriorityPool);
+
+NoObjectReusePriorityPool.prototype.objectCanBeReused = function(obj) {
+ return false;
+};
+
+
+function testExceedMax1() {
+ var p = new goog.structs.PriorityPool(0, 3);
+
+ var getCount1 = 0;
+ var callback1 = function(obj) {
+ assertNotNull(obj);
+ getCount1++;
+ };
+
+ var getCount2 = 0;
+ var callback2 = function(obj) {
+ getCount2++;
+ };
+
+ p.getObject(callback1);
+ p.getObject(callback1);
+ p.getObject(callback1);
+ p.getObject(callback2);
+ p.getObject(callback2);
+ p.getObject(callback2);
+
+ assertEquals('getCount for allocated, Should be 3', getCount1, 3);
+ assertEquals('getCount for unallocated, Should be 0', getCount2, 0);
+}
+
+
+function testExceedMax2() {
+ var p = new goog.structs.PriorityPool(0, 1);
+
+ var getCount1 = 0;
+ var callback1 = function(obj) {
+ assertNotNull(obj);
+ getCount1++;
+ };
+
+ var getCount2 = 0;
+ var callback2 = function(obj) {
+ getCount2++;
+ };
+
+ p.getObject(callback1);
+ p.getObject(callback2);
+ p.getObject(callback2);
+ p.getObject(callback2);
+ p.getObject(callback2);
+ p.getObject(callback2);
+
+ assertEquals('getCount for allocated, Should be 1', getCount1, 1);
+ assertEquals('getCount for unallocated, Should be 0', getCount2, 0);
+}
+
+function testExceedMax3() {
+ var p = new goog.structs.PriorityPool(0, 2);
+
+ var obj1 = null;
+ var callback1 = function(obj) {
+ obj1 = obj;
+ };
+
+ var obj2 = null;
+ var callback2 = function(obj) {
+ obj2 = obj;
+ };
+
+ var obj3 = null;
+ var callback3 = function(obj) {
+ obj3 = obj;
+ };
+
+ p.getObject(callback1);
+ p.getObject(callback2);
+ p.getObject(callback3);
+
+ assertNotNull(obj1);
+ assertNotNull(obj2);
+ assertNull(obj3);
+}
+
+function testExceedMax4() {
+ var p = new goog.structs.PriorityPool(); // default: 10
+ var objs = [];
+
+ var getCount1 = 0;
+ var callback1 = function(obj) {
+ assertNotNull(obj);
+ getCount1++;
+ };
+
+ var getCount2 = 0;
+ var callback2 = function(obj) {
+ getCount2++;
+ };
+
+ for (var i = 0; i < 12; i++) {
+ p.getObject(i < 10 ? callback1 : callback2);
+ }
+
+ assertEquals('getCount for allocated, Should be 10', getCount1, 10);
+ assertEquals('getCount for unallocated, Should be 0', getCount2, 0);
+}
+
+
+function testReleaseAndGet1() {
+ var p = new goog.structs.PriorityPool(0, 10);
+
+ var o = null;
+ var callback = function(obj) {
+ o = obj;
+ };
+
+ p.getObject(callback);
+ assertEquals(1, p.getCount());
+ assertEquals(1, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+ assertTrue('Result should be true', p.releaseObject(o));
+ assertEquals(1, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(1, p.getFreeCount());
+}
+
+
+function testReleaseAndGet2() {
+ var p = new NoObjectReusePriorityPool(0, 10);
+
+ var o = null;
+ var callback = function(obj) {
+ o = obj;
+ };
+
+ p.getObject(callback);
+ assertEquals(1, p.getCount());
+ assertEquals(1, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+ assertTrue('Result should be true', p.releaseObject(o));
+ assertEquals(0, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+}
+
+
+function testReleaseAndGet3() {
+ var p = new goog.structs.PriorityPool(0, 10);
+ var o1 = null;
+ var callback1 = function(obj) {
+ o1 = obj;
+ };
+
+ var o2 = null;
+ var callback2 = function(obj) {
+ o2 = obj;
+ };
+
+ var o3 = null;
+ var callback3 = function(obj) {
+ o3 = obj;
+ };
+
+ var o4 = {};
+
+ p.getObject(callback1);
+ p.getObject(callback2);
+ p.getObject(callback3);
+
+ assertEquals(3, p.getCount());
+ assertEquals(3, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+ assertTrue('Result should be true', p.releaseObject(o1));
+ assertTrue('Result should be true', p.releaseObject(o2));
+ assertFalse('Result should be false', p.releaseObject(o4));
+ assertEquals(3, p.getCount());
+ assertEquals(1, p.getInUseCount());
+ assertEquals(2, p.getFreeCount());
+}
+
+
+function testReleaseAndGet4() {
+ var p = new NoObjectReusePriorityPool(0, 10);
+
+ var o1 = null;
+ var callback1 = function(obj) {
+ o1 = obj;
+ };
+
+ var o2 = null;
+ var callback2 = function(obj) {
+ o2 = obj;
+ };
+
+ var o3 = null;
+ var callback3 = function(obj) {
+ o3 = obj;
+ };
+
+ var o4 = {};
+
+ p.getObject(callback1);
+ p.getObject(callback2);
+ p.getObject(callback3);
+ assertEquals(3, p.getCount());
+ assertEquals(3, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+ assertTrue('Result should be true', p.releaseObject(o1));
+ assertTrue('Result should be true', p.releaseObject(o2));
+ assertFalse('Result should be false', p.releaseObject(o4));
+ assertEquals(1, p.getCount());
+ assertEquals(1, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+}
+
+
+function testIsInPool1() {
+ var p = new goog.structs.PriorityPool();
+ var o1 = null;
+ var callback1 = function(obj) {
+ o1 = obj;
+ };
+
+ var o2 = null;
+ var callback2 = function(obj) {
+ o2 = obj;
+ };
+
+ var o3 = null;
+ var callback3 = function(obj) {
+ o3 = obj;
+ };
+
+ var o4 = {};
+ var o5 = {};
+
+ p.getObject(callback1);
+ p.getObject(callback2);
+ p.getObject(callback3);
+ var o6 = o1;
+
+ assertTrue(p.contains(o1));
+ assertTrue(p.contains(o2));
+ assertTrue(p.contains(o3));
+ assertFalse(p.contains(o4));
+ assertFalse(p.contains(o5));
+ assertTrue(p.contains(o6));
+}
+
+
+function testSetMin1() {
+ var p = new goog.structs.PriorityPool(0, 10);
+
+ assertEquals(0, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+
+ p.setMinimumCount(10);
+
+ assertEquals(10, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(10, p.getFreeCount());
+}
+
+
+function testSetMin2() {
+ var p = new goog.structs.PriorityPool(0, 10);
+
+ assertEquals(0, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+
+ var o1 = null;
+ var callback1 = function(obj) {
+ o1 = obj;
+ };
+ p.getObject(callback1);
+
+ assertEquals(1, p.getCount());
+ assertEquals(1, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+
+ p.setMinimumCount(10);
+
+ assertEquals(10, p.getCount());
+ assertEquals(1, p.getInUseCount());
+ assertEquals(9, p.getFreeCount());
+}
+
+
+function testSetMax1() {
+ var p = new goog.structs.PriorityPool(0, 10);
+
+ assertEquals(0, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+
+ var o1 = null;
+ var callback1 = function(obj) {
+ o1 = obj;
+ };
+
+ var o2 = null;
+ var callback2 = function(obj) {
+ o2 = obj;
+ };
+
+ var o3 = null;
+ var callback3 = function(obj) {
+ o3 = obj;
+ };
+
+ var o4 = null;
+ var callback4 = function(obj) {
+ o4 = obj;
+ };
+
+ var o5 = null;
+ var callback5 = function(obj) {
+ o5 = obj;
+ };
+
+ p.getObject(callback1);
+ p.getObject(callback2);
+ p.getObject(callback3);
+ p.getObject(callback4);
+ p.getObject(callback5);
+
+ assertEquals(5, p.getCount());
+ assertEquals(5, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+
+ assertTrue('Result should be true', p.releaseObject(o5));
+
+ assertEquals(5, p.getCount());
+ assertEquals(4, p.getInUseCount());
+ assertEquals(1, p.getFreeCount());
+
+ p.setMaximumCount(4);
+
+ assertEquals(4, p.getCount());
+ assertEquals(4, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+}
+
+
+function testInvalidMinMax1() {
+ var p = new goog.structs.PriorityPool(0, 10);
+
+ assertEquals(0, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(0, p.getFreeCount());
+
+ assertThrows(function() {
+ p.setMinimumCount(11);
+ });
+}
+
+
+function testInvalidMinMax2() {
+ var p = new goog.structs.PriorityPool(5, 10);
+
+ assertEquals(5, p.getCount());
+ assertEquals(0, p.getInUseCount());
+ assertEquals(5, p.getFreeCount());
+
+ assertThrows(function() {
+ p.setMaximumCount(4);
+ });
+}
+
+
+function testInvalidMinMax3() {
+ assertThrows(function() {
+ new goog.structs.PriorityPool(10, 1);
+ });
+}
+
+function testQueue1() {
+ var p = new goog.structs.PriorityPool(0, 2);
+
+ var o1 = null;
+ var callback1 = function(obj) {
+ o1 = obj;
+ };
+
+ var o2 = null;
+ var callback2 = function(obj) {
+ o2 = obj;
+ };
+
+ var o3 = null;
+ var callback3 = function(obj) {
+ o3 = obj;
+ };
+
+ p.getObject(callback1);
+ p.getObject(callback2);
+ p.getObject(callback3);
+
+ assertNotNull(o1);
+ assertNotNull(o2);
+ assertNull(o3);
+
+ p.releaseObject(o1);
+ assertNotNull(o3);
+}
+
+
+function testPriority1() {
+ var p = new goog.structs.PriorityPool(0, 2);
+
+ var o1 = null;
+ var callback1 = function(obj) {
+ o1 = obj;
+ };
+
+ var o2 = null;
+ var callback2 = function(obj) {
+ o2 = obj;
+ };
+
+ var o3 = null;
+ var callback3 = function(obj) {
+ o3 = obj;
+ };
+
+ var o4 = null;
+ var callback4 = function(obj) {
+ o4 = obj;
+ };
+
+ p.getObject(callback1);
+ p.getObject(callback2);
+ p.getObject(callback3, 10);
+ p.getObject(callback4, 5);
+
+ assertNotNull(o1);
+ assertNotNull(o2);
+ assertNull(o3);
+ assertNull(o4);
+
+ p.releaseObject(o1);
+ assertNull(o3);
+ assertNotNull(o4);
+}
+
+
+function testRateLimiting() {
+ var clock = new goog.testing.MockClock();
+ clock.install();
+
+ var p = new goog.structs.PriorityPool(0, 4);
+ p.setDelay(100);
+
+ var getCount = 0;
+ var callback = function(obj) {
+ assertNotNull(obj);
+ getCount++;
+ };
+
+ p.getObject(callback);
+ assertEquals(1, getCount);
+
+ p.getObject(callback);
+ assertEquals(1, getCount);
+
+ clock.tick(100);
+ assertEquals(2, getCount);
+
+ p.getObject(callback);
+ p.getObject(callback);
+ assertEquals(2, getCount);
+
+ clock.tick(100);
+ assertEquals(3, getCount);
+
+ clock.tick(100);
+ assertEquals(4, getCount);
+
+ p.getObject(callback);
+ assertEquals(4, getCount);
+
+ clock.tick(100);
+ assertEquals(4, getCount);
+
+ goog.dispose(clock);
+}
+
+
+function testRateLimitingWithChangingDelay() {
+ var clock = new goog.testing.MockClock();
+ clock.install();
+
+ var p = new goog.structs.PriorityPool(0, 3);
+ p.setDelay(100);
+
+ var getCount = 0;
+ var callback = function(obj) {
+ assertNotNull(obj);
+ getCount++;
+ };
+
+ p.getObject(callback);
+ assertEquals(1, getCount);
+
+ p.getObject(callback);
+ assertEquals(1, getCount);
+
+ clock.tick(50);
+ assertEquals(1, getCount);
+
+ p.setDelay(50);
+ assertEquals(2, getCount);
+
+ p.getObject(callback);
+ assertEquals(2, getCount);
+
+ clock.tick(20);
+ assertEquals(2, getCount);
+
+ p.setDelay(40);
+ assertEquals(2, getCount);
+
+ clock.tick(20);
+ assertEquals(3, getCount);
+
+ goog.dispose(clock);
+}
+
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/priorityqueue.js b/contexts/data/lib/closure-library/closure/goog/structs/priorityqueue.js
new file mode 100644
index 0000000..07b2b28
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/priorityqueue.js
@@ -0,0 +1,64 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Datastructure: Priority Queue.
+ *
+ *
+ * This file provides the implementation of a Priority Queue. Smaller priorities
+ * move to the front of the queue. If two values have the same priority,
+ * it is arbitrary which value will come to the front of the queue first.
+ */
+
+// TODO(user): Should this rely on natural ordering via some Comparable
+// interface?
+
+
+goog.provide('goog.structs.PriorityQueue');
+
+goog.require('goog.structs');
+goog.require('goog.structs.Heap');
+
+
+
+/**
+ * Class for Priority Queue datastructure.
+ *
+ * @constructor
+ * @extends {goog.structs.Heap}
+ */
+goog.structs.PriorityQueue = function() {
+ goog.structs.Heap.call(this);
+};
+goog.inherits(goog.structs.PriorityQueue, goog.structs.Heap);
+
+
+/**
+ * Puts the specified value in the queue.
+ * @param {*} priority The priority of the value.
+ * @param {*} value The value.
+ */
+goog.structs.PriorityQueue.prototype.enqueue = function(priority, value) {
+ this.insert(priority, value);
+};
+
+
+/**
+ * Retrieves and removes the head of this queue.
+ * @return {*} The element at the head of this queue. Returns
+ * undefined if the queue is empty.
+ */
+goog.structs.PriorityQueue.prototype.dequeue = function() {
+ return this.remove();
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/priorityqueue_test.html b/contexts/data/lib/closure-library/closure/goog/structs/priorityqueue_test.html
new file mode 100644
index 0000000..ceae23c
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/priorityqueue_test.html
@@ -0,0 +1,179 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2006 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs.PriorityQueue</title>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.structs');
+ goog.require('goog.structs.PriorityQueue');
+ goog.require('goog.testing.jsunit');
+</script>
+</head>
+<body>
+<script>
+
+function getPriorityQueue() {
+ var p = new goog.structs.PriorityQueue();
+ p.enqueue(0, 'a');
+ p.enqueue(1, 'b');
+ p.enqueue(2, 'c');
+ p.enqueue(3, 'd');
+ return p;
+}
+
+
+function getPriorityQueue2() {
+ var p = new goog.structs.PriorityQueue();
+ p.insert(1, 'b');
+ p.insert(3, 'd');
+ p.insert(0, 'a');
+ p.insert(2, 'c');
+ return p;
+}
+
+
+function testGetCount1() {
+ var p = getPriorityQueue();
+ assertEquals('count, should be 4', p.getCount(), 4);
+ p.dequeue();
+ assertEquals('count, should be 3', p.getCount(), 3);
+}
+
+
+function testGetCount2() {
+ var p = getPriorityQueue();
+ assertEquals('count, should be 4', p.getCount(), 4);
+ p.dequeue();
+ assertEquals('count, should be 3', p.getCount(), 3);
+}
+
+
+function testGetCount3() {
+ var p = getPriorityQueue();
+ p.dequeue();
+ p.dequeue();
+ p.dequeue();
+ p.dequeue();
+ assertEquals('count, should be 0', p.getCount(), 0);
+}
+
+
+function testKeys() {
+ var p = getPriorityQueue();
+ var keys = p.getKeys();
+ for (var i = 0; i < 4; i++) {
+ assertTrue('getKeys, key ' + i + ' found', goog.structs.contains(keys, i));
+ }
+ assertEquals('getKeys, Should be 4 keys', goog.structs.getCount(keys), 4);
+}
+
+
+function testValues() {
+ var p = getPriorityQueue();
+ var values = p.getValues();
+
+ assertTrue('getKeys, value "a" found', goog.structs.contains(values, 'a'));
+ assertTrue('getKeys, value "b" found', goog.structs.contains(values, 'b'));
+ assertTrue('getKeys, value "c" found', goog.structs.contains(values, 'c'));
+ assertTrue('getKeys, value "d" found', goog.structs.contains(values, 'd'));
+ assertEquals('getKeys, Should be 4 keys', goog.structs.getCount(values), 4);
+}
+
+
+function testClear() {
+ var p = getPriorityQueue();
+ p.clear();
+ assertTrue('cleared so it should be empty', p.isEmpty());
+}
+
+
+function testIsEmpty() {
+ var p = getPriorityQueue();
+ assertFalse('4 values so should not be empty', p.isEmpty());
+
+ p.dequeue();
+ p.dequeue();
+ p.dequeue();
+ assertFalse('1 values so should not be empty', p.isEmpty());
+
+ p.dequeue();
+ assertTrue('0 values so should be empty', p.isEmpty());
+}
+
+
+function testPeek1() {
+ var p = getPriorityQueue();
+ assertEquals('peek, Should be "a"', p.peek(), 'a');
+}
+
+
+function testPeek2() {
+ var p = getPriorityQueue2();
+ assertEquals('peek, Should be "a"', p.peek(), 'a');
+}
+
+
+function testPeek3() {
+ var p = getPriorityQueue();
+ p.clear();
+ assertEquals('peek, Should be "a"', p.peek(), undefined);
+}
+
+
+function testDequeue1() {
+ var p = getPriorityQueue();
+
+ assertEquals('dequeue, Should be "a"', p.dequeue(), 'a');
+ assertEquals('dequeue, Should be "b"', p.dequeue(), 'b');
+ assertEquals('dequeue, Should be "c"', p.dequeue(), 'c');
+ assertEquals('dequeue, Should be "d"', p.dequeue(), 'd');
+}
+
+
+function testDequeue2() {
+ var p = getPriorityQueue2();
+
+ assertEquals('dequeue, Should be "a"', p.dequeue(), 'a');
+ assertEquals('dequeue, Should be "b"', p.dequeue(), 'b');
+ assertEquals('dequeue, Should be "c"', p.dequeue(), 'c');
+ assertEquals('dequeue, Should be "d"', p.dequeue(), 'd');
+}
+
+
+function testEnqueuePeek1() {
+ var p = new goog.structs.PriorityQueue();
+
+ p.enqueue(3, 'd');
+ assertEquals('peak, Should be "d"', p.peek(), 'd');
+ p.enqueue(2, 'c');
+ assertEquals('peak, Should be "c"', p.peek(), 'c');
+ p.enqueue(1, 'b');
+ assertEquals('peak, Should be "b"', p.peek(), 'b');
+ p.enqueue(0, 'a');
+ assertEquals('peak, Should be "a"', p.peek(), 'a');
+}
+
+
+function testEnqueuePeek2() {
+ var p = new goog.structs.PriorityQueue();
+
+ p.enqueue(1, 'b');
+ assertEquals('peak, Should be "b"', p.peek(), 'b');
+ p.enqueue(3, 'd');
+ assertEquals('peak, Should be "b"', p.peek(), 'b');
+ p.enqueue(0, 'a');
+ assertEquals('peak, Should be "a"', p.peek(), 'a');
+ p.enqueue(2, 'c');
+ assertEquals('peak, Should be "a"', p.peek(), 'a');
+}
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/quadtree.js b/contexts/data/lib/closure-library/closure/goog/structs/quadtree.js
new file mode 100644
index 0000000..db52476
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/quadtree.js
@@ -0,0 +1,571 @@
+// Copyright 2008 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Datastructure: A point Quad Tree for representing 2D data. Each
+ * region has the same ratio as the bounds for the tree.
+ *
+ * The implementation currently requires pre-determined bounds for data as it
+ * can not rebalance itself to that degree.
+ *
+ * @see ../demos/quadtree.html
+ */
+
+
+goog.provide('goog.structs.QuadTree');
+goog.provide('goog.structs.QuadTree.Node');
+goog.provide('goog.structs.QuadTree.Point');
+
+goog.require('goog.math.Coordinate');
+
+
+
+/**
+ * Constructs a new quad tree.
+ * @param {number} minX Minimum x-value that can be held in tree.
+ * @param {number} minY Minimum y-value that can be held in tree.
+ * @param {number} maxX Maximum x-value that can be held in tree.
+ * @param {number} maxY Maximum y-value that can be held in tree.
+ * @constructor
+ */
+goog.structs.QuadTree = function(minX, minY, maxX, maxY) {
+
+ /**
+ * The root node for the quad tree.
+ * @type {goog.structs.QuadTree.Node}
+ * @private
+ */
+ this.root_ = new goog.structs.QuadTree.Node(
+ minX, minY, maxX - minX, maxY - minY);
+};
+
+
+/**
+ * Count of the number of items in the tree.
+ * @type {number}
+ * @private
+ */
+goog.structs.QuadTree.prototype.count_ = 0;
+
+
+/**
+ * Returns a reference to the tree's root node. Callers shouldn't modify nodes,
+ * directly. This is a convenience for visualization and debugging purposes.
+ * @return {goog.structs.QuadTree.Node} The root node.
+ */
+goog.structs.QuadTree.prototype.getRootNode = function() {
+ return this.root_;
+};
+
+
+/**
+ * Sets the value of an (x, y) point within the quad-tree.
+ * @param {number} x The x-coordinate.
+ * @param {number} y The y-coordinate.
+ * @param {*} value The value associated with the point.
+ */
+goog.structs.QuadTree.prototype.set = function(x, y, value) {
+ var root = this.root_;
+ if (x < root.x || y < root.y || x > root.x + root.w || y > root.y + root.h) {
+ throw Error('Out of bounds : (' + x + ', ' + y + ')');
+ }
+ if (this.insert_(root, new goog.structs.QuadTree.Point(x, y, value))) {
+ this.count_++;
+ }
+};
+
+
+/**
+ * Gets the value of the point at (x, y) or null if the point is empty.
+ * @param {number} x The x-coordinate.
+ * @param {number} y The y-coordinate.
+ * @param {*=} opt_default The default value to return if the node doesn't
+ * exist.
+ * @return {*} The value of the node, the default value if the node
+ * doesn't exist, or undefined if the node doesn't exist and no default
+ * has been provided.
+ */
+goog.structs.QuadTree.prototype.get = function(x, y, opt_default) {
+ var node = this.find_(this.root_, x, y);
+ return node ? node.point.value : opt_default;
+};
+
+
+/**
+ * Removes a point from (x, y) if it exists.
+ * @param {number} x The x-coordinate.
+ * @param {number} y The y-coordinate.
+ * @return {*} The value of the node that was removed, or null if the
+ * node doesn't exist.
+ */
+goog.structs.QuadTree.prototype.remove = function(x, y) {
+ var node = this.find_(this.root_, x, y);
+ if (node) {
+ var value = node.point.value;
+ node.point = null;
+ node.nodeType = goog.structs.QuadTree.NodeType.EMPTY;
+ this.balance_(node);
+ this.count_--;
+ return value;
+ } else {
+ return null;
+ }
+};
+
+
+/**
+ * Returns true if the point at (x, y) exists in the tree.
+ * @param {number} x The x-coordinate.
+ * @param {number} y The y-coordinate.
+ * @return {boolean} Whether the tree contains a point at (x, y).
+ */
+goog.structs.QuadTree.prototype.contains = function(x, y) {
+ return this.get(x, y) != null;
+};
+
+
+/**
+ * @return {boolean} Whether the tree is empty.
+ */
+goog.structs.QuadTree.prototype.isEmpty = function() {
+ return this.root_.nodeType == goog.structs.QuadTree.NodeType.EMPTY;
+};
+
+
+/**
+ * @return {number} The number of items in the tree.
+ */
+goog.structs.QuadTree.prototype.getCount = function() {
+ return this.count_;
+};
+
+
+/**
+ * Removes all items from the tree.
+ */
+goog.structs.QuadTree.prototype.clear = function() {
+ this.root_.nw = this.root_.ne = this.root_.sw = this.root_.se = null;
+ this.root_.nodeType = goog.structs.QuadTree.NodeType.EMPTY;
+ this.root_.point = null;
+ this.count_ = 0;
+};
+
+
+/**
+ * Returns an array containing the coordinates of each point stored in the tree.
+ * @return {Array.<goog.math.Coordinate?>} Array of coordinates.
+ */
+goog.structs.QuadTree.prototype.getKeys = function() {
+ var arr = [];
+ this.traverse_(this.root_, function(node) {
+ arr.push(new goog.math.Coordinate(node.point.x, node.point.y));
+ });
+ return arr;
+};
+
+
+/**
+ * Returns an array containing all values stored within the tree.
+ * @return {Array.<Object>} The values stored within the tree.
+ */
+goog.structs.QuadTree.prototype.getValues = function() {
+ var arr = [];
+ this.traverse_(this.root_, function(node) {
+ // Must have a point because it's a leaf.
+ arr.push(node.point.value);
+ });
+ return arr;
+};
+
+
+/**
+ * Clones the quad-tree and returns the new instance.
+ * @return {goog.structs.QuadTree} A clone of the tree.
+ */
+goog.structs.QuadTree.prototype.clone = function() {
+ var x1 = this.root_.x;
+ var y1 = this.root_.y;
+ var x2 = x1 + this.root_.w;
+ var y2 = y1 + this.root_.h;
+ var clone = new goog.structs.QuadTree(x1, y1, x2, y2);
+ // This is inefficient as the clone needs to recalculate the structure of the
+ // tree, even though we know it already. But this is easier and can be
+ // optimized when/if needed.
+ this.traverse_(this.root_, function(node) {
+ clone.set(node.point.x, node.point.y, node.point.value);
+ });
+ return clone;
+};
+
+
+/**
+ * Traverses the tree and calls a function on each node.
+ * @param {function(Object, goog.math.Coordinate, goog.structs.QuadTree)} fn
+ * The function to call for every value. This function takes 3 arguments
+ * (the value, the coordinate, and the tree itself) and the return value is
+ * irrelevant.
+ * @param {Object=} opt_obj The object to be used as the value of 'this'
+ * within {@ code fn}.
+ */
+goog.structs.QuadTree.prototype.forEach = function(fn, opt_obj) {
+ this.traverse_(this.root_, function(node) {
+ var coord = new goog.math.Coordinate(node.point.x, node.point.y);
+ fn.call(opt_obj, node.point.value, coord, this);
+ });
+};
+
+
+/**
+ * Traverses the tree depth-first, with quadrants being traversed in clockwise
+ * order (NE, SE, SW, NW). The provided function will be called for each
+ * leaf node that is encountered.
+ * @param {goog.structs.QuadTree.Node} node The current node.
+ * @param {function(goog.structs.QuadTree.Node)} fn The function to call
+ * for each leaf node. This function takes the node as an argument, and its
+ * return value is irrelevant.
+ * @private
+ */
+goog.structs.QuadTree.prototype.traverse_ = function(node, fn) {
+ switch (node.nodeType) {
+ case goog.structs.QuadTree.NodeType.LEAF:
+ fn.call(this, node);
+ break;
+
+ case goog.structs.QuadTree.NodeType.POINTER:
+ this.traverse_(node.ne, fn);
+ this.traverse_(node.se, fn);
+ this.traverse_(node.sw, fn);
+ this.traverse_(node.nw, fn);
+ break;
+ }
+};
+
+
+/**
+ * Finds a leaf node with the same (x, y) coordinates as the target point, or
+ * null if no point exists.
+ * @param {goog.structs.QuadTree.Node} node The node to search in.
+ * @param {number} x The x-coordinate of the point to search for.
+ * @param {number} y The y-coordinate of the point to search for.
+ * @return {goog.structs.QuadTree.Node} The leaf node that matches the target,
+ * or null if it doesn't exist.
+ * @private
+ */
+goog.structs.QuadTree.prototype.find_ = function(node, x, y) {
+ switch (node.nodeType) {
+ case goog.structs.QuadTree.NodeType.EMPTY:
+ return null;
+
+ case goog.structs.QuadTree.NodeType.LEAF:
+ return node.point.x == x && node.point.y == y ? node : null;
+
+ case goog.structs.QuadTree.NodeType.POINTER:
+ return this.find_(this.getQuadrantForPoint_(node, x, y), x, y);
+
+ default:
+ throw Error('Invalid nodeType');
+ }
+};
+
+
+/**
+ * Inserts a point into the tree, updating the tree's structure if necessary.
+ * @param {goog.structs.QuadTree.Node} parent The parent to insert the point
+ * into.
+ * @param {goog.structs.QuadTree.Point} point The point to insert.
+ * @return {boolean} True if a new node was added to the tree; False if a node
+ * already existed with the correpsonding coordinates and had its value
+ * reset.
+ * @private
+ */
+goog.structs.QuadTree.prototype.insert_ = function(parent, point) {
+ switch (parent.nodeType) {
+ case goog.structs.QuadTree.NodeType.EMPTY:
+ this.setPointForNode_(parent, point);
+ return true;
+
+ case goog.structs.QuadTree.NodeType.LEAF:
+ if (parent.point.x == point.x && parent.point.y == point.y) {
+ this.setPointForNode_(parent, point);
+ return false;
+ } else {
+ this.split_(parent);
+ return this.insert_(parent, point);
+ }
+
+ case goog.structs.QuadTree.NodeType.POINTER:
+ return this.insert_(
+ this.getQuadrantForPoint_(parent, point.x, point.y), point);
+
+ default:
+ throw Error('Invalid nodeType in parent');
+ }
+};
+
+
+/**
+ * Converts a leaf node to a pointer node and reinserts the node's point into
+ * the correct child.
+ * @param {goog.structs.QuadTree.Node} node The node to split.
+ * @private
+ */
+goog.structs.QuadTree.prototype.split_ = function(node) {
+ var oldPoint = node.point;
+ node.point = null;
+
+ node.nodeType = goog.structs.QuadTree.NodeType.POINTER;
+
+ var x = node.x;
+ var y = node.y;
+ var hw = node.w / 2;
+ var hh = node.h / 2;
+
+ node.nw = new goog.structs.QuadTree.Node(x, y, hw, hh, node);
+ node.ne = new goog.structs.QuadTree.Node(x + hw, y, hw, hh, node);
+ node.sw = new goog.structs.QuadTree.Node(x, y + hh, hw, hh, node);
+ node.se = new goog.structs.QuadTree.Node(x + hw, y + hh, hw, hh, node);
+
+ this.insert_(node, oldPoint);
+};
+
+
+/**
+ * Attempts to balance a node. A node will need balancing if all its children
+ * are empty or it contains just one leaf.
+ * @param {goog.structs.QuadTree.Node} node The node to balance.
+ * @private
+ */
+goog.structs.QuadTree.prototype.balance_ = function(node) {
+ switch (node.nodeType) {
+ case goog.structs.QuadTree.NodeType.EMPTY:
+ case goog.structs.QuadTree.NodeType.LEAF:
+ if (node.parent) {
+ this.balance_(node.parent);
+ }
+ break;
+
+ case goog.structs.QuadTree.NodeType.POINTER:
+ var nw = node.nw, ne = node.ne, sw = node.sw, se = node.se;
+ var firstLeaf = null;
+
+ // Look for the first non-empty child, if there is more than one then we
+ // break as this node can't be balanced.
+ if (nw.nodeType != goog.structs.QuadTree.NodeType.EMPTY) {
+ firstLeaf = nw;
+ }
+ if (ne.nodeType != goog.structs.QuadTree.NodeType.EMPTY) {
+ if (firstLeaf) {
+ break;
+ }
+ firstLeaf = ne;
+ }
+ if (sw.nodeType != goog.structs.QuadTree.NodeType.EMPTY) {
+ if (firstLeaf) {
+ break;
+ }
+ firstLeaf = sw;
+ }
+ if (se.nodeType != goog.structs.QuadTree.NodeType.EMPTY) {
+ if (firstLeaf) {
+ break;
+ }
+ firstLeaf = se;
+ }
+
+ if (!firstLeaf) {
+ // All child nodes are empty: so make this node empty.
+ node.nodeType = goog.structs.QuadTree.NodeType.EMPTY;
+ node.nw = node.ne = node.sw = node.se = null;
+
+ } else if (firstLeaf.nodeType == goog.structs.QuadTree.NodeType.POINTER) {
+ // Only child was a pointer, therefore we can't rebalance.
+ break;
+
+ } else {
+ // Only child was a leaf: so update node's point and make it a leaf.
+ node.nodeType = goog.structs.QuadTree.NodeType.LEAF;
+ node.nw = node.ne = node.sw = node.se = null;
+ node.point = firstLeaf.point;
+ }
+
+ // Try and balance the parent as well.
+ if (node.parent) {
+ this.balance_(node.parent);
+ }
+
+ break;
+ }
+};
+
+
+/**
+ * Returns the child quadrant within a node that contains the given (x, y)
+ * coordinate.
+ * @param {goog.structs.QuadTree.Node} parent The node.
+ * @param {number} x The x-coordinate to look for.
+ * @param {number} y The y-coordinate to look for.
+ * @return {goog.structs.QuadTree.Node} The child quadrant that contains the
+ * point.
+ * @private
+ */
+goog.structs.QuadTree.prototype.getQuadrantForPoint_ = function(parent, x, y) {
+ var mx = parent.x + parent.w / 2;
+ var my = parent.y + parent.h / 2;
+ if (x < mx) {
+ return y < my ? parent.nw : parent.sw;
+ } else {
+ return y < my ? parent.ne : parent.se;
+ }
+};
+
+
+/**
+ * Sets the point for a node, as long as the node is a leaf or empty.
+ * @param {goog.structs.QuadTree.Node} node The node to set the point for.
+ * @param {goog.structs.QuadTree.Point} point The point to set.
+ * @private
+ */
+goog.structs.QuadTree.prototype.setPointForNode_ = function(node, point) {
+ if (node.nodeType == goog.structs.QuadTree.NodeType.POINTER) {
+ throw Error('Can not set point for node of type POINTER');
+ }
+ node.nodeType = goog.structs.QuadTree.NodeType.LEAF;
+ node.point = point;
+};
+
+
+/**
+ * Enumeration of node types.
+ * @enum {number}
+ */
+goog.structs.QuadTree.NodeType = {
+ EMPTY: 0,
+ LEAF: 1,
+ POINTER: 2
+};
+
+
+
+/**
+ * Constructs a new quad tree node.
+ * @param {number} x X-coordiate of node.
+ * @param {number} y Y-coordinate of node.
+ * @param {number} w Width of node.
+ * @param {number} h Height of node.
+ * @param {goog.structs.QuadTree.Node=} opt_parent Optional parent node.
+ * @constructor
+ */
+goog.structs.QuadTree.Node = function(x, y, w, h, opt_parent) {
+ /**
+ * The x-coordinate of the node.
+ * @type {number}
+ */
+ this.x = x;
+
+ /**
+ * The y-coordinate of the node.
+ * @type {number}
+ */
+ this.y = y;
+
+ /**
+ * The width of the node.
+ * @type {number}
+ */
+ this.w = w;
+
+ /**
+ * The height of the node.
+ * @type {number}
+ */
+ this.h = h;
+
+ /**
+ * The parent node.
+ * @type {goog.structs.QuadTree.Node?}
+ */
+ this.parent = opt_parent || null;
+};
+
+
+/**
+ * The node's type.
+ * @type {goog.structs.QuadTree.NodeType}
+ */
+goog.structs.QuadTree.Node.prototype.nodeType =
+ goog.structs.QuadTree.NodeType.EMPTY;
+
+
+/**
+ * The child node in the North-West quadrant.
+ * @type {goog.structs.QuadTree.Node?}
+ */
+goog.structs.QuadTree.Node.prototype.nw = null;
+
+
+/**
+ * The child node in the North-East quadrant.
+ * @type {goog.structs.QuadTree.Node?}
+ */
+goog.structs.QuadTree.Node.prototype.ne = null;
+
+
+/**
+ * The child node in the South-West quadrant.
+ * @type {goog.structs.QuadTree.Node?}
+ */
+goog.structs.QuadTree.Node.prototype.sw = null;
+
+
+/**
+ * The child node in the South-East quadrant.
+ * @type {goog.structs.QuadTree.Node?}
+ */
+goog.structs.QuadTree.Node.prototype.se = null;
+
+
+/**
+ * The point for the node, if it is a leaf node.
+ * @type {goog.structs.QuadTree.Point?}
+ */
+goog.structs.QuadTree.Node.prototype.point = null;
+
+
+
+/**
+ * Creates a new point object.
+ * @param {number} x The x-coordinate of the point.
+ * @param {number} y The y-coordinate of the point.
+ * @param {*=} opt_value Optional value associated with the point.
+ * @constructor
+ */
+goog.structs.QuadTree.Point = function(x, y, opt_value) {
+ /**
+ * The x-coordinate for the point.
+ * @type {number}
+ */
+ this.x = x;
+
+ /**
+ * The y-coordinate for the point.
+ * @type {number}
+ */
+ this.y = y;
+
+ /**
+ * Optional value associated with the point.
+ * @type {*}
+ */
+ this.value = goog.isDef(opt_value) ? opt_value : null;
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/quadtree_test.html b/contexts/data/lib/closure-library/closure/goog/structs/quadtree_test.html
new file mode 100644
index 0000000..c51e144
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/quadtree_test.html
@@ -0,0 +1,179 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2008 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs.QuadTree</title>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.array');
+ goog.require('goog.structs');
+ goog.require('goog.structs.QuadTree');
+ goog.require('goog.testing.jsunit');
+</script>
+</head>
+<body>
+<script>
+
+ function getTree() {
+ var qt = new goog.structs.QuadTree(0, 0, 100, 100);
+ qt.set(5, 20, 'Foo');
+ qt.set(50, 32, 'Bar');
+ qt.set(47, 96, 'Baz');
+ qt.set(50, 50, 'Bing');
+ qt.set(12, 0, 'Bong');
+ return qt;
+ }
+
+ function testGetCount() {
+ var qt = getTree();
+ assertEquals('Count should be 5', 5, qt.getCount());
+ qt.remove(50, 32);
+ assertEquals('Count should be 4', 4, qt.getCount());
+ }
+
+ function testGetKeys() {
+ var keys = getTree().getKeys();
+ var keyString = keys.sort().join(' ');
+ var expected = '(12, 0) (47, 96) (5, 20) (50, 32) (50, 50)';
+ assertEquals('Sorted keys should be ' + expected, expected, keyString);
+ }
+
+ function testGetValues() {
+ var values = getTree().getValues();
+ var valueString = values.sort().join(',');
+ assertEquals('Sorted values should be Bar,Baz,Bing,Bong,Foo',
+ 'Bar,Baz,Bing,Bong,Foo', valueString);
+ }
+
+ function testContains() {
+ var qt = getTree();
+ assertTrue('Should contain (5, 20)', qt.contains(5, 20));
+ assertFalse('Should not contain (13, 13)', qt.contains(13, 13));
+ }
+
+ function testClear() {
+ var qt = getTree();
+ qt.clear();
+ assertTrue('Tree should be empty', qt.isEmpty());
+ assertFalse('Tree should not contain (5, 20)', qt.contains(5, 20));
+ }
+
+ function testConstructor() {
+ var qt = new goog.structs.QuadTree(-10, -5, 6, 12);
+ var root = qt.getRootNode();
+ assertEquals('X of root should be -10', -10, root.x);
+ assertEquals('Y of root should be -5', -5, root.y);
+ assertEquals('Width of root should be 16', 16, root.w);
+ assertEquals('Height of root should be 17', 17, root.h);
+ assertTrue('Tree should be empty', qt.isEmpty());
+ }
+
+ function testClone() {
+ var qt = getTree().clone();
+ assertFalse('Clone should not be empty', qt.isEmpty());
+ assertTrue('Should contain (47, 96)', qt.contains(47, 96));
+ }
+
+ function testRemove() {
+ var qt = getTree();
+ assertEquals('(5, 20) should be removed', 'Foo', qt.remove(5, 20));
+ assertEquals('(5, 20) should be removed', 'Bar', qt.remove(50, 32));
+ assertEquals('(5, 20) should be removed', 'Baz', qt.remove(47, 96));
+ assertEquals('(5, 20) should be removed', 'Bing', qt.remove(50, 50));
+ assertEquals('(5, 20) should be removed', 'Bong', qt.remove(12, 0));
+ assertNull('(6, 6) wasn\'t there to remove', qt.remove(6, 6));
+ assertTrue('Tree should be empty', qt.isEmpty());
+ assertTreesChildrenAreNull(qt)
+ }
+
+ function testIsEmpty() {
+ var qt = getTree();
+ qt.clear();
+ assertTrue(qt.isEmpty());
+ assertEquals('Root should be empty node',
+ goog.structs.QuadTree.NodeType.EMPTY, qt.getRootNode().nodeType);
+ assertTreesChildrenAreNull(qt);
+ }
+
+ function testForEach() {
+ var qt = getTree();
+ var s = '';
+ goog.structs.forEach(qt, function(val, key, qt2) {
+ assertNotUndefined(key);
+ assertEquals(qt, qt2);
+ s += key.x + ',' + key.y + '=' + val + ' ';
+ });
+ assertEquals('50,32=Bar 50,50=Bing 47,96=Baz 5,20=Foo 12,0=Bong ', s);
+ }
+
+ function testBalancing() {
+ var qt = new goog.structs.QuadTree(0, 0, 100, 100);
+ var root = qt.getRootNode();
+
+ // Add a point to the NW quadrant.
+ qt.set(25, 25, 'first');
+
+ assertEquals('Root should be a leaf node.',
+ goog.structs.QuadTree.NodeType.LEAF, root.nodeType);
+ assertTreesChildrenAreNull(qt);
+
+ assertEquals('first', root.point.value);
+
+ // Add another point in the NW quadrant
+ qt.set(25, 30, 'second');
+
+ assertEquals('Root should now be a pointer.',
+ goog.structs.QuadTree.NodeType.POINTER, root.nodeType);
+ assertNotNull('NE should be not be null', root.ne);
+ assertNotNull('NW should be not be null', root.nw);
+ assertNotNull('SE should be not be null', root.se);
+ assertNotNull('SW should be not be null', root.sw);
+ assertNull(root.point);
+
+ // Delete the second point.
+ qt.remove(25, 30);
+
+ assertEquals('Root should have been rebalanced and be a leaf node.',
+ goog.structs.QuadTree.NodeType.LEAF, root.nodeType);
+ assertTreesChildrenAreNull(qt);
+ assertEquals('first', root.point.value);
+ }
+
+ function testTreeBounds() {
+ var qt = getTree();
+ assertFails(qt, qt.set, [-10, -10, 1]);
+ assertFails(qt, qt.set, [-10, 10, 2]);
+ assertFails(qt, qt.set, [10, -10, 3]);
+ assertFails(qt, qt.set, [-10, 110, 4]);
+ assertFails(qt, qt.set, [10, 130, 5]);
+ assertFails(qt, qt.set, [110, -10, 6]);
+ assertFails(qt, qt.set, [150, 14, 7]);
+ }
+
+ // Helper functions
+
+ function assertFails(context, fn, args) {
+ assertThrows('Exception expected from ' + fn.toString() +
+ ' with arguments ' + args,
+ function() {
+ fn.apply(context, args);
+ });
+ }
+
+ function assertTreesChildrenAreNull(qt) {
+ var root = qt.getRootNode();
+ assertNull('NE should be null', root.ne);
+ assertNull('NW should be null', root.nw);
+ assertNull('SE should be null', root.se);
+ assertNull('SW should be null', root.sw);
+ }
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/queue.js b/contexts/data/lib/closure-library/closure/goog/structs/queue.js
new file mode 100644
index 0000000..3be02f5
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/queue.js
@@ -0,0 +1,157 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Datastructure: Queue.
+ *
+ *
+ * This file provides the implementation of a FIFO Queue structure.
+ * API is similar to that of com.google.common.collect.IntQueue
+ */
+
+goog.provide('goog.structs.Queue');
+
+goog.require('goog.array');
+
+
+
+/**
+ * Class for FIFO Queue data structure.
+ *
+ * @constructor
+ */
+goog.structs.Queue = function() {
+ this.elements_ = [];
+};
+
+
+/**
+ * The index of the next element to be removed from the queue.
+ * @private
+ * @type {number}
+ */
+goog.structs.Queue.prototype.head_ = 0;
+
+
+/**
+ * The index at which the next element would be added to the queue.
+ * @private
+ * @type {number}
+ */
+goog.structs.Queue.prototype.tail_ = 0;
+
+
+/**
+ * Puts the specified element on this queue.
+ * @param {*} element The element to be added to the queue.
+ */
+goog.structs.Queue.prototype.enqueue = function(element) {
+ this.elements_[this.tail_++] = element;
+};
+
+
+/**
+ * Retrieves and removes the head of this queue.
+ * @return {*} The element at the head of this queue. Returns undefined if the
+ * queue is empty.
+ */
+goog.structs.Queue.prototype.dequeue = function() {
+ if (this.head_ == this.tail_) {
+ return undefined;
+ }
+ var result = this.elements_[this.head_];
+ delete this.elements_[this.head_];
+ this.head_++;
+ return result;
+};
+
+
+/**
+ * Retrieves but does not remove the head of this queue.
+ * @return {*} The element at the head of this queue. Returns undefined if the
+ * queue is empty.
+ */
+goog.structs.Queue.prototype.peek = function() {
+ if (this.head_ == this.tail_) {
+ return undefined;
+ }
+ return this.elements_[this.head_];
+};
+
+
+/**
+ * Returns the number of elements in this queue.
+ * @return {number} The number of elements in this queue.
+ */
+goog.structs.Queue.prototype.getCount = function() {
+ return this.tail_ - this.head_;
+};
+
+
+/**
+ * Returns true if this queue contains no elements.
+ * @return {boolean} true if this queue contains no elements.
+ */
+goog.structs.Queue.prototype.isEmpty = function() {
+ return this.tail_ - this.head_ == 0;
+};
+
+
+/**
+ * Removes all elements from the queue.
+ */
+goog.structs.Queue.prototype.clear = function() {
+ this.elements_.length = 0;
+ this.head_ = 0;
+ this.tail_ = 0;
+};
+
+
+/**
+ * Returns true if the given value is in the queue.
+ * @param {*} obj The value to look for.
+ * @return {boolean} Whether the object is in the queue.
+ */
+goog.structs.Queue.prototype.contains = function(obj) {
+ return goog.array.contains(this.elements_, obj);
+};
+
+
+/**
+ * Removes the first occurrence of a particular value from the queue.
+ * @param {*} obj Object to remove.
+ * @return {boolean} True if an element was removed.
+ */
+goog.structs.Queue.prototype.remove = function(obj) {
+ var index = goog.array.indexOf(this.elements_, obj);
+ if (index < 0) {
+ return false;
+ }
+ if (index == this.head_) {
+ this.dequeue();
+ } else {
+ goog.array.removeAt(this.elements_, index);
+ this.tail_--;
+ }
+ return true;
+};
+
+
+/**
+ * Returns all the values in the queue.
+ * @return {Array} An array of the values in the queue.
+ */
+goog.structs.Queue.prototype.getValues = function() {
+ return this.elements_.slice(this.head_, this.tail_);
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/queue_test.html b/contexts/data/lib/closure-library/closure/goog/structs/queue_test.html
new file mode 100644
index 0000000..bbfae75
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/queue_test.html
@@ -0,0 +1,140 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2006 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs.Queue</title>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.structs.Queue');
+ goog.require('goog.testing.jsunit');
+</script>
+</head>
+<body>
+<script>
+
+function stringifyQueue(q) {
+ var values = q.getValues();
+ var s = '';
+ for (var i = 0; i < values.length; i++) {
+ s += values[i];
+ }
+ return s;
+}
+
+function createQueue() {
+ var q = new goog.structs.Queue();
+ q.enqueue('a');
+ q.enqueue('b');
+ q.enqueue('c');
+ return q;
+}
+
+function testConstructor() {
+ var q = new goog.structs.Queue();
+ assertTrue('testConstructor(), queue should be empty initially', q.isEmpty());
+ assertEquals('testConstructor(), count should be 0', q.getCount(), 0);
+ assertEquals('testConstructor(), head element should be undefined', q.peek(),
+ undefined);
+}
+
+function testCount() {
+ var q = createQueue();
+ assertEquals('testCount(), count should be 3', q.getCount(), 3);
+ q.enqueue('d');
+ assertEquals('testCount(), count should be 4', q.getCount(), 4);
+ q.dequeue();
+ assertEquals('testCount(), count should be 3', q.getCount(), 3);
+ q.clear();
+ assertEquals('testCount(), count should be 0', q.getCount(), 0);
+}
+
+function testEnqueue() {
+ var q = new goog.structs.Queue();
+ q.enqueue('a');
+ assertEquals('testEnqueue(), count should be 1', q.getCount(), 1);
+ q.enqueue('b');
+ assertEquals('testEnqueue(), count should be 2', q.getCount(), 2);
+ assertEquals('testEnqueue(), head element should be a', q.peek(), 'a');
+ q.dequeue();
+ assertEquals('testEnqueue(), count should be 1', q.getCount(), 1);
+ assertEquals('testEnqueue(), head element should be b', q.peek(), 'b');
+}
+
+function testDequeue() {
+ var q = createQueue();
+ var head = q.dequeue();
+ assertEquals('testDequeue(), should return a', head, 'a');
+ q.dequeue();
+ head = q.dequeue();
+ assertEquals('testDequeue(), should return c', head, 'c');
+ assertTrue('testDequeue(), queue should be empty', q.isEmpty());
+ head = q.dequeue();
+ assertEquals('testDequeue(), should return undefined for empty queue', head,
+ undefined);
+}
+
+function testPeek() {
+ var q = createQueue();
+ var head = q.peek();
+ assertEquals('testPeek(), should return a', head, 'a');
+ var head2 = q.dequeue();
+ assertEquals('testPeek(), dequeue should return peek() result', head, head2);
+ head = q.peek();
+ assertEquals('testPeek(), should return b', head, 'b');
+ q.clear();
+ head = q.peek();
+ assertEquals('testPeek(), should return undefined for empty queue', head,
+ undefined);
+}
+
+function testClear() {
+ var q = createQueue();
+ q.clear();
+ assertTrue('testClear(), queue should be empty', q.isEmpty());
+}
+
+function testQueue() {
+ var q = createQueue();
+ assertEquals('testQueue(), contents must be abc', stringifyQueue(q), 'abc');
+}
+
+function testRemove() {
+ var q = createQueue();
+ assertEquals('testRemove(), contents must be abc', stringifyQueue(q), 'abc');
+
+ q.dequeue();
+ assertEquals('testRemove(), contents must be bc', stringifyQueue(q), 'bc');
+
+ q.enqueue('a');
+ assertEquals('testRemove(), contents must be bca', stringifyQueue(q), 'bca');
+
+ assertTrue('testRemove(), remove should have returned true', q.remove('c'));
+ assertEquals('testRemove(), contents must be ba', stringifyQueue(q), 'ba');
+
+ assertTrue('testRemove(), remove should have returned true', q.remove('b'));
+ assertEquals('testRemove(), contents must be a', stringifyQueue(q), 'a');
+
+ assertFalse('testRemove(), remove should have returned false', q.remove('b'));
+ assertEquals('testRemove(), contents must be a', stringifyQueue(q), 'a');
+
+ assertTrue('testRemove(), remove should have returned true', q.remove('a'));
+ assertEquals('testRemove(), contents must be empty', stringifyQueue(q), '');
+}
+
+function testContains() {
+ var q = createQueue();
+ assertTrue('testContains(), contains should have returned true',
+ q.contains('a'));
+ assertFalse('testContains(), contains should have returned false',
+ q.contains('foobar'));
+}
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/set.js b/contexts/data/lib/closure-library/closure/goog/structs/set.js
new file mode 100644
index 0000000..4719f6a
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/set.js
@@ -0,0 +1,255 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Datastructure: Set.
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ * @author pallosp@google.com (Peter Pallos)
+ *
+ * This class implements a set data structure. Adding and removing is O(1). It
+ * supports both object and primitive values. Be careful because you can add
+ * both 1 and new Number(1), because these are not the same. You can even add
+ * multiple new Number(1) because these are not equal.
+ */
+
+
+goog.provide('goog.structs.Set');
+
+goog.require('goog.structs');
+goog.require('goog.structs.Collection');
+goog.require('goog.structs.Map');
+
+
+
+/**
+ * A set that can contain both primitives and objects. Adding and removing
+ * elements is O(1). Primitives are treated as identical if they have the same
+ * type and convert to the same string. Objects are treated as identical only
+ * if they are references to the same object. WARNING: A goog.structs.Set can
+ * contain both 1 and (new Number(1)), because they are not the same. WARNING:
+ * Adding (new Number(1)) twice will yield two distinct elements, because they
+ * are two different objects. WARNING: Any object that is added to a
+ * goog.structs.Set will be modified! Because goog.getUid() is used to
+ * identify objects, every object in the set will be mutated.
+ * @param {Array|Object=} opt_values Initial values to start with.
+ * @constructor
+ * @implements {goog.structs.Collection}
+ */
+goog.structs.Set = function(opt_values) {
+ this.map_ = new goog.structs.Map;
+ if (opt_values) {
+ this.addAll(opt_values);
+ }
+};
+
+
+/**
+ * Obtains a unique key for an element of the set. Primitives will yield the
+ * same key if they have the same type and convert to the same string. Object
+ * references will yield the same key only if they refer to the same object.
+ * @param {*} val Object or primitive value to get a key for.
+ * @return {string} A unique key for this value/object.
+ * @private
+ */
+goog.structs.Set.getKey_ = function(val) {
+ var type = typeof val;
+ if (type == 'object' && val || type == 'function') {
+ return 'o' + goog.getUid(/** @type {Object} */ (val));
+ } else {
+ return type.substr(0, 1) + val;
+ }
+};
+
+
+/**
+ * @return {number} The number of elements in the set.
+ */
+goog.structs.Set.prototype.getCount = function() {
+ return this.map_.getCount();
+};
+
+
+/**
+ * Add a primitive or an object to the set.
+ * @param {*} element The primitive or object to add.
+ */
+goog.structs.Set.prototype.add = function(element) {
+ this.map_.set(goog.structs.Set.getKey_(element), element);
+};
+
+
+/**
+ * Adds all the values in the given collection to this set.
+ * @param {Array|Object} col A collection containing the elements to add.
+ */
+goog.structs.Set.prototype.addAll = function(col) {
+ var values = goog.structs.getValues(col);
+ var l = values.length;
+ for (var i = 0; i < l; i++) {
+ this.add(values[i]);
+ }
+};
+
+
+/**
+ * Removes all values in the given collection from this set.
+ * @param {Array|Object} col A collection containing the elements to remove.
+ */
+goog.structs.Set.prototype.removeAll = function(col) {
+ var values = goog.structs.getValues(col);
+ var l = values.length;
+ for (var i = 0; i < l; i++) {
+ this.remove(values[i]);
+ }
+};
+
+
+/**
+ * Removes the given element from this set.
+ * @param {*} element The primitive or object to remove.
+ * @return {boolean} Whether the element was found and removed.
+ */
+goog.structs.Set.prototype.remove = function(element) {
+ return this.map_.remove(goog.structs.Set.getKey_(element));
+};
+
+
+/**
+ * Removes all elements from this set.
+ */
+goog.structs.Set.prototype.clear = function() {
+ this.map_.clear();
+};
+
+
+/**
+ * Tests whether this set is empty.
+ * @return {boolean} True if there are no elements in this set.
+ */
+goog.structs.Set.prototype.isEmpty = function() {
+ return this.map_.isEmpty();
+};
+
+
+/**
+ * Tests whether this set contains the given element.
+ * @param {*} element The primitive or object to test for.
+ * @return {boolean} True if this set contains the given element.
+ */
+goog.structs.Set.prototype.contains = function(element) {
+ return this.map_.containsKey(goog.structs.Set.getKey_(element));
+};
+
+
+/**
+ * Tests whether this set contains all the values in a given collection.
+ * Repeated elements in the collection are ignored, e.g. (new
+ * goog.structs.Set([1, 2])).containsAll([1, 1]) is True.
+ * @param {Object} col A collection-like object.
+ * @return {boolean} True if the set contains all elements.
+ */
+goog.structs.Set.prototype.containsAll = function(col) {
+ return goog.structs.every(col, this.contains, this);
+};
+
+
+/**
+ * Finds all values that are present in both this set and the given collection.
+ * @param {Array|Object} col A collection.
+ * @return {!goog.structs.Set} A new set containing all the values (primitives
+ * or objects) present in both this set and the given collection.
+ */
+goog.structs.Set.prototype.intersection = function(col) {
+ var result = new goog.structs.Set();
+
+ var values = goog.structs.getValues(col);
+ for (var i = 0; i < values.length; i++) {
+ var value = values[i];
+ if (this.contains(value)) {
+ result.add(value);
+ }
+ }
+
+ return result;
+};
+
+
+/**
+ * Returns an array containing all the elements in this set.
+ * @return {!Array} An array containing all the elements in this set.
+ */
+goog.structs.Set.prototype.getValues = function() {
+ return this.map_.getValues();
+};
+
+
+/**
+ * Creates a shallow clone of this set.
+ * @return {!goog.structs.Set} A new set containing all the same elements as
+ * this set.
+ */
+goog.structs.Set.prototype.clone = function() {
+ return new goog.structs.Set(this);
+};
+
+
+/**
+ * Tests whether the given collection consists of the same elements as this set,
+ * regardless of order, without repetition. Primitives are treated as equal if
+ * they have the same type and convert to the same string; objects are treated
+ * as equal if they are references to the same object. This operation is O(n).
+ * @param {Object} col A collection.
+ * @return {boolean} True if the given collection consists of the same elements
+ * as this set, regardless of order, without repetition.
+ */
+goog.structs.Set.prototype.equals = function(col) {
+ return this.getCount() == goog.structs.getCount(col) && this.isSubsetOf(col);
+};
+
+
+/**
+ * Tests whether the given collection contains all the elements in this set.
+ * Primitives are treated as equal if they have the same type and convert to the
+ * same string; objects are treated as equal if they are references to the same
+ * object. This operation is O(n).
+ * @param {Object} col A collection.
+ * @return {boolean} True if this set is a subset of the given collection.
+ */
+goog.structs.Set.prototype.isSubsetOf = function(col) {
+ var colCount = goog.structs.getCount(col);
+ if (this.getCount() > colCount) {
+ return false;
+ }
+ // TODO(user) Find the minimal collection size where the conversion makes
+ // the contains() method faster.
+ if (!(col instanceof goog.structs.Set) && colCount > 5) {
+ // Convert to a goog.structs.Set so that goog.structs.contains runs in
+ // O(1) time instead of O(n) time.
+ col = new goog.structs.Set(col);
+ }
+ return goog.structs.every(this, function(value) {
+ return goog.structs.contains(col, value);
+ });
+};
+
+
+/**
+ * Returns an iterator that iterates over the elements in this set.
+ * @param {boolean=} opt_keys This argument is ignored.
+ * @return {!goog.iter.Iterator} An iterator over the elements in this set.
+ */
+goog.structs.Set.prototype.__iterator__ = function(opt_keys) {
+ return this.map_.__iterator__(false);
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/set_perf.html b/contexts/data/lib/closure-library/closure/goog/structs/set_perf.html
new file mode 100644
index 0000000..1b784bd
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/set_perf.html
@@ -0,0 +1,237 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2009 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<!--
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <title>Closure Performance Tests - goog.ui.Set vs goog.ui.StringSet</title>
+ <link rel="stylesheet" type="text/css" href="../testing/performancetable.css"/>
+ <script src="../base.js"></script>
+ <script>
+ goog.require('goog.functions');
+ goog.require('goog.string');
+ goog.require('goog.structs.Set');
+ goog.require('goog.structs.StringSet');
+ goog.require('goog.testing.PerformanceTable');
+ goog.require('goog.testing.PropertyReplacer');
+ goog.require('goog.testing.jsunit');
+ </script>
+</head>
+<body>
+ <h1>goog.ui.Set and goog.ui.StringSet Performance Tests</h1>
+ <p>
+ <strong>User-agent:</strong>
+ <script>document.write(navigator.userAgent);</script>
+ </p>
+ <div id="perfTable"></div>
+ <hr>
+
+ <script>
+ var table = new goog.testing.PerformanceTable(
+ goog.dom.getElement('perfTable'));
+
+ // Number of operations to measure in each table line.
+ var OPS_COUNT = 20000;
+
+ var stubs = new goog.testing.PropertyReplacer();
+
+ function tearDown() {
+ stubs.reset();
+ }
+
+ function testCreateSetFromArrayWithoutRepetition() {
+ var values = []
+ for (var i = 0; i < OPS_COUNT; i++) {
+ values.push(i);
+ }
+
+ table.run(function() {
+ var s = new goog.structs.StringSet(values);
+ }, 'Create string set from number array without repetition');
+
+ values = []
+ for (var i = 0; i < OPS_COUNT; i++) {
+ values.push(String(i));
+ }
+
+ table.run(function() {
+ var s = new goog.structs.StringSet(values);
+ }, 'Create string set from string array without repetition');
+ }
+
+ function testCreateSetWithoutRepetition() {
+ table.run(function() {
+ var s = new goog.structs.Set();
+ for (var i = 0; i < OPS_COUNT; i++) {
+ s.add(i);
+ }
+ }, 'Add elements to set without repetition');
+
+ table.run(function() {
+ var s = new goog.structs.StringSet();
+ for (var i = 0; i < OPS_COUNT; i++) {
+ s.add(i);
+ }
+ }, 'Add elements to string set without repetition');
+
+ stubs.set(goog.structs.StringSet.prototype, 'encode',
+ goog.functions.identity);
+ stubs.set(goog.structs.StringSet.prototype, 'decode',
+ goog.functions.identity);
+
+ table.run(function() {
+ var s = new goog.structs.StringSet();
+ for (var i = 0; i < OPS_COUNT; i++) {
+ s.add(i);
+ }
+ }, 'Add elements to string set without repetition and escaping');
+ }
+
+ function testCreateSetWithRepetition() {
+ table.run(function() {
+ var s = new goog.structs.Set();
+ for (var n = 0; n < 10 ; n++) {
+ for (var i = 0; i < OPS_COUNT / 10; i++) {
+ s.add(i);
+ }
+ }
+ }, 'Add elements to set with repetition');
+
+ table.run(function() {
+ var s = new goog.structs.StringSet();
+ for (var n = 0; n < 10; n++) {
+ for (var i = 0; i < OPS_COUNT / 10; i++) {
+ s.add(i);
+ }
+ }
+ }, 'Add elements to string set with repetition');
+ }
+
+ function testForEach() {
+ var bigSet = new goog.structs.Set;
+ var bigStringSet = new goog.structs.StringSet;
+ for (var i = 0; i < OPS_COUNT; i++) {
+ bigSet.add(i);
+ bigStringSet.add(i);
+ }
+
+ table.run(function() {
+ goog.structs.forEach(bigSet, goog.nullFunction);
+ }, 'Iterate over set with forEach');
+
+ table.run(function() {
+ goog.structs.forEach(bigStringSet, goog.nullFunction);
+ }, 'Iterate over string set with forEach');
+ }
+
+ function testForEachWithLargeKeys() {
+ var bigSet = new goog.structs.Set;
+ var bigStringSet = new goog.structs.StringSet;
+ for (var i = 0; i < OPS_COUNT / 100; i++) {
+ bigSet.add(goog.string.repeat(String(i), 1000));
+ bigStringSet.add(goog.string.repeat(String(i), 1000));
+ }
+
+ table.run(function() {
+ for (var i = 0; i < 100; i++) {
+ goog.structs.forEach(bigSet, goog.nullFunction);
+ }
+ }, 'Iterate over set of large strings with forEach');
+
+ table.run(function() {
+ for (var i = 0; i < 100; i++) {
+ goog.structs.forEach(bigStringSet, goog.nullFunction);
+ }
+ }, 'Iterate over string set of large strings with forEach');
+ }
+
+ function testAddRemove() {
+ table.run(function() {
+ var s = new goog.structs.Set();
+ for (var i = 0; i < OPS_COUNT / 2; i++) {
+ s.add(i);
+ }
+ for (var i = 0; i < OPS_COUNT / 2; i++) {
+ s.remove(i);
+ }
+ }, 'Add then remove elements from set');
+
+ table.run(function() {
+ var s = new goog.structs.StringSet();
+ for (var i = 0; i < OPS_COUNT / 2; i++) {
+ s.add(i);
+ }
+ for (var i = 0; i < OPS_COUNT / 2; i++) {
+ s.remove(i);
+ }
+ }, 'Add then remove elements from string set');
+ }
+
+ function testContains() {
+ var bigSet = new goog.structs.Set;
+ var bigStringSet = new goog.structs.StringSet;
+ var arr = [];
+ for (var i = 0; i < OPS_COUNT; i++) {
+ bigSet.add(i);
+ bigStringSet.add(i);
+ arr.push(i);
+ }
+
+ table.run(function() {
+ for (var i = 0; i < OPS_COUNT; i++) {
+ bigSet.contains(i);
+ }
+ }, 'Membership check for each element of set');
+
+ table.run(function() {
+ for (var i = 0; i < OPS_COUNT; i++) {
+ bigStringSet.contains(i);
+ }
+ }, 'Membership check for each element of string set with contains');
+
+ table.run(function() {
+ bigStringSet.containsArray(arr);
+ }, 'Membership check for each element of string set with containsArray');
+
+ stubs.set(goog.structs.StringSet.prototype, 'encode',
+ goog.functions.identity);
+ stubs.set(goog.structs.StringSet.prototype, 'decode',
+ goog.functions.identity);
+
+ table.run(function() {
+ for (var i = 0; i < OPS_COUNT; i++) {
+ bigStringSet.contains(i);
+ }
+ }, 'Membership check for each element of string set without escaping');
+ }
+
+ function testEquals() {
+ table.run(function() {
+ var s1 = new goog.structs.Set();
+ var s2 = new goog.structs.Set();
+ for (var i = 0; i < OPS_COUNT / 4; i++) {
+ s1.add(i);
+ s2.add(i);
+ }
+ s1.equals(s2);
+ }, 'Create then compare two sets');
+
+ table.run(function() {
+ var s1 = new goog.structs.StringSet();
+ var s2 = new goog.structs.StringSet();
+ for (var i = 0; i < OPS_COUNT / 4; i++) {
+ s1.add(i);
+ s2.add(i);
+ }
+ s1.equals(s2);
+ }, 'Create then compare two string sets');
+ }
+ </script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/set_test.html b/contexts/data/lib/closure-library/closure/goog/structs/set_test.html
new file mode 100644
index 0000000..aa3f587
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/set_test.html
@@ -0,0 +1,551 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2006 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs.Set</title>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.iter');
+ goog.require('goog.structs');
+ goog.require('goog.structs.Set');
+ goog.require('goog.testing.jsunit');
+</script>
+</head>
+<body>
+<script>
+
+var Set = goog.structs.Set;
+
+function stringifySet(s) {
+ return goog.structs.getValues(s).join('');
+}
+
+function testGetCount() {
+ var s = new Set;
+ var a = new String('a'); s.add(a);
+ var b = new String('b'); s.add(b);
+ var c = new String('c'); s.add(c);
+ assertEquals('count, should be 3', s.getCount(), 3);
+ var d = new String('d'); s.add(d);
+ assertEquals('count, should be 4', s.getCount(), 4);
+ s.remove(d);
+ assertEquals('count, should be 3', s.getCount(), 3);
+
+ s = new Set;
+ s.add('a');
+ s.add('b');
+ s.add('c');
+ assertEquals('count, should be 3', s.getCount(), 3);
+ s.add('d');
+ assertEquals('count, should be 4', s.getCount(), 4);
+ s.remove('d');
+ assertEquals('count, should be 3', s.getCount(), 3);
+}
+
+function testGetValues() {
+ var s = new Set;
+ var a = new String('a'); s.add(a);
+ var b = new String('b'); s.add(b);
+ var c = new String('c'); s.add(c);
+ var d = new String('d'); s.add(d);
+ assertEquals(s.getValues().join(''), 'abcd');
+
+ var s = new Set;
+ s.add('a');
+ s.add('b');
+ s.add('c');
+ s.add('d');
+ assertEquals(s.getValues().join(''), 'abcd');
+}
+
+function testContains() {
+ var s = new Set;
+ var a = new String('a'); s.add(a);
+ var b = new String('b'); s.add(b);
+ var c = new String('c'); s.add(c);
+ var d = new String('d'); s.add(d);
+ var e = new String('e');;
+
+ assertTrue("contains, Should contain 'a'", s.contains(a));
+ assertFalse("contains, Should not contain 'e'", s.contains(e));
+
+ s = new Set;
+ s.add('a');
+ s.add('b');
+ s.add('c');
+ s.add('d');
+
+ assertTrue("contains, Should contain 'a'", s.contains('a'));
+ assertFalse("contains, Should not contain 'e'", s.contains('e'));
+}
+
+function testContainsFunctionValue() {
+ var s = new Set;
+
+ var fn1 = function() {};
+
+ assertFalse(s.contains(fn1));
+ s.add(fn1);
+ assertTrue(s.contains(fn1));
+
+ var fn2 = function() {};
+
+ assertFalse(s.contains(fn2));
+ s.add(fn2);
+ assertTrue(s.contains(fn2));
+
+ assertEquals(s.getCount(), 2);
+}
+
+function testContainsAll() {
+ var set = new Set([1, 2, 3]);
+
+ assertTrue("{1, 2, 3} contains []", set.containsAll([]));
+ assertTrue("{1, 2, 3} contains [1]", set.containsAll([1]));
+ assertTrue("{1, 2, 3} contains [1, 1]", set.containsAll([1, 1]));
+ assertTrue("{1, 2, 3} contains [3, 2, 1]", set.containsAll([3, 2, 1]));
+ assertFalse("{1, 2, 3} doesn't contain [4]", set.containsAll([4]));
+ assertFalse("{1, 2, 3} doesn't contain [1, 4]", set.containsAll([1, 4]));
+
+ assertTrue("{1, 2, 3} contains {a: 1}", set.containsAll({a: 1}));
+ assertFalse("{1, 2, 3} doesn't contain {a: 4}", set.containsAll({a: 4}));
+
+ assertTrue("{1, 2, 3} contains {1}", set.containsAll(new Set([1])));
+ assertFalse("{1, 2, 3} doesn't contain {4}", set.containsAll(new Set([4])));
+}
+
+function testIntersection() {
+ var emptySet = new Set;
+
+ assertTrue('intersection of empty set and [] should be empty',
+ emptySet.intersection([]).isEmpty());
+ assertIntersection('intersection of 2 empty sets should be empty',
+ emptySet, new Set(), new Set());
+
+ var abcdSet = new Set();
+ abcdSet.add('a');
+ abcdSet.add('b');
+ abcdSet.add('c');
+ abcdSet.add('d');
+
+ assertTrue('intersection of populated set and [] should be empty',
+ abcdSet.intersection([]).isEmpty());
+ assertIntersection('intersection of 2 empty sets should be empty',
+ abcdSet, new Set(), new Set());
+
+ var bcSet = new Set(['b', 'c']);
+ assertIntersection('intersection of [a,b,c,d] and [b,c]',
+ abcdSet, bcSet, bcSet);
+
+ var bceSet = new Set(['b', 'c', 'e']);
+ assertIntersection('intersection of [a,b,c,d] and [b,c,e]',
+ abcdSet, bceSet, bcSet);
+}
+
+/**
+ * Helper function to assert intersection is commutative.
+ */
+function assertIntersection(msg, set1, set2, expectedIntersection) {
+ assertTrue(msg + ': set1->set2',
+ set1.intersection(set2).equals(expectedIntersection));
+ assertTrue(msg + ': set2->set1',
+ set2.intersection(set1).equals(expectedIntersection));
+}
+
+function testRemoveAll() {
+ assertRemoveAll('removeAll of empty set from empty set', [], [], []);
+ assertRemoveAll('removeAll of empty set from populated set',
+ ['a', 'b', 'c', 'd'], [], ['a', 'b', 'c', 'd']);
+ assertRemoveAll('removeAll of [a,d] from [a,b,c,d]',
+ ['a', 'b', 'c', 'd'], ['a', 'd'], ['b', 'c']);
+ assertRemoveAll('removeAll of [b,c] from [a,b,c,d]',
+ ['a', 'b', 'c', 'd'], ['b', 'c'], ['a', 'd']);
+ assertRemoveAll('removeAll of [b,c,e] from [a,b,c,d]',
+ ['a', 'b', 'c', 'd'], ['b', 'c', 'e'], ['a', 'd']);
+ assertRemoveAll('removeAll of [a,b,c,d] from [a,d]',
+ ['a', 'd'], ['a', 'b', 'c', 'd'], []);
+ assertRemoveAll('removeAll of [a,b,c,d] from [b,c]',
+ ['b', 'c'], ['a', 'b', 'c', 'd'], []);
+ assertRemoveAll('removeAll of [a,b,c,d] from [b,c,e]',
+ ['b', 'c', 'e'], ['a', 'b', 'c', 'd'], ['e']);
+}
+
+/**
+ * Helper function to test removeAll.
+ */
+function assertRemoveAll(msg, elements1, elements2, expectedResult) {
+ var set1 = new Set(elements1);
+ var set2 = new Set(elements2);
+ set1.removeAll(set2);
+
+ assertTrue(msg + ': set1 count increased after removeAll',
+ elements1.length >= set1.getCount());
+ assertEquals(msg + ': set2 count changed after removeAll',
+ elements2.length, set2.getCount());
+ assertTrue(msg + ': wrong set1 after removeAll', set1.equals(expectedResult));
+ assertIntersection(msg + ': non-empty intersection after removeAll',
+ set1, set2, []);
+}
+
+function testAdd() {
+ var s = new Set;
+ var a = new String('a');
+ var b = new String('b');
+ s.add(a);
+ assertTrue(s.contains(a));
+ s.add(b)
+ assertTrue(s.contains(b));
+
+ s = new Set;
+ s.add('a')
+ assertTrue(s.contains('a'));
+ s.add('b')
+ assertTrue(s.contains('b'));
+ s.add(null);
+ assertTrue('contains null', s.contains(null));
+ assertFalse('does not contain "null"', s.contains('null'));
+}
+
+
+function testClear() {
+ var s = new Set;
+ var a = new String('a'); s.add(a);
+ var b = new String('b'); s.add(b);
+ var c = new String('c'); s.add(c);
+ var d = new String('d'); s.add(d);
+ s.clear();
+ assertTrue('cleared so it should be empty', s.isEmpty());
+ assertTrue("cleared so it should not contain 'a' key", !s.contains(a));
+
+ s = new Set;
+ s.add('a');
+ s.add('b');
+ s.add('c');
+ s.add('d');
+ s.clear();
+ assertTrue('cleared so it should be empty', s.isEmpty());
+ assertTrue("cleared so it should not contain 'a' key", !s.contains('a'));
+}
+
+
+function testAddAll() {
+ var s = new Set;
+ var a = new String('a');
+ var b = new String('b');
+ var c = new String('c');
+ var d = new String('d');
+ s.addAll([a, b, c, d]);
+ assertTrue('addAll so it should not be empty', !s.isEmpty());
+ assertTrue("addAll so it should contain 'c' key", s.contains(c));
+
+ var s2 = new Set;
+ s2.addAll(s);
+ assertTrue('addAll so it should not be empty', !s2.isEmpty());
+ assertTrue("addAll so it should contain 'c' key", s2.contains(c));
+
+
+ s = new Set;
+ s.addAll(['a', 'b', 'c', 'd']);
+ assertTrue('addAll so it should not be empty', !s.isEmpty());
+ assertTrue("addAll so it should contain 'c' key", s.contains('c'));
+
+ s2 = new Set;
+ s2.addAll(s);
+ assertTrue('addAll so it should not be empty', !s2.isEmpty());
+ assertTrue("addAll so it should contain 'c' key", s2.contains('c'));
+}
+
+
+function testConstructor() {
+ var s = new Set;
+ var a = new String('a'); s.add(a);
+ var b = new String('b'); s.add(b);
+ var c = new String('c'); s.add(c);
+ var d = new String('d'); s.add(d);
+ var s2 = new Set(s);
+ assertFalse('constr with Set so it should not be empty', s2.isEmpty());
+ assertTrue('constr with Set so it should contain c', s2.contains(c));
+
+ s = new Set;
+ s.add('a');
+ s.add('b');
+ s.add('c');
+ s.add('d');
+ s2 = new Set(s);
+ assertFalse('constr with Set so it should not be empty', s2.isEmpty());
+ assertTrue('constr with Set so it should contain c', s2.contains('c'));
+}
+
+
+function testClone() {
+ var s = new Set;
+ var a = new String('a'); s.add(a);
+ var b = new String('b'); s.add(b);
+ var c = new String('c'); s.add(c);
+ var d = new String('d'); s.add(d);
+
+ var s2 = s.clone();
+ assertFalse('clone so it should not be empty', s2.isEmpty());
+ assertTrue("clone so it should contain 'c' key", s2.contains(c));
+
+ var s = new Set;
+ s.add('a');
+ s.add('b');
+ s.add('c');
+ s.add('d');
+
+ s2 = s.clone();
+ assertFalse('clone so it should not be empty', s2.isEmpty());
+ assertTrue("clone so it should contain 'c' key", s2.contains('c'));
+}
+
+
+/**
+ * Helper method for testEquals().
+ * @param {Object} a First element to use in the tests.
+ * @param {Object} b Second element to use in the tests.
+ * @param {Object} c Third element to use in the tests.
+ * @param {Object} d Fourth element to use in the tests.
+ */
+function helperForTestEquals(a, b, c, d) {
+ var s = new Set([a, b, c]);
+
+ assertTrue("set == itself", s.equals(s));
+ assertTrue("set == same set", s.equals(new Set([a, b, c])));
+ assertTrue("set == its clone", s.equals(s.clone()));
+ assertTrue("set == array of same elements", s.equals([a, b, c]));
+ assertTrue("set == array of same elements in different order",
+ s.equals([c, b, a]));
+
+ assertFalse("set != empty set", s.equals(new Set));
+ assertFalse("set != its subset", s.equals(new Set([a, c])));
+ assertFalse("set != its superset",
+ s.equals(new Set([a, b, c, d])));
+ assertFalse("set != different set",
+ s.equals(new Set([b, c, d])));
+ assertFalse("set != its subset as array", s.equals([a, c]));
+ assertFalse("set != its superset as array", s.equals([a, b, c, d]));
+ assertFalse("set != different set as array", s.equals([b, c, d]));
+ assertFalse("set != [a, b, c, c]", s.equals([a, b, c, c]));
+ assertFalse("set != [a, b, b]", s.equals([a, b, b]));
+ assertFalse("set != [a, a]", s.equals([a, a]));
+}
+
+
+function testEquals() {
+ helperForTestEquals(1, 2, 3, 4);
+ helperForTestEquals('a', 'b', 'c', 'd');
+ helperForTestEquals(new String('a'), new String('b'),
+ new String('c'), new String('d'));
+}
+
+
+/**
+ * Helper method for testIsSubsetOf().
+ * @param {Object} a First element to use in the tests.
+ * @param {Object} b Second element to use in the tests.
+ * @param {Object} c Third element to use in the tests.
+ * @param {Object} d Fourth element to use in the tests.
+ */
+function helperForTestIsSubsetOf(a, b, c, d) {
+ var s = new Set([a, b, c]);
+
+ assertTrue("set <= itself", s.isSubsetOf(s));
+ assertTrue("set <= same set",
+ s.isSubsetOf(new Set([a, b, c])));
+ assertTrue("set <= its clone", s.isSubsetOf(s.clone()));
+ assertTrue("set <= array of same elements", s.isSubsetOf([a, b, c]));
+ assertTrue("set <= array of same elements in different order",
+ s.equals([c, b, a]));
+
+ assertTrue("set <= Set([a, b, c, d])",
+ s.isSubsetOf(new Set([a, b, c, d])));
+ assertTrue("set <= [a, b, c, d]", s.isSubsetOf([a, b, c, d]));
+ assertTrue("set <= [a, b, c, c]", s.isSubsetOf([a, b, c, c]));
+
+ assertFalse("set !<= Set([a, b])",
+ s.isSubsetOf(new Set([a, b])));
+ assertFalse("set !<= [a, b]", s.isSubsetOf([a, b]));
+ assertFalse("set !<= Set([c, d])",
+ s.isSubsetOf(new Set([c, d])));
+ assertFalse("set !<= [c, d]", s.isSubsetOf([c, d]));
+ assertFalse("set !<= Set([a, c, d])",
+ s.isSubsetOf(new Set([a, c, d])));
+ assertFalse("set !<= [a, c, d]", s.isSubsetOf([a, c, d]));
+ assertFalse("set !<= [a, a, b]", s.isSubsetOf([a, a, b]));
+ assertFalse("set !<= [a, a, b, b]", s.isSubsetOf([a, a, b, b]));
+}
+
+
+function testIsSubsetOf() {
+ helperForTestIsSubsetOf(1, 2, 3, 4);
+ helperForTestIsSubsetOf('a', 'b', 'c', 'd');
+ helperForTestIsSubsetOf(new String('a'), new String('b'),
+ new String('c'), new String('d'));
+}
+
+
+function testForEach() {
+ var s = new Set;
+ var a = new String('a'); s.add(a);
+ var b = new String('b'); s.add(b);
+ var c = new String('c'); s.add(c);
+ var d = new String('d'); s.add(d);
+ var str = '';
+ goog.structs.forEach(s, function(val, key, set) {
+ assertUndefined(key);
+ assertEquals(s, set);
+ str += val;
+ });
+ assertEquals(str, 'abcd');
+
+ s = new Set;
+ s.add('a');
+ s.add('b');
+ s.add('c');
+ s.add('d');
+ str = '';
+ goog.structs.forEach(s, function(val, key, set) {
+ assertUndefined(key);
+ assertEquals(s, set);
+ str += val;
+ });
+ assertEquals(str, 'abcd');
+}
+
+
+function testFilter() {
+ var s = new Set;
+ var a = new Number(0); s.add(a);
+ var b = new Number(1); s.add(b);
+ var c = new Number(2); s.add(c);
+ var d = new Number(3); s.add(d);
+
+ var s2 = goog.structs.filter(s, function (val, key, set) {
+ assertUndefined(key);
+ assertEquals(s, set);
+ return val > 1;
+ });
+ assertEquals(stringifySet(s2), '23');
+
+ s = new Set;
+ s.add(0);
+ s.add(1);
+ s.add(2);
+ s.add(3);
+
+ s2 = goog.structs.filter(s, function (val, key, set) {
+ assertUndefined(key);
+ assertEquals(s, set);
+ return val > 1;
+ });
+ assertEquals(stringifySet(s2), '23');
+}
+
+
+function testSome() {
+ var s = new Set;
+ var a = new Number(0); s.add(a);
+ var b = new Number(1); s.add(b);
+ var c = new Number(2); s.add(c);
+ var d = new Number(3); s.add(d);
+
+ var b = goog.structs.some(s, function (val, key, s2) {
+ assertUndefined(key);
+ assertEquals(s, s2);
+ return val > 1;
+ });
+ assertTrue(b);
+ var b = goog.structs.some(s, function (val, key, s2) {
+ assertUndefined(key);
+ assertEquals(s, s2);
+ return val > 100;
+ });
+ assertFalse(b);
+
+ s = new Set;
+ s.add(0);
+ s.add(1);
+ s.add(2);
+ s.add(3);
+
+ b = goog.structs.some(s, function (val, key, s2) {
+ assertUndefined(key);
+ assertEquals(s, s2);
+ return val > 1;
+ });
+ assertTrue(b);
+ b = goog.structs.some(s, function (val, key, s2) {
+ assertUndefined(key);
+ assertEquals(s, s2);
+ return val > 100;
+ });
+ assertFalse(b);
+}
+
+
+function testEvery() {
+ var s = new Set;
+ var a = new Number(0); s.add(a);
+ var b = new Number(1); s.add(b);
+ var c = new Number(2); s.add(c);
+ var d = new Number(3); s.add(d);
+
+ var b = goog.structs.every(s, function (val, key, s2) {
+ assertUndefined(key);
+ assertEquals(s, s2);
+ return val >= 0;
+ });
+ assertTrue(b);
+ b = goog.structs.every(s, function (val, key, s2) {
+ assertUndefined(key);
+ assertEquals(s, s2);
+ return val > 1;
+ });
+ assertFalse(b);
+
+ s = new Set;
+ s.add(0);
+ s.add(1);
+ s.add(2);
+ s.add(3);
+
+ b = goog.structs.every(s, function (val, key, s2) {
+ assertUndefined(key);
+ assertEquals(s, s2);
+ return val >= 0;
+ });
+ assertTrue(b);
+ b = goog.structs.every(s, function (val, key, s2) {
+ assertUndefined(key);
+ assertEquals(s, s2);
+ return val > 1;
+ });
+ assertFalse(b);
+}
+
+function testIterator() {
+ var s = new Set;
+ s.add(0);
+ s.add(1);
+ s.add(2);
+ s.add(3);
+ s.add(4);
+
+ assertEquals('01234', goog.iter.join(s, ''));
+
+ s.remove(1);
+ s.remove(3);
+
+ assertEquals('024', goog.iter.join(s, ''));
+}
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/simplepool.js b/contexts/data/lib/closure-library/closure/goog/structs/simplepool.js
new file mode 100644
index 0000000..3c13e0a
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/simplepool.js
@@ -0,0 +1,205 @@
+// Copyright 2007 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Datastructure: Pool.
+ *
+ *
+ * A generic class for handling pools of objects that is more efficient than
+ * goog.structs.Pool because it doesn't maintain a list of objects that are in
+ * use. See constructor comment.
+ */
+
+
+goog.provide('goog.structs.SimplePool');
+
+goog.require('goog.Disposable');
+
+
+
+/**
+ * A generic pool class. Simpler and more efficient than goog.structs.Pool
+ * because it doesn't maintain a list of objects that are in use. This class
+ * has constant overhead and doesn't create any additional objects as part of
+ * the pool management after construction time.
+ *
+ * IMPORTANT: If the objects being pooled are arrays or maps that can have
+ * unlimited number of properties, they need to be cleaned before being
+ * returned to the pool.
+ *
+ * Also note that {@see goog.object.clean} actually allocates an array to clean
+ * the object passed to it, so simply using this function would defy the
+ * purpose of using the pool.
+ *
+ * @param {number} initialCount Initial number of objects to populate the
+ * free pool at construction time.
+ * @param {number} maxCount Maximum number of objects to keep in the free pool.
+ * @constructor
+ * @extends {goog.Disposable}
+ */
+goog.structs.SimplePool = function(initialCount, maxCount) {
+ goog.Disposable.call(this);
+
+ /**
+ * Maximum number of objects allowed
+ * @type {number}
+ * @private
+ */
+ this.maxCount_ = maxCount;
+
+ /**
+ * Queue used to store objects that are currently in the pool and available
+ * to be used.
+ * @type {Array}
+ * @private
+ */
+ this.freeQueue_ = [];
+
+ this.createInitial_(initialCount);
+};
+goog.inherits(goog.structs.SimplePool, goog.Disposable);
+
+
+/**
+ * Function for overriding createObject. The avoids a common case requiring
+ * subclassing this class.
+ * @type {Function}
+ * @private
+ */
+goog.structs.SimplePool.prototype.createObjectFn_ = null;
+
+
+/**
+ * Function for overriding disposeObject. The avoids a common case requiring
+ * subclassing this class.
+ * @type {Function}
+ * @private
+ */
+goog.structs.SimplePool.prototype.disposeObjectFn_ = null;
+
+
+/**
+ * Sets the {@code createObject} function which is used for creating a new
+ * object in the pool.
+ * @param {Function} createObjectFn Create object function which returns the
+ * newly createrd object.
+ */
+goog.structs.SimplePool.prototype.setCreateObjectFn = function(createObjectFn) {
+ this.createObjectFn_ = createObjectFn;
+};
+
+
+/**
+ * Sets the {@code disposeObject} function which is used for disposing of an
+ * object in the pool.
+ * @param {Function} disposeObjectFn Dispose object function which takes the
+ * object to dispose as a parameter.
+ */
+goog.structs.SimplePool.prototype.setDisposeObjectFn = function(
+ disposeObjectFn) {
+ this.disposeObjectFn_ = disposeObjectFn;
+};
+
+
+/**
+ * Gets an unused object from the the pool, if there is one available,
+ * otherwise creates a new one.
+ * @return {*} An object from the pool or a new one if necessary.
+ */
+goog.structs.SimplePool.prototype.getObject = function() {
+ if (this.freeQueue_.length) {
+ return this.freeQueue_.pop();
+ }
+ return this.createObject();
+};
+
+
+/**
+ * Returns an object to the pool so that it can be reused. If the pool is
+ * already full, the object is disposed instead.
+ * @param {*} obj The object to release.
+ */
+goog.structs.SimplePool.prototype.releaseObject = function(obj) {
+ if (this.freeQueue_.length < this.maxCount_) {
+ this.freeQueue_.push(obj);
+ } else {
+ this.disposeObject(obj);
+ }
+};
+
+
+/**
+ * Populates the pool with initialCount objects.
+ * @param {number} initialCount The number of objects to add to the pool.
+ * @private
+ */
+goog.structs.SimplePool.prototype.createInitial_ = function(initialCount) {
+ if (initialCount > this.maxCount_) {
+ throw Error('[goog.structs.SimplePool] Initial cannot be greater than max');
+ }
+ for (var i = 0; i < initialCount; i++) {
+ this.freeQueue_.push(this.createObject());
+ }
+};
+
+
+/**
+ * Should be overriden by sub-classes to return an instance of the object type
+ * that is expected in the pool.
+ * @return {*} The created object.
+ */
+goog.structs.SimplePool.prototype.createObject = function() {
+ if (this.createObjectFn_) {
+ return this.createObjectFn_();
+ } else {
+ return {};
+ }
+};
+
+
+/**
+ * Should be overriden to dispose of an object. Default implementation is to
+ * remove all of the object's members, which should render it useless. Calls the
+ * object's dispose method, if available.
+ * @param {*} obj The object to dispose.
+ */
+goog.structs.SimplePool.prototype.disposeObject = function(obj) {
+ if (this.disposeObjectFn_) {
+ this.disposeObjectFn_(obj);
+ } else if (goog.isObject(obj)) {
+ if (goog.isFunction(obj.dispose)) {
+ obj.dispose();
+ } else {
+ for (var i in obj) {
+ delete obj[i];
+ }
+ }
+ }
+};
+
+
+/**
+ * Disposes of the pool and all objects currently held in the pool.
+ * @override
+ * @protected
+ */
+goog.structs.SimplePool.prototype.disposeInternal = function() {
+ goog.structs.SimplePool.superClass_.disposeInternal.call(this);
+ // Call disposeObject on each object held by the pool.
+ var freeQueue = this.freeQueue_;
+ while (freeQueue.length) {
+ this.disposeObject(freeQueue.pop());
+ }
+ delete this.freeQueue_;
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/stringset.js b/contexts/data/lib/closure-library/closure/goog/structs/stringset.js
new file mode 100644
index 0000000..c95ad8c
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/stringset.js
@@ -0,0 +1,404 @@
+// Copyright 2009 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Data structure for set of strings.
+ *
+ *
+ * This class implements a set data structure for strings. Adding and removing
+ * is O(1). It doesn't contain any bloat from {@link goog.structs.Set}, i.e.
+ * it isn't optimized for IE6 garbage collector (see the description of
+ * {@link goog.structs.Map#keys_} for details), and it distinguishes its
+ * elements by their string value not by hash code.
+ */
+
+goog.provide('goog.structs.StringSet');
+
+goog.require('goog.iter');
+
+
+
+/**
+ * Creates a set of strings.
+ * @param {!Array=} opt_elements Elements to add to the set. The non-string
+ * items will be converted to strings, so 15 and '15' will mean the same.
+ * @constructor
+ */
+goog.structs.StringSet = function(opt_elements) {
+ /**
+ * An object storing the escaped elements of the set in its keys.
+ * @type {!Object}
+ * @private
+ */
+ this.elements_ = {};
+
+ if (opt_elements) {
+ for (var i = 0; i < opt_elements.length; i++) {
+ this.elements_[this.encode(opt_elements[i])] = null;
+ }
+ }
+};
+
+
+/**
+ * Empty object. Referring to it is faster than creating a new empty object in
+ * {@link #encode}.
+ * @type {Object}
+ * @private
+ */
+goog.structs.StringSet.EMPTY_OBJECT_ = {};
+
+
+/**
+ * The '__proto__' and the '__count__' keys aren't enumerable in Firefox, and
+ * 'toString', 'valueOf', 'constructor', etc. aren't enumerable in IE so they
+ * have to be escaped before they are added to the internal object.
+ * NOTE: When a new set is created, 50-80% of the CPU time is spent in encode.
+ * @param {*} element The element to escape.
+ * @return {*} The escaped element or the element itself if it doesn't have to
+ * be escaped.
+ * @protected
+ */
+goog.structs.StringSet.prototype.encode = function(element) {
+ return element in goog.structs.StringSet.EMPTY_OBJECT_ ||
+ String(element).charCodeAt(0) == 32 ? ' ' + element : element;
+};
+
+
+/**
+ * Inverse function of {@link #encode}.
+ * NOTE: forEach would be 30% faster in FF if the compiler inlined decode.
+ * @param {string} key The escaped element used as the key of the internal
+ * object.
+ * @return {string} The unescaped element.
+ * @protected
+ */
+goog.structs.StringSet.prototype.decode = function(key) {
+ return key.charCodeAt(0) == 32 ? key.substr(1) : key;
+};
+
+
+/**
+ * Adds a single element to the set.
+ * @param {*} element The element to add. It will be converted to string.
+ */
+goog.structs.StringSet.prototype.add = function(element) {
+ this.elements_[this.encode(element)] = null;
+};
+
+
+/**
+ * Adds a the elements of an array to this set.
+ * @param {!Array} arr The array to add the elements of.
+ */
+goog.structs.StringSet.prototype.addArray = function(arr) {
+ for (var i = 0; i < arr.length; i++) {
+ this.elements_[this.encode(arr[i])] = null;
+ }
+};
+
+
+/**
+ * Adds the elements which are in {@code set1} but not in {@code set2} to this
+ * set.
+ * @param {!goog.structs.StringSet} set1 First set.
+ * @param {!goog.structs.StringSet} set2 Second set.
+ * @private
+ */
+goog.structs.StringSet.prototype.addDifference_ = function(set1, set2) {
+ for (var key in set1.elements_) {
+ if (set1.elements_.hasOwnProperty(key) &&
+ !set2.elements_.hasOwnProperty(key)) {
+ this.elements_[key] = null;
+ }
+ }
+};
+
+
+/**
+ * Adds a the elements of a set to this set.
+ * @param {!goog.structs.StringSet} stringSet The set to add the elements of.
+ */
+goog.structs.StringSet.prototype.addSet = function(stringSet) {
+ for (var key in stringSet.elements_) {
+ if (stringSet.elements_.hasOwnProperty(key)) {
+ this.elements_[key] = null;
+ }
+ }
+};
+
+
+/**
+ * Removes all elements of the set.
+ */
+goog.structs.StringSet.prototype.clear = function() {
+ this.elements_ = {};
+};
+
+
+/**
+ * @return {!goog.structs.StringSet} Clone of the set.
+ */
+goog.structs.StringSet.prototype.clone = function() {
+ var ret = new goog.structs.StringSet;
+ ret.addSet(this);
+ return ret;
+};
+
+
+/**
+ * Tells if the set contains the given element.
+ * @param {*} element The element to check.
+ * @return {boolean} Whether it is in the set.
+ */
+goog.structs.StringSet.prototype.contains = function(element) {
+ return this.elements_.hasOwnProperty(this.encode(element));
+};
+
+
+/**
+ * Tells if the set contains all elements of the array.
+ * @param {!Array} arr The elements to check.
+ * @return {boolean} Whether they are in the set.
+ */
+goog.structs.StringSet.prototype.containsArray = function(arr) {
+ for (var i = 0; i < arr.length; i++) {
+ if (!this.elements_.hasOwnProperty(this.encode(arr[i]))) {
+ return false;
+ }
+ }
+ return true;
+};
+
+
+/**
+ * Tells if this set has the same elements as the given set.
+ * @param {!goog.structs.StringSet} stringSet The other set.
+ * @return {boolean} Whether they have the same elements.
+ */
+goog.structs.StringSet.prototype.equals = function(stringSet) {
+ return this.isSubsetOf(stringSet) && stringSet.isSubsetOf(this);
+};
+
+
+/**
+ * Calls a function for each element in the set.
+ * @param {function(string, undefined, !goog.structs.StringSet)} f The function
+ * to call for every element. It takes the element, undefined (because sets
+ * have no notion of keys), and the set.
+ * @param {Object=} opt_obj The object to be used as the value of 'this'
+ * within {@code f}.
+ */
+goog.structs.StringSet.prototype.forEach = function(f, opt_obj) {
+ for (var key in this.elements_) {
+ if (this.elements_.hasOwnProperty(key)) {
+ f.call(opt_obj, this.decode(key), undefined, this);
+ }
+ }
+};
+
+
+/**
+ * Counts the number of elements in the set in linear time.
+ * NOTE: getCount is always called at most once per set instance in google3.
+ * If this usage pattern won't change, the linear getCount implementation is
+ * better, because
+ * <li>populating a set and getting the number of elements in it takes the same
+ * amount of time as keeping a count_ member up to date and getting its value;
+ * <li>if getCount is not called, adding and removing elements have no overhead.
+ * @return {number} The number of elements in the set.
+ */
+goog.structs.StringSet.prototype.getCount = function() {
+ var count = 0;
+ for (var key in this.elements_) {
+ if (this.elements_.hasOwnProperty(key)) {
+ count++;
+ }
+ }
+ return count;
+};
+
+
+/**
+ * Calculates the difference of two sets.
+ * @param {!goog.structs.StringSet} stringSet The set to subtract from this set.
+ * @return {!goog.structs.StringSet} {@code this} minus {@code stringSet}.
+ */
+goog.structs.StringSet.prototype.getDifference = function(stringSet) {
+ var ret = new goog.structs.StringSet;
+ ret.addDifference_(this, stringSet);
+ return ret;
+};
+
+
+/**
+ * Calculates the intersection of this set with another set.
+ * @param {!goog.structs.StringSet} stringSet The set to take the intersection
+ * with.
+ * @return {!goog.structs.StringSet} A new set with the common elements.
+ */
+goog.structs.StringSet.prototype.getIntersection = function(stringSet) {
+ var ret = new goog.structs.StringSet;
+ for (var key in this.elements_) {
+ if (stringSet.elements_.hasOwnProperty(key) &&
+ this.elements_.hasOwnProperty(key)) {
+ ret.elements_[key] = null;
+ }
+ }
+ return ret;
+};
+
+
+/**
+ * Calculates the symmetric difference of two sets.
+ * @param {!goog.structs.StringSet} stringSet The other set.
+ * @return {!goog.structs.StringSet} A new set with the elements in exactly one
+ * of {@code this} and {@code stringSet}.
+ */
+goog.structs.StringSet.prototype.getSymmetricDifference = function(stringSet) {
+ var ret = new goog.structs.StringSet;
+ ret.addDifference_(this, stringSet);
+ ret.addDifference_(stringSet, this);
+ return ret;
+};
+
+
+/**
+ * Calculates the union of this set and another set.
+ * @param {!goog.structs.StringSet} stringSet The set to take the union with.
+ * @return {!goog.structs.StringSet} A new set with the union of elements.
+ */
+goog.structs.StringSet.prototype.getUnion = function(stringSet) {
+ var ret = this.clone();
+ ret.addSet(stringSet);
+ return ret;
+};
+
+
+/**
+ * @return {!Array.<string>} The elements of the set.
+ */
+goog.structs.StringSet.prototype.getValues = function() {
+ var ret = [];
+ for (var key in this.elements_) {
+ if (this.elements_.hasOwnProperty(key)) {
+ ret.push(this.decode(key));
+ }
+ }
+ return ret;
+};
+
+
+/**
+ * Tells if this set and the given set are disjoint.
+ * @param {!goog.structs.StringSet} stringSet The other set.
+ * @return {boolean} True iff they don't have common elements.
+ */
+goog.structs.StringSet.prototype.isDisjoint = function(stringSet) {
+ for (var key in this.elements_) {
+ if (stringSet.elements_.hasOwnProperty(key) &&
+ this.elements_.hasOwnProperty(key)) {
+ return false;
+ }
+ }
+ return true;
+};
+
+
+/**
+ * @return {boolean} Whether the set is empty.
+ */
+goog.structs.StringSet.prototype.isEmpty = function() {
+ for (var key in this.elements_) {
+ if (this.elements_.hasOwnProperty(key)) {
+ return false;
+ }
+ }
+ return true;
+};
+
+
+/**
+ * Tells if this set is the subset of the given set.
+ * @param {!goog.structs.StringSet} stringSet The other set.
+ * @return {boolean} Whether this set if the subset of that.
+ */
+goog.structs.StringSet.prototype.isSubsetOf = function(stringSet) {
+ for (var key in this.elements_) {
+ if (!stringSet.elements_.hasOwnProperty(key) &&
+ this.elements_.hasOwnProperty(key)) {
+ return false;
+ }
+ }
+ return true;
+};
+
+
+/**
+ * Tells if this set is the superset of the given set.
+ * @param {!goog.structs.StringSet} stringSet The other set.
+ * @return {boolean} Whether this set if the superset of that.
+ */
+goog.structs.StringSet.prototype.isSupersetOf = function(stringSet) {
+ return this.isSubsetOf.call(stringSet, this);
+};
+
+
+/**
+ * Removes a single element from the set.
+ * @param {*} element The element to remove.
+ * @return {boolean} Whether the element was in the set.
+ */
+goog.structs.StringSet.prototype.remove = function(element) {
+ var key = this.encode(element);
+ if (this.elements_.hasOwnProperty(key)) {
+ delete this.elements_[key];
+ return true;
+ }
+ return false;
+};
+
+
+/**
+ * Removes all elements of the given array from this set.
+ * @param {!Array} arr The elements to remove.
+ */
+goog.structs.StringSet.prototype.removeArray = function(arr) {
+ for (var i = 0; i < arr.length; i++) {
+ delete this.elements_[this.encode(arr[i])];
+ }
+};
+
+
+/**
+ * Removes all elements of the given set from this set.
+ * @param {!goog.structs.StringSet} stringSet The set of elements to remove.
+ */
+goog.structs.StringSet.prototype.removeSet = function(stringSet) {
+ for (var key in stringSet.elements_) {
+ delete this.elements_[key];
+ }
+};
+
+
+/**
+ * Returns an iterator that iterates over the elements in the set.
+ * NOTE: creating the iterator copies the whole set so use {@link #forEach} when
+ * possible.
+ * @param {boolean=} opt_keys Ignored for sets.
+ * @return {!goog.iter.Iterator} An iterator over the elements in the set.
+ */
+goog.structs.StringSet.prototype.__iterator__ = function(opt_keys) {
+ return goog.iter.toIterator(this.getValues());
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/stringset_test.html b/contexts/data/lib/closure-library/closure/goog/structs/stringset_test.html
new file mode 100644
index 0000000..804e5eb
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/stringset_test.html
@@ -0,0 +1,251 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2009 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<!--
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs.StringSet</title>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.array');
+ goog.require('goog.iter');
+ goog.require('goog.structs.StringSet');
+ goog.require('goog.testing.asserts');
+ goog.require('goog.testing.jsunit');
+</script>
+</head>
+<body>
+<script>
+
+// Test how overwritten object prototype affects StringSet.
+Object.prototype.evil1 = null;
+Object.prototype.evil2 = null;
+
+var TEST_VALUES = [
+ '', ' ', ' ', 'true', 'null', 'undefined', '0', 'new', 'constructor',
+ 'prototype', '__proto__', 'set', 'hasOwnProperty', 'toString', 'valueOf',
+ 'evil1'
+];
+
+var TEST_VALUES_WITH_DUPLICATES = [
+ '', '', ' ', ' ', 'true', true, 'null', null, 'undefined', undefined, '0', 0,
+ 'new', 'constructor', 'prototype', '__proto__', 'set', 'hasOwnProperty',
+ 'toString', 'valueOf', 'evil1'
+];
+
+function testConstructor() {
+ var empty = new goog.structs.StringSet;
+ assertSameElements('elements in empty set', [], empty.getValues());
+
+ var s = new goog.structs.StringSet(TEST_VALUES_WITH_DUPLICATES);
+ assertSameElements('duplicates are filtered out by their string value',
+ TEST_VALUES, s.getValues());
+}
+
+function testAdd() {
+ var s = new goog.structs.StringSet;
+ goog.array.forEach(TEST_VALUES_WITH_DUPLICATES, s.add, s);
+ assertSameElements(TEST_VALUES, s.getValues());
+}
+
+function testAddArray() {
+ var s = new goog.structs.StringSet;
+ s.addArray(TEST_VALUES_WITH_DUPLICATES);
+ assertSameElements('added elements from array', TEST_VALUES, s.getValues());
+}
+
+function testAddSet() {
+ var s = new goog.structs.StringSet;
+ s.addSet(new goog.structs.StringSet([1, 2]));
+ assertSameElements('empty set + {1, 2}', ['1', '2'], s.getValues());
+ s.addSet(new goog.structs.StringSet([2, 3]));
+ assertSameElements('{1, 2} + {2, 3}', ['1', '2', '3'], s.getValues());
+}
+
+function testClear() {
+ var s = new goog.structs.StringSet([1, 2]);
+ s.clear();
+ assertSameElements('cleared set', [], s.getValues());
+}
+
+function testClone() {
+ var s = new goog.structs.StringSet([1, 2]);
+ var c = s.clone();
+ assertSameElements('elements in clone', ['1', '2'], c.getValues());
+ s.add(3);
+ assertSameElements('changing the original set does not affect the clone',
+ ['1', '2'], c.getValues());
+}
+
+function testContains() {
+ var e = new goog.structs.StringSet;
+ goog.array.forEach(TEST_VALUES, function(element) {
+ assertFalse('empty set does not contain ' + element, e.contains(element));
+ });
+
+ var s = new goog.structs.StringSet(TEST_VALUES);
+ goog.array.forEach(TEST_VALUES_WITH_DUPLICATES, function(element) {
+ assertTrue('s contains ' + element, s.contains(element));
+ });
+ assertFalse('s does not contain 42', s.contains(42));
+
+ Object.prototype[' a'] = 'a';
+ Object.prototype[' a'] = 'a';
+ assertFalse('empty set does not contain elements defined in Object.prototype',
+ new goog.structs.StringSet().contains(' a'));
+}
+
+function testContainsArray() {
+ var s = new goog.structs.StringSet(TEST_VALUES);
+ assertTrue('set contains empty array', s.containsArray([]));
+ assertTrue('set contains all elements of itself with some duplication',
+ s.containsArray(TEST_VALUES_WITH_DUPLICATES));
+ assertFalse('set does not contain 42', s.containsArray([42]));
+}
+
+function testEquals() {
+ var s = new goog.structs.StringSet([1, 2]);
+ assertTrue('set equals to itself', s.equals(s));
+ assertTrue('set equals to its clone', s.equals(s.clone()));
+ assertFalse('set does not equal to its subset',
+ s.equals(new goog.structs.StringSet([1])));
+ assertFalse('set does not equal to its superset',
+ s.equals(new goog.structs.StringSet([1, 2, 3])));
+}
+
+function testForEach() {
+ var s = new goog.structs.StringSet(TEST_VALUES);
+ var values = [];
+ var context = {};
+ s.forEach(function(value, key, stringSet) {
+ assertEquals('context of forEach callback', context, this);
+ values.push(value);
+ assertUndefined('key argument of forEach callback', key);
+ assertEquals('set argument of forEach callback', s, stringSet);
+ }, context);
+ assertSameElements('values passed to forEach callback', TEST_VALUES, values);
+}
+
+function testGetCount() {
+ var empty = new goog.structs.StringSet;
+ assertEquals('count(empty set)', 0, empty.getCount());
+
+ var s = new goog.structs.StringSet(TEST_VALUES);
+ assertEquals('count(non-empty set)', TEST_VALUES.length, s.getCount());
+}
+
+function testGetDifference() {
+ var s1 = new goog.structs.StringSet([1, 2]);
+ var s2 = new goog.structs.StringSet([2, 3]);
+ assertSameElements('{1, 2} - {2, 3}', ['1'],
+ s1.getDifference(s2).getValues());
+}
+
+function testGetIntersection() {
+ var s1 = new goog.structs.StringSet([1, 2]);
+ var s2 = new goog.structs.StringSet([2, 3]);
+ assertSameElements('{1, 2} * {2, 3}', ['2'],
+ s1.getIntersection(s2).getValues());
+}
+
+function testGetSymmetricDifference() {
+ var s1 = new goog.structs.StringSet([1, 2]);
+ var s2 = new goog.structs.StringSet([2, 3]);
+ assertSameElements('{1, 2} sym.diff. {2, 3}', ['1', '3'],
+ s1.getSymmetricDifference(s2).getValues());
+}
+
+function testGetUnion() {
+ var s1 = new goog.structs.StringSet([1, 2]);
+ var s2 = new goog.structs.StringSet([2, 3]);
+ assertSameElements('{1, 2} + {2, 3}', ['1', '2', '3'],
+ s1.getUnion(s2).getValues());
+}
+
+function testIsDisjoint() {
+ var s = new goog.structs.StringSet;
+ var s12 = new goog.structs.StringSet([1, 2]);
+ var s23 = new goog.structs.StringSet([2, 3]);
+ var s34 = new goog.structs.StringSet([3, 4]);
+
+ assertTrue('{} and {1, 2} are disjoint', s.isDisjoint(s12));
+ assertTrue('{1, 2} and {3, 4} are disjoint', s12.isDisjoint(s34));
+ assertFalse('{1, 2} and {2, 3} are not disjoint', s12.isDisjoint(s23));
+}
+
+function testIsEmpty() {
+ assertTrue('empty set', new goog.structs.StringSet().isEmpty());
+ assertFalse('non-empty set', new goog.structs.StringSet(['']).isEmpty());
+}
+
+function testIsSubsetOf() {
+ var s1 = new goog.structs.StringSet([1]);
+ var s12 = new goog.structs.StringSet([1, 2]);
+ var s123 = new goog.structs.StringSet([1, 2, 3]);
+ var s23 = new goog.structs.StringSet([2, 3]);
+
+ assertTrue('{1, 2} is subset of {1, 2}', s12.isSubsetOf(s12));
+ assertTrue('{1, 2} is subset of {1, 2, 3}', s12.isSubsetOf(s123));
+ assertFalse('{1, 2} is not subset of {1}', s12.isSubsetOf(s1));
+ assertFalse('{1, 2} is not subset of {2, 3}', s12.isSubsetOf(s23));
+}
+
+function testIsSupersetOf() {
+ var s1 = new goog.structs.StringSet([1]);
+ var s12 = new goog.structs.StringSet([1, 2]);
+ var s123 = new goog.structs.StringSet([1, 2, 3]);
+ var s23 = new goog.structs.StringSet([2, 3]);
+
+ assertTrue('{1, 2} is superset of {1}', s12.isSupersetOf(s1));
+ assertTrue('{1, 2} is superset of {1, 2}', s12.isSupersetOf(s12));
+ assertFalse('{1, 2} is not superset of {1, 2, 3}', s12.isSupersetOf(s123));
+ assertFalse('{1, 2} is not superset of {2, 3}', s12.isSupersetOf(s23));
+}
+
+function testRemove() {
+ var n = new goog.structs.StringSet([1, 2]);
+ assertFalse('3 not removed from {1, 2}', n.remove(3));
+ assertSameElements('set == {1, 2}', ['1', '2'], n.getValues());
+ assertTrue('2 removed from {1, 2}', n.remove(2));
+ assertSameElements('set == {1}', ['1'], n.getValues());
+ assertTrue('"1" removed from {1}', n.remove('1'));
+ assertSameElements('set == {}', [], n.getValues());
+
+ var s = new goog.structs.StringSet(TEST_VALUES);
+ goog.array.forEach(TEST_VALUES, s.remove, s);
+ assertSameElements('all special values have been removed', [], s.getValues());
+}
+
+function testRemoveArray() {
+ var s = new goog.structs.StringSet(TEST_VALUES);
+ s.removeArray(TEST_VALUES.slice(0, TEST_VALUES.length - 2));
+ assertSameElements('removed elements from array',
+ TEST_VALUES.slice(TEST_VALUES.length - 2), s.getValues());
+}
+
+function testRemoveSet() {
+ var s1 = new goog.structs.StringSet([1, 2]);
+ var s2 = new goog.structs.StringSet([2, 3]);
+ s1.removeSet(s2);
+ assertSameElements('{1, 2} - {2, 3}', ['1'], s1.getValues());
+}
+
+function testIterator() {
+ var s = new goog.structs.StringSet(TEST_VALUES_WITH_DUPLICATES);
+ var values = []
+ goog.iter.forEach(s, function(value) {
+ values.push(value);
+ });
+ assertSameElements('__iterator__ takes all elements once',
+ TEST_VALUES, values);
+}
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/structs.js b/contexts/data/lib/closure-library/closure/goog/structs/structs.js
new file mode 100644
index 0000000..ec39582
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/structs.js
@@ -0,0 +1,342 @@
+// Copyright 2006 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Generics method for collection-like classes and objects.
+ *
+ * @author arv@google.com (Erik Arvidsson)
+ *
+ * This file contains functions to work with collections. It supports using
+ * Map, Set, Array and Object and other classes that implement collection-like
+ * methods.
+ */
+
+
+goog.provide('goog.structs');
+
+goog.require('goog.array');
+goog.require('goog.object');
+
+
+// We treat an object as a dictionary if it has getKeys or it is an object that
+// isn't arrayLike.
+
+
+/**
+ * Returns the number of values in the collection-like object.
+ * @param {Object} col The collection-like object.
+ * @return {number} The number of values in the collection-like object.
+ */
+goog.structs.getCount = function(col) {
+ if (typeof col.getCount == 'function') {
+ return col.getCount();
+ }
+ if (goog.isArrayLike(col) || goog.isString(col)) {
+ return col.length;
+ }
+ return goog.object.getCount(col);
+};
+
+
+/**
+ * Returns the values of the collection-like object.
+ * @param {Object} col The collection-like object.
+ * @return {!Array} The values in the collection-like object.
+ */
+goog.structs.getValues = function(col) {
+ if (typeof col.getValues == 'function') {
+ return col.getValues();
+ }
+ if (goog.isString(col)) {
+ return col.split('');
+ }
+ if (goog.isArrayLike(col)) {
+ var rv = [];
+ var l = col.length;
+ for (var i = 0; i < l; i++) {
+ rv.push(col[i]);
+ }
+ return rv;
+ }
+ return goog.object.getValues(col);
+};
+
+
+/**
+ * Returns the keys of the collection. Some collections have no notion of
+ * keys/indexes and this function will return undefined in those cases.
+ * @param {Object} col The collection-like object.
+ * @return {!Array|undefined} The keys in the collection.
+ */
+goog.structs.getKeys = function(col) {
+ if (typeof col.getKeys == 'function') {
+ return col.getKeys();
+ }
+ // if we have getValues but no getKeys we know this is a key-less collection
+ if (typeof col.getValues == 'function') {
+ return undefined;
+ }
+ if (goog.isArrayLike(col) || goog.isString(col)) {
+ var rv = [];
+ var l = col.length;
+ for (var i = 0; i < l; i++) {
+ rv.push(i);
+ }
+ return rv;
+ }
+
+ return goog.object.getKeys(col);
+};
+
+
+/**
+ * Whether the collection contains the given value. This is O(n) and uses
+ * equals (==) to test the existence.
+ * @param {Object} col The collection-like object.
+ * @param {*} val The value to check for.
+ * @return {boolean} True if the map contains the value.
+ */
+goog.structs.contains = function(col, val) {
+ if (typeof col.contains == 'function') {
+ return col.contains(val);
+ }
+ if (typeof col.containsValue == 'function') {
+ return col.containsValue(val);
+ }
+ if (goog.isArrayLike(col) || goog.isString(col)) {
+ return goog.array.contains(/** @type {Array} */ (col), val);
+ }
+ return goog.object.containsValue(col, val);
+};
+
+
+/**
+ * Whether the collection is empty.
+ * @param {Object} col The collection-like object.
+ * @return {boolean} True if empty.
+ */
+goog.structs.isEmpty = function(col) {
+ if (typeof col.isEmpty == 'function') {
+ return col.isEmpty();
+ }
+
+ // We do not use goog.string.isEmpty because here we treat the string as
+ // collection and as such even whitespace matters
+
+ if (goog.isArrayLike(col) || goog.isString(col)) {
+ return goog.array.isEmpty(/** @type {Array} */ (col));
+ }
+ return goog.object.isEmpty(col);
+};
+
+
+/**
+ * Removes all the elements from the collection.
+ * @param {Object} col The collection-like object.
+ */
+goog.structs.clear = function(col) {
+ // NOTE(arv): This should not contain strings because strings are immutable
+ if (typeof col.clear == 'function') {
+ col.clear();
+ } else if (goog.isArrayLike(col)) {
+ goog.array.clear((/** @type {goog.array.ArrayLike} */ col));
+ } else {
+ goog.object.clear(col);
+ }
+};
+
+
+/**
+ * Calls a function for each value in a collection. The function takes
+ * three arguments; the value, the key and the collection.
+ *
+ * @param {Object} col The collection-like object.
+ * @param {Function} f The function to call for every value. This function takes
+ * 3 arguments (the value, the key or undefined if the collection has no
+ * notion of keys, and the collection) and the return value is irrelevant.
+ * @param {Object=} opt_obj The object to be used as the value of 'this'
+ * within {@code f}.
+ */
+goog.structs.forEach = function(col, f, opt_obj) {
+ if (typeof col.forEach == 'function') {
+ col.forEach(f, opt_obj);
+ } else if (goog.isArrayLike(col) || goog.isString(col)) {
+ goog.array.forEach(/** @type {Array} */ (col), f, opt_obj);
+ } else {
+ var keys = goog.structs.getKeys(col);
+ var values = goog.structs.getValues(col);
+ var l = values.length;
+ for (var i = 0; i < l; i++) {
+ f.call(opt_obj, values[i], keys && keys[i], col);
+ }
+ }
+};
+
+
+/**
+ * Calls a function for every value in the collection. When a call returns true,
+ * adds the value to a new collection (Array is returned by default).
+ *
+ * @param {Object} col The collection-like object.
+ * @param {Function} f The function to call for every value. This function takes
+ * 3 arguments (the value, the key or undefined if the collection has no
+ * notion of keys, and the collection) and should return a Boolean. If the
+ * return value is true the value is added to the result collection. If it
+ * is false the value is not included.
+ * @param {Object=} opt_obj The object to be used as the value of 'this'
+ * within {@code f}.
+ * @return {!Object|!Array} A new collection where the passed values are
+ * present. If col is a key-less collection an array is returned. If col
+ * has keys and values a plain old JS object is returned.
+ */
+goog.structs.filter = function(col, f, opt_obj) {
+ if (typeof col.filter == 'function') {
+ return col.filter(f, opt_obj);
+ }
+ if (goog.isArrayLike(col) || goog.isString(col)) {
+ return goog.array.filter(/** @type {!Array} */ (col), f, opt_obj);
+ }
+
+ var rv;
+ var keys = goog.structs.getKeys(col);
+ var values = goog.structs.getValues(col);
+ var l = values.length;
+ if (keys) {
+ rv = {};
+ for (var i = 0; i < l; i++) {
+ if (f.call(opt_obj, values[i], keys[i], col)) {
+ rv[keys[i]] = values[i];
+ }
+ }
+ } else {
+ // We should not use goog.array.filter here since we want to make sure that
+ // the index is undefined as well as make sure that col is passed to the
+ // function.
+ rv = [];
+ for (var i = 0; i < l; i++) {
+ if (f.call(opt_obj, values[i], undefined, col)) {
+ rv.push(values[i]);
+ }
+ }
+ }
+ return rv;
+};
+
+
+/**
+ * Calls a function for every value in the collection and adds the result into a
+ * new collection (defaults to creating a new Array).
+ *
+ * @param {Object} col The collection-like object.
+ * @param {Function} f The function to call for every value. This function
+ * takes 3 arguments (the value, the key or undefined if the collection has
+ * no notion of keys, and the collection) and should return something. The
+ * result will be used as the value in the new collection.
+ * @param {Object=} opt_obj The object to be used as the value of 'this'
+ * within {@code f}.
+ * @return {!Object|!Array} A new collection with the new values. If col is a
+ * key-less collection an array is returned. If col has keys and values a
+ * plain old JS object is returned.
+ */
+goog.structs.map = function(col, f, opt_obj) {
+ if (typeof col.map == 'function') {
+ return col.map(f, opt_obj);
+ }
+ if (goog.isArrayLike(col) || goog.isString(col)) {
+ return goog.array.map(/** @type {!Array} */ (col), f, opt_obj);
+ }
+
+ var rv;
+ var keys = goog.structs.getKeys(col);
+ var values = goog.structs.getValues(col);
+ var l = values.length;
+ if (keys) {
+ rv = {};
+ for (var i = 0; i < l; i++) {
+ rv[keys[i]] = f.call(opt_obj, values[i], keys[i], col);
+ }
+ } else {
+ // We should not use goog.array.map here since we want to make sure that
+ // the index is undefined as well as make sure that col is passed to the
+ // function.
+ rv = [];
+ for (var i = 0; i < l; i++) {
+ rv[i] = f.call(opt_obj, values[i], undefined, col);
+ }
+ }
+ return rv;
+};
+
+
+/**
+ * Calls f for each value in a collection. If any call returns true this returns
+ * true (without checking the rest). If all returns false this returns false.
+ *
+ * @param {Object|Array|string} col The collection-like object.
+ * @param {Function} f The function to call for every value. This function takes
+ * 3 arguments (the value, the key or undefined if the collection has no
+ * notion of keys, and the collection) and should return a Boolean.
+ * @param {Object=} opt_obj The object to be used as the value of 'this'
+ * within {@code f}.
+ * @return {boolean} True if any value passes the test.
+ */
+goog.structs.some = function(col, f, opt_obj) {
+ if (typeof col.some == 'function') {
+ return col.some(f, opt_obj);
+ }
+ if (goog.isArrayLike(col) || goog.isString(col)) {
+ return goog.array.some(/** @type {!Array} */ (col), f, opt_obj);
+ }
+ var keys = goog.structs.getKeys(col);
+ var values = goog.structs.getValues(col);
+ var l = values.length;
+ for (var i = 0; i < l; i++) {
+ if (f.call(opt_obj, values[i], keys && keys[i], col)) {
+ return true;
+ }
+ }
+ return false;
+};
+
+
+/**
+ * Calls f for each value in a collection. If all calls return true this return
+ * true this returns true. If any returns false this returns false at this point
+ * and does not continue to check the remaining values.
+ *
+ * @param {Object} col The collection-like object.
+ * @param {Function} f The function to call for every value. This function takes
+ * 3 arguments (the value, the key or undefined if the collection has no
+ * notion of keys, and the collection) and should return a Boolean.
+ * @param {Object=} opt_obj The object to be used as the value of 'this'
+ * within {@code f}.
+ * @return {boolean} True if all key-value pairs pass the test.
+ */
+goog.structs.every = function(col, f, opt_obj) {
+ if (typeof col.every == 'function') {
+ return col.every(f, opt_obj);
+ }
+ if (goog.isArrayLike(col) || goog.isString(col)) {
+ return goog.array.every(/** @type {!Array} */ (col), f, opt_obj);
+ }
+ var keys = goog.structs.getKeys(col);
+ var values = goog.structs.getValues(col);
+ var l = values.length;
+ for (var i = 0; i < l; i++) {
+ if (!f.call(opt_obj, values[i], keys && keys[i], col)) {
+ return false;
+ }
+ }
+ return true;
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/structs_test.html b/contexts/data/lib/closure-library/closure/goog/structs/structs_test.html
new file mode 100644
index 0000000..fb9fe78
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/structs_test.html
@@ -0,0 +1,1050 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2006 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs</title>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.array');
+ goog.require('goog.object');
+ goog.require('goog.structs');
+ goog.require('goog.structs.Set'); // needed for filter
+ goog.require('goog.structs.Map');
+ goog.require('goog.testing.jsunit');
+</script>
+</head>
+<body>
+<!-- test container with 10 elements inside, 1 hr and 1 h1 with id h1 -->
+<div id="test">
+ <hr>
+ <p>Paragraph 0</p>
+ <p>Paragraph 1</p>
+ <p>Paragraph 2</p>
+ <p>Paragraph 3</p>
+ <p>Paragraph 4</p>
+ <p>Paragraph 5</p>
+ <p>Paragraph 6</p>
+ <p>Paragraph 7</p>
+ <h1 id="h1">Header</h1>
+</div>
+
+
+<script>
+
+/*
+
+ This one does not test Map or Set
+ It tests Array, Object, String and a NodeList
+
+*/
+
+
+
+function stringifyObject(obj) {
+ var sb = [];
+ for (var key in obj) {
+ sb.push(key + obj[key]);
+ }
+ return sb.join('');
+}
+
+
+function getTestElement() {
+ return document.getElementById('test');
+}
+
+
+function getAll() {
+ return getTestElement().getElementsByTagName('*')
+}
+
+
+var node;
+
+
+function addNode() {
+ node = document.createElement('span');
+ getTestElement().appendChild(node);
+}
+
+
+function removeNode() {
+ getTestElement().removeChild(node);
+}
+
+
+function nodeNames(nl) {
+ var sb = [];
+ for (var i = 0, n; n = nl[i]; i++) {
+ sb.push(n.nodeName.toLowerCase());
+ }
+ return sb.join(',');
+}
+
+
+var allTagNames1 = 'hr,p,p,p,p,p,p,p,p,h1';
+var allTagNames2 = allTagNames1 + ',span';
+
+
+function testGetCount() {
+ var arr = ['a', 'b', 'c'];
+ assertEquals('count, should be 3', 3, goog.structs.getCount(arr));
+ arr.push('d');
+ assertEquals('count, should be 4', 4, goog.structs.getCount(arr));
+ goog.array.remove(arr, 'd');
+ assertEquals('count, should be 3', 3, goog.structs.getCount(arr));
+
+ var obj = {a: 0, b: 1, c: 2};
+ assertEquals('count, should be 3', 3, goog.structs.getCount(obj));
+ obj.d = 3;
+ assertEquals('count, should be 4', 4, goog.structs.getCount(obj));
+ delete obj.d;
+ assertEquals('count, should be 3', 3, goog.structs.getCount(obj));
+
+ var s = 'abc';
+ assertEquals('count, should be 3', 3, goog.structs.getCount(s));
+ s += 'd';
+ assertEquals('count, should be 4', 4, goog.structs.getCount(s));
+
+ var all = getAll();
+ assertEquals('count, should be 10', 10, goog.structs.getCount(all));
+ addNode();
+ assertEquals('count, should be 11', 11, goog.structs.getCount(all));
+ removeNode();
+ assertEquals('count, should be 10', 10, goog.structs.getCount(all));
+
+ var aMap = new goog.structs.Map({a: 0, b: 1, c: 2});
+ assertEquals('count, should be 3', 3, goog.structs.getCount(aMap));
+ aMap.set('d', 3);
+ assertEquals('count, should be 4', 4, goog.structs.getCount(aMap));
+ aMap.remove('a');
+ assertEquals('count, should be 3', 3, goog.structs.getCount(aMap));
+
+ var aSet = new goog.structs.Set('abc');
+ assertEquals('count, should be 3', 3, goog.structs.getCount(aSet));
+ aSet.add('d');
+ assertEquals('count, should be 4', 4, goog.structs.getCount(aSet));
+ aSet.remove('a');
+ assertEquals('count, should be 3', 3, goog.structs.getCount(aSet));
+}
+
+
+function testGetValues() {
+ var arr = ['a', 'b', 'c', 'd'];
+ assertEquals('abcd', goog.structs.getValues(arr).join(''));
+
+ var obj = {a: 0, b: 1, c: 2, d: 3};
+ assertEquals('0123', goog.structs.getValues(obj).join(''));
+
+ var s = 'abc';
+ assertEquals('abc', goog.structs.getValues(s).join(''));
+ s += 'd';
+ assertEquals('abcd', goog.structs.getValues(s).join(''));
+
+ var all = getAll();
+ assertEquals(allTagNames1, nodeNames(goog.structs.getValues(all)));
+ addNode();
+ assertEquals(allTagNames2, nodeNames(goog.structs.getValues(all)));
+ removeNode();
+ assertEquals(allTagNames1, nodeNames(goog.structs.getValues(all)));
+
+ var aMap = new goog.structs.Map({a: 1, b: 2, c: 3});
+ assertEquals('123', goog.structs.getValues(aMap).join(''));
+
+ var aSet = new goog.structs.Set([1, 2, 3]);
+ assertEquals('123', goog.structs.getValues(aMap).join(''));
+}
+
+
+function testGetKeys() {
+ var arr = ['a', 'b', 'c', 'd'];
+ assertEquals('0123', goog.structs.getKeys(arr).join(''));
+
+ var obj = {a: 0, b: 1, c: 2, d: 3};
+ assertEquals('abcd', goog.structs.getKeys(obj).join(''));
+
+ var s = 'abc';
+ assertEquals('012', goog.structs.getKeys(s).join(''));
+ s += 'd';
+ assertEquals('0123', goog.structs.getKeys(s).join(''));
+
+ var all = getAll();
+ assertEquals('0123456789', goog.structs.getKeys(all).join(''));
+ addNode();
+ assertEquals('012345678910', goog.structs.getKeys(all).join(''));
+ removeNode();
+ assertEquals('0123456789', goog.structs.getKeys(all).join(''));
+
+ var aMap = new goog.structs.Map({a: 1, b: 2, c: 3});
+ assertEquals('abc', goog.structs.getKeys(aMap).join(''));
+
+ var aSet = new goog.structs.Set([1, 2, 3]);
+ assertUndefined(goog.structs.getKeys(aSet));
+}
+
+function testContains() {
+ var arr = ['a', 'b', 'c', 'd'];
+ assertTrue("contains, Should contain 'a'", goog.structs.contains(arr, 'a'));
+ assertFalse("contains, Should not contain 'e'", goog.structs.contains(arr, 'e'));
+
+ var obj = {a: 0, b: 1, c: 2, d: 3};
+ assertTrue("contains, Should contain '0'", goog.structs.contains(obj, 0));
+ assertFalse("contains, Should not contain '4'", goog.structs.contains(obj, 4));
+
+ var s = 'abc';
+ assertTrue("contains, Should contain 'a'", goog.structs.contains(s, 'a'));
+ assertFalse("contains, Should not contain 'd'", goog.structs.contains(s, 'd'));
+
+ var all = getAll();
+ assertTrue("contains, Should contain 'h1'",
+ goog.structs.contains(all, document.getElementById('h1')));
+ assertFalse("contains, Should not contain 'document.body'",
+ goog.structs.contains(all, document.body));
+
+ var aMap = new goog.structs.Map({a: 1, b: 2, c: 3});
+ assertTrue("contains, Should contain '1'", goog.structs.contains(aMap, 1));
+ assertFalse("contains, Should not contain '4'", goog.structs.contains(aMap, 4));
+
+ var aSet = new goog.structs.Set([1, 2, 3]);
+ assertTrue("contains, Should contain '1'", goog.structs.contains(aSet, 1));
+ assertFalse("contains, Should not contain '4'", goog.structs.contains(aSet, 4));
+}
+
+
+function testClear() {
+ var arr = ['a', 'b', 'c', 'd'];
+ goog.structs.clear(arr);
+ assertTrue('cleared so it should be empty', goog.structs.isEmpty(arr));
+ assertFalse("cleared so it should not contain 'a'", goog.structs.contains(arr, 'a'));
+
+ var obj = {a: 0, b: 1, c: 2, d: 3};
+ goog.structs.clear(obj);
+ assertTrue('cleared so it should be empty', goog.structs.isEmpty(obj));
+ assertFalse("cleared so it should not contain 'a' key", goog.structs.contains(obj, 0));
+
+ var aMap = new goog.structs.Map({a: 1, b: 2, c: 3});
+ goog.structs.clear(aMap);
+ assertTrue('cleared map so it should be empty', goog.structs.isEmpty(aMap));
+ assertFalse("cleared map so it should not contain '1' value",
+ goog.structs.contains(aMap, 1));
+
+ var aSet = new goog.structs.Set([1, 2, 3]);
+ goog.structs.clear(aSet);
+ assertTrue('cleared set so it should be empty', goog.structs.isEmpty(aSet));
+ assertFalse("cleared set so it should not contain '1'", goog.structs.contains(aSet, 1));
+
+ // cannot clear a string or a NodeList
+}
+
+
+
+// Map
+
+function testMap() {
+ var RV = {};
+ var obj = {
+ map: function(g) {
+ assertEquals(f, g);
+ assertEquals(this, obj);
+ return RV;
+ }
+ };
+ function f() {}
+ assertEquals(RV, goog.structs.map(obj, f));
+}
+
+function testMap2() {
+ var THIS_OBJ = {};
+ var RV = {};
+ var obj = {
+ map: function(g, obj2) {
+ assertEquals(f, g);
+ assertEquals(this, obj);
+ assertEquals(THIS_OBJ, obj2);
+ return RV;
+ }
+ };
+ function f() {}
+ assertEquals(RV, goog.structs.map(obj, f, THIS_OBJ));
+}
+
+function testMapArrayLike() {
+ var col = [0, 1, 2];
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ return v * v;
+ }
+ assertArrayEquals([0, 1, 4], goog.structs.map(col, f));
+}
+
+function testMapArrayLike2() {
+ var THIS_OBJ = {};
+ var col = [0, 1, 2];
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ return v * v;
+ }
+ assertArrayEquals([0, 1, 4], goog.structs.map(col, f, THIS_OBJ));
+}
+
+function testMapString() {
+ var col = '012';
+ function f(v, i, col2) {
+ // Teh SpiderMonkey Array.map for strings turns the string into a String
+ // so we cannot use assertEquals because it uses ===.
+ assertTrue(col == col2);
+ assertEquals('number', typeof i);
+ return Number(v) * Number(v);
+ }
+ assertArrayEquals([0, 1, 4], goog.structs.map(col, f));
+}
+
+function testMapString2() {
+ var THIS_OBJ = {};
+ var col = '012';
+ function f(v, i, col2) {
+ // for some reason the strings are equal but identical???
+ assertEquals(String(col), String(col2));
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ return Number(v) * Number(v);
+ }
+ assertArrayEquals([0, 1, 4], goog.structs.map(col, f, THIS_OBJ));
+}
+
+function testMapMap() {
+ var col = new goog.structs.Map({a: 0, b: 1, c: 2});
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('string', typeof key);
+ return v * v;
+ }
+ assertObjectEquals({a: 0, b: 1, c: 4}, goog.structs.map(col, f));
+}
+
+function testMapMap2() {
+ var THIS_OBJ = {};
+ var col = new goog.structs.Map({a: 0, b: 1, c: 2});
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('string', typeof key);
+ assertEquals(THIS_OBJ, this);
+ return v * v;
+ }
+ assertObjectEquals({a: 0, b: 1, c: 4}, goog.structs.map(col, f, THIS_OBJ));
+}
+
+function testMapSet() {
+ var col = new goog.structs.Set([0, 1, 2]);
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('undefined', typeof key);
+ return v * v;
+ }
+ assertArrayEquals([0, 1, 4], goog.structs.map(col, f));
+}
+
+function testMapSet2() {
+ var THIS_OBJ = {};
+ var col = new goog.structs.Set([0, 1, 2]);
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('undefined', typeof key);
+ assertEquals(THIS_OBJ, this);
+ return v * v;
+ }
+ assertArrayEquals([0, 1, 4], goog.structs.map(col, f, THIS_OBJ));
+}
+
+function testMapNodeList() {
+ var col = getAll();
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ return v.tagName;
+ }
+ assertEquals('HRPPPPPPPPH1', goog.structs.map(col, f).join(''));
+}
+
+function testMapNodeList2() {
+ var THIS_OBJ = {};
+ var col = getAll();
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ return v.tagName;
+ }
+ assertEquals('HRPPPPPPPPH1', goog.structs.map(col, f, THIS_OBJ).join(''));
+}
+
+// Filter
+
+function testFilter() {
+ var RV = {};
+ var obj = {
+ filter: function(g) {
+ assertEquals(f, g);
+ assertEquals(this, obj);
+ return RV;
+ }
+ };
+ function f() {}
+ assertEquals(RV, goog.structs.filter(obj, f));
+}
+
+function testFilter2() {
+ var THIS_OBJ = {};
+ var RV = {};
+ var obj = {
+ filter: function(g, obj2) {
+ assertEquals(f, g);
+ assertEquals(this, obj);
+ assertEquals(THIS_OBJ, obj2);
+ return RV;
+ }
+ };
+ function f() {}
+ assertEquals(RV, goog.structs.filter(obj, f, THIS_OBJ));
+}
+
+function testFilterArrayLike() {
+ var col = [0, 1, 2];
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ return v > 0;
+ }
+ assertArrayEquals([1, 2], goog.structs.filter(col, f));
+}
+
+function testFilterArrayLike2() {
+ var THIS_OBJ = {};
+ var col = [0, 1, 2];
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ return v > 0;
+ }
+ assertArrayEquals([1, 2], goog.structs.filter(col, f, THIS_OBJ));
+}
+
+function testFilterString() {
+ var col = '012';
+ function f(v, i, col2) {
+ // for some reason the strings are equal but identical???
+ assertEquals(String(col), String(col2));
+ assertEquals('number', typeof i);
+ return Number(v) > 0;
+ }
+ assertArrayEquals(['1', '2'], goog.structs.filter(col, f));
+}
+
+function testFilterString2() {
+ var THIS_OBJ = {};
+ var col = '012';
+ function f(v, i, col2) {
+ // for some reason the strings are equal but identical???
+ assertEquals(String(col), String(col2));
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ return Number(v) > 0;
+ }
+ assertArrayEquals(['1', '2'], goog.structs.filter(col, f, THIS_OBJ));
+}
+
+function testFilterMap() {
+ var col = new goog.structs.Map({a: 0, b: 1, c: 2});
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('string', typeof key);
+ return v > 0;
+ }
+ assertObjectEquals({b: 1, c: 2}, goog.structs.filter(col, f));
+}
+
+function testFilterMap2() {
+ var THIS_OBJ = {};
+ var col = new goog.structs.Map({a: 0, b: 1, c: 2});
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('string', typeof key);
+ assertEquals(THIS_OBJ, this);
+ return v > 0;
+ }
+ assertObjectEquals({b: 1, c: 2}, goog.structs.filter(col, f, THIS_OBJ));
+}
+
+function testFilterSet() {
+ var col = new goog.structs.Set([0, 1, 2]);
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('undefined', typeof key);
+ return v > 0;
+ }
+ assertArrayEquals([1, 2], goog.structs.filter(col, f));
+}
+
+function testFilterSet2() {
+ var THIS_OBJ = {};
+ var col = new goog.structs.Set([0, 1, 2]);
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('undefined', typeof key);
+ assertEquals(THIS_OBJ, this);
+ return v > 0;
+ }
+ assertArrayEquals([1, 2], goog.structs.filter(col, f, THIS_OBJ));
+}
+
+function testFilterNodeList() {
+ var col = getAll();
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ return v.tagName == 'P';
+ }
+ assertEquals('p,p,p,p,p,p,p,p',
+ nodeNames(goog.structs.filter(col, f)));
+}
+
+function testFilterNodeList2() {
+ var THIS_OBJ = {};
+ var col = getAll();
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ return v.tagName == 'P';
+ }
+ assertEquals('p,p,p,p,p,p,p,p',
+ nodeNames(goog.structs.filter(col, f, THIS_OBJ)));
+}
+
+// Some
+
+function testSome() {
+ var RV = {};
+ var obj = {
+ some: function(g) {
+ assertEquals(f, g);
+ assertEquals(this, obj);
+ return RV;
+ }
+ };
+ function f() {}
+ assertEquals(RV, goog.structs.some(obj, f));
+}
+
+function testSome2() {
+ var THIS_OBJ = {};
+ var RV = {};
+ var obj = {
+ some: function(g, obj2) {
+ assertEquals(f, g);
+ assertEquals(this, obj);
+ assertEquals(THIS_OBJ, obj2);
+ return RV;
+ }
+ };
+ function f() {}
+ assertEquals(RV, goog.structs.some(obj, f, THIS_OBJ));
+}
+
+function testSomeArrayLike() {
+ var limit = 0;
+ var col = [0, 1, 2];
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ return v > limit;
+ }
+ assertTrue(goog.structs.some(col, f));
+ limit = 2;
+ assertFalse(goog.structs.some(col, f));
+}
+
+function testSomeArrayLike2() {
+ var THIS_OBJ = {};
+ var limit = 0;
+ var col = [0, 1, 2];
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ return v > limit;
+ }
+ assertTrue(goog.structs.some(col, f, THIS_OBJ));
+ limit = 2;
+ assertFalse(goog.structs.some(col, f, THIS_OBJ));
+}
+
+function testSomeString() {
+ var limit = 0;
+ var col = '012';
+ function f(v, i, col2) {
+ // for some reason the strings are equal but identical???
+ assertEquals(String(col), String(col2));
+ assertEquals('number', typeof i);
+ return Number(v) > limit;
+ }
+ assertTrue(goog.structs.some(col, f));
+ limit = 2;
+ assertFalse(goog.structs.some(col, f));
+}
+
+function testSomeString2() {
+ var THIS_OBJ = {};
+ var limit = 0;
+ var col = '012';
+ function f(v, i, col2) {
+ // for some reason the strings are equal but identical???
+ assertEquals(String(col), String(col2));
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ return Number(v) > limit;
+ }
+ assertTrue(goog.structs.some(col, f, THIS_OBJ));
+ limit = 2;
+ assertFalse(goog.structs.some(col, f, THIS_OBJ));
+}
+
+function testSomeMap() {
+ var limit = 0;
+ var col = new goog.structs.Map({a: 0, b: 1, c: 2});
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('string', typeof key);
+ return v > limit;
+ }
+ assertObjectEquals(true, goog.structs.some(col, f));
+ limit = 2;
+ assertFalse(goog.structs.some(col, f));
+}
+
+function testSomeMap2() {
+ var THIS_OBJ = {};
+ var limit = 0;
+ var col = new goog.structs.Map({a: 0, b: 1, c: 2});
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('string', typeof key);
+ assertEquals(THIS_OBJ, this);
+ return v > limit;
+ }
+ assertObjectEquals(true, goog.structs.some(col, f, THIS_OBJ));
+ limit = 2;
+ assertFalse(goog.structs.some(col, f, THIS_OBJ));
+}
+
+function testSomeSet() {
+ var limit = 0;
+ var col = new goog.structs.Set([0, 1, 2]);
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('undefined', typeof key);
+ return v > limit;
+ }
+ assertTrue(goog.structs.some(col, f));
+ limit = 2;
+ assertFalse(goog.structs.some(col, f));
+}
+
+function testSomeSet2() {
+ var THIS_OBJ = {};
+ var limit = 0;
+ var col = new goog.structs.Set([0, 1, 2]);
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('undefined', typeof key);
+ assertEquals(THIS_OBJ, this);
+ return v > limit;
+ }
+ assertTrue(goog.structs.some(col, f, THIS_OBJ));
+ limit = 2;
+ assertFalse(goog.structs.some(col, f, THIS_OBJ));
+}
+
+function testSomeNodeList() {
+ var tagName = 'P';
+ var col = getAll();
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ return v.tagName == tagName;
+ }
+ assertTrue(goog.structs.some(col, f));
+ tagName = 'MARQUEE';
+ assertFalse(goog.structs.some(col, f));
+}
+
+function testSomeNodeList2() {
+ var THIS_OBJ = {};
+ var tagName = 'P';
+ var col = getAll();
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ return v.tagName == tagName;
+ }
+ assertTrue(goog.structs.some(col, f, THIS_OBJ));
+ tagName = 'MARQUEE';
+ assertFalse(goog.structs.some(col, f, THIS_OBJ));
+}
+
+// Every
+
+function testEvery() {
+ var RV = {};
+ var obj = {
+ every: function(g) {
+ assertEquals(f, g);
+ assertEquals(this, obj);
+ return RV;
+ }
+ };
+ function f() {}
+ assertEquals(RV, goog.structs.every(obj, f));
+}
+
+function testEvery2() {
+ var THIS_OBJ = {};
+ var RV = {};
+ var obj = {
+ every: function(g, obj2) {
+ assertEquals(f, g);
+ assertEquals(this, obj);
+ assertEquals(THIS_OBJ, obj2);
+ return RV;
+ }
+ };
+ function f() {}
+ assertEquals(RV, goog.structs.every(obj, f, THIS_OBJ));
+}
+
+function testEveryArrayLike() {
+ var limit = -1;
+ var col = [0, 1, 2];
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ return v > limit;
+ }
+ assertTrue(goog.structs.every(col, f));
+ limit = 1;
+ assertFalse(goog.structs.every(col, f));
+}
+
+function testEveryArrayLike2() {
+ var THIS_OBJ = {};
+ var limit = -1;
+ var col = [0, 1, 2];
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ return v > limit;
+ }
+ assertTrue(goog.structs.every(col, f, THIS_OBJ));
+ limit = 1;
+ assertFalse(goog.structs.every(col, f, THIS_OBJ));
+}
+
+function testEveryString() {
+ var limit = -1;
+ var col = '012';
+ function f(v, i, col2) {
+ // for some reason the strings are equal but identical???
+ assertEquals(String(col), String(col2));
+ assertEquals('number', typeof i);
+ return Number(v) > limit;
+ }
+ assertTrue(goog.structs.every(col, f));
+ limit = 1;
+ assertFalse(goog.structs.every(col, f));
+}
+
+function testEveryString2() {
+ var THIS_OBJ = {};
+ var limit = -1;
+ var col = '012';
+ function f(v, i, col2) {
+ // for some reason the strings are equal but identical???
+ assertEquals(String(col), String(col2));
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ return Number(v) > limit;
+ }
+ assertTrue(goog.structs.every(col, f, THIS_OBJ));
+ limit = 1;
+ assertFalse(goog.structs.every(col, f, THIS_OBJ));
+}
+
+function testEveryMap() {
+ var limit = -1;
+ var col = new goog.structs.Map({a: 0, b: 1, c: 2});
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('string', typeof key);
+ return v > limit;
+ }
+ assertObjectEquals(true, goog.structs.every(col, f));
+ limit = 1;
+ assertFalse(goog.structs.every(col, f));
+}
+
+function testEveryMap2() {
+ var THIS_OBJ = {};
+ var limit = -1;
+ var col = new goog.structs.Map({a: 0, b: 1, c: 2});
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('string', typeof key);
+ assertEquals(THIS_OBJ, this);
+ return v > limit;
+ }
+ assertObjectEquals(true, goog.structs.every(col, f, THIS_OBJ));
+ limit = 1;
+ assertFalse(goog.structs.every(col, f, THIS_OBJ));
+}
+
+function testEverySet() {
+ var limit = -1;
+ var col = new goog.structs.Set([0, 1, 2]);
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('undefined', typeof key);
+ return v > limit;
+ }
+ assertTrue(goog.structs.every(col, f));
+ limit = 1;
+ assertFalse(goog.structs.every(col, f));
+}
+
+function testEverySet2() {
+ var THIS_OBJ = {};
+ var limit = -1;
+ var col = new goog.structs.Set([0, 1, 2]);
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('undefined', typeof key);
+ assertEquals(THIS_OBJ, this);
+ return v > limit;
+ }
+ assertTrue(goog.structs.every(col, f, THIS_OBJ));
+ limit = 1;
+ assertFalse(goog.structs.every(col, f, THIS_OBJ));
+}
+
+function testEveryNodeList() {
+ var nodeType = 1; // ELEMENT
+ var col = getAll();
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ return v.nodeType == nodeType;
+ }
+ assertTrue(goog.structs.every(col, f));
+ nodeType = 3; // TEXT
+ assertFalse(goog.structs.every(col, f));
+}
+
+function testEveryNodeList2() {
+ var THIS_OBJ = {};
+ var nodeType = 1; // ELEMENT
+ var col = getAll();
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ return v.nodeType == nodeType;
+ }
+ assertTrue(goog.structs.every(col, f, THIS_OBJ));
+ nodeType = 3; // TEXT
+ assertFalse(goog.structs.every(col, f, THIS_OBJ));
+}
+
+// For each
+
+function testForEach() {
+ var called = false;
+ var obj = {
+ forEach: function(g) {
+ assertEquals(f, g);
+ assertEquals(this, obj);
+ called = true;
+ }
+ };
+ function f() {}
+ goog.structs.forEach(obj, f);
+ assertTrue(called);
+}
+
+function testForEach2() {
+ var called = false;
+ var THIS_OBJ = {};
+ var obj = {
+ forEach: function(g, obj2) {
+ assertEquals(f, g);
+ assertEquals(this, obj);
+ assertEquals(THIS_OBJ, obj2);
+ called = true;
+ }
+ };
+ function f() {}
+ goog.structs.forEach(obj, f, THIS_OBJ);
+ assertTrue(called);
+}
+
+function testForEachArrayLike() {
+ var col = [0, 1, 2];
+ var values = [];
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ values.push(v * v);
+ }
+ goog.structs.forEach(col, f)
+ assertArrayEquals([0, 1, 4], values);
+}
+
+function testForEachArrayLike2() {
+ var THIS_OBJ = {};
+ var col = [0, 1, 2];
+ var values = [];
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ values.push(v * v);
+ }
+ goog.structs.forEach(col, f, THIS_OBJ);
+ assertArrayEquals([0, 1, 4], values);
+}
+
+function testForEachString() {
+ var col = '012';
+ var values = [];
+ function f(v, i, col2) {
+ // for some reason the strings are equal but identical???
+ assertEquals(String(col), String(col2));
+ assertEquals('number', typeof i);
+ values.push(Number(v) * Number(v));
+ }
+ goog.structs.forEach(col, f);
+ assertArrayEquals([0, 1, 4], values);
+}
+
+function testForEachString2() {
+ var THIS_OBJ = {};
+ var col = '012';
+ var values = [];
+ function f(v, i, col2) {
+ // for some reason the strings are equal but identical???
+ assertEquals(String(col), String(col2));
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ values.push(Number(v) * Number(v));
+ }
+ goog.structs.forEach(col, f, THIS_OBJ);
+ assertArrayEquals([0, 1, 4], values);
+}
+
+function testForEachMap() {
+ var col = new goog.structs.Map({a: 0, b: 1, c: 2});
+ var values = [];
+ var keys = [];
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('string', typeof key);
+ values.push(v * v);
+ keys.push(key);
+ }
+ goog.structs.forEach(col, f);
+ assertArrayEquals([0, 1, 4], values);
+ assertArrayEquals(['a', 'b', 'c'], keys);
+}
+
+function testForEachMap2() {
+ var THIS_OBJ = {};
+ var col = new goog.structs.Map({a: 0, b: 1, c: 2});
+ var values = [];
+ var keys = [];
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('string', typeof key);
+ assertEquals(THIS_OBJ, this);
+ values.push(v * v);
+ keys.push(key);
+ }
+ goog.structs.forEach(col, f, THIS_OBJ);
+ assertArrayEquals([0, 1, 4], values);
+ assertArrayEquals(['a', 'b', 'c'], keys);
+}
+
+function testForEachSet() {
+ var col = new goog.structs.Set([0, 1, 2]);
+ var values = [];
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('undefined', typeof key);
+ values.push(v * v);
+ }
+ goog.structs.forEach(col, f);
+ assertArrayEquals([0, 1, 4], values);
+}
+
+function testForEachSet2() {
+ var THIS_OBJ = {};
+ var col = new goog.structs.Set([0, 1, 2]);
+ var values = [];
+ function f(v, key, col2) {
+ assertEquals(col, col2);
+ assertEquals('undefined', typeof key);
+ assertEquals(THIS_OBJ, this);
+ values.push(v * v);
+ }
+ goog.structs.forEach(col, f, THIS_OBJ);
+ assertArrayEquals([0, 1, 4], values);
+}
+
+function testForEachNodeList() {
+ var values = [];
+ var col = getAll();
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ values.push(v.tagName);
+ }
+ goog.structs.forEach(col, f);
+ assertEquals('HRPPPPPPPPH1', values.join(''));
+}
+
+function testForEachNodeList2() {
+ var THIS_OBJ = {};
+ var values = [];
+ var col = getAll();
+ function f(v, i, col2) {
+ assertEquals(col, col2);
+ assertEquals('number', typeof i);
+ assertEquals(THIS_OBJ, this);
+ values.push(v.tagName);
+ }
+ goog.structs.forEach(col, f, THIS_OBJ);
+ assertEquals('HRPPPPPPPPH1', values.join(''));
+}
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/treenode.js b/contexts/data/lib/closure-library/closure/goog/structs/treenode.js
new file mode 100644
index 0000000..4d67ed4
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/treenode.js
@@ -0,0 +1,427 @@
+// Copyright 2010 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Generic tree node data structure with arbitrary number of child
+ * nodes.
+ *
+ */
+
+goog.provide('goog.structs.TreeNode');
+
+goog.require('goog.array');
+goog.require('goog.asserts');
+goog.require('goog.structs.Node');
+
+
+
+/**
+ * Generic tree node data structure with arbitrary number of child nodes.
+ * It is possible to create a dynamic tree structure by overriding
+ * {@link #getParent} and {@link #getChildren} in a subclass. All other getters
+ * will automatically work.
+ *
+ * @param {*} key Key.
+ * @param {*} value Value.
+ * @constructor
+ * @extends {goog.structs.Node}
+ */
+goog.structs.TreeNode = function(key, value) {
+ goog.structs.Node.call(this, key, value);
+};
+goog.inherits(goog.structs.TreeNode, goog.structs.Node);
+
+
+/**
+ * Constant for empty array to avoid unnecessary allocations.
+ * @private
+ */
+goog.structs.TreeNode.EMPTY_ARRAY_ = [];
+
+
+/**
+ * Reference to the parent node or null if it has no parent.
+ * @type {goog.structs.TreeNode}
+ * @private
+ */
+goog.structs.TreeNode.prototype.parent_ = null;
+
+
+/**
+ * Child nodes or null in case of leaf node.
+ * @type {Array.<!goog.structs.TreeNode>}
+ * @private
+ */
+goog.structs.TreeNode.prototype.children_ = null;
+
+
+/**
+ * @return {!goog.structs.TreeNode} Clone of the tree node without its parent
+ * and child nodes. The key and the value are copied by reference.
+ */
+goog.structs.TreeNode.prototype.clone = function() {
+ return new goog.structs.TreeNode(this.getKey(), this.getValue());
+};
+
+
+/**
+ * @return {!goog.structs.TreeNode} Clone of the subtree with this node as root.
+ */
+goog.structs.TreeNode.prototype.deepClone = function() {
+ var clone = this.clone();
+ this.forEachChild(function(child) {
+ clone.addChild(child.deepClone());
+ });
+ return clone;
+};
+
+
+/**
+ * @return {goog.structs.TreeNode} Parent node or null if it has no parent.
+ */
+goog.structs.TreeNode.prototype.getParent = function() {
+ return this.parent_;
+};
+
+
+/**
+ * @return {boolean} Whether the node is a leaf node.
+ */
+goog.structs.TreeNode.prototype.isLeaf = function() {
+ return !this.getChildCount();
+};
+
+
+/**
+ * Tells if the node is the last child of its parent. This method helps how to
+ * connect the tree nodes with lines: L shapes should be used before the last
+ * children and |- shapes before the rest. Schematic tree visualization:
+ *
+ * <pre>
+ * Node1
+ * |-Node2
+ * | L-Node3
+ * | |-Node4
+ * | L-Node5
+ * L-Node6
+ * </pre>
+ *
+ * @return {boolean} Whether the node has parent and is the last child of it.
+ */
+goog.structs.TreeNode.prototype.isLastChild = function() {
+ var parent = this.getParent();
+ return Boolean(parent && this == goog.array.peek(parent.getChildren()));
+};
+
+
+/**
+ * @return {!Array.<!goog.structs.TreeNode>} Immutable child nodes.
+ */
+goog.structs.TreeNode.prototype.getChildren = function() {
+ return this.children_ || goog.structs.TreeNode.EMPTY_ARRAY_;
+};
+
+
+/**
+ * Gets the child node of this node at the given index.
+ * @param {number} index Child index.
+ * @return {goog.structs.TreeNode} The node at the given index or null if not
+ * found.
+ */
+goog.structs.TreeNode.prototype.getChildAt = function(index) {
+ return this.getChildren()[index] || null;
+};
+
+
+/**
+ * @return {number} The number of children.
+ */
+goog.structs.TreeNode.prototype.getChildCount = function() {
+ return this.getChildren().length;
+};
+
+
+/**
+ * @return {number} The number of ancestors of the node.
+ */
+goog.structs.TreeNode.prototype.getDepth = function() {
+ var depth = 0;
+ var node = this;
+ while (node.getParent()) {
+ depth++;
+ node = node.getParent();
+ }
+ return depth;
+};
+
+
+/**
+ * @return {!Array.<!goog.structs.TreeNode>} All ancestor nodes in bottom-up
+ * order.
+ */
+goog.structs.TreeNode.prototype.getAncestors = function() {
+ var ancestors = [];
+ var node = this.getParent();
+ while (node) {
+ ancestors.push(node);
+ node = node.getParent();
+ }
+ return ancestors;
+};
+
+
+/**
+ * @return {!goog.structs.TreeNode} The root of the tree structure, i.e. the
+ * farthest ancestor of the node or the node itself if it has no parents.
+ */
+goog.structs.TreeNode.prototype.getRoot = function() {
+ var root = this;
+ while (root.getParent()) {
+ root = root.getParent();
+ }
+ return root;
+};
+
+
+/**
+ * Builds a nested array structure from the node keys in this node's subtree to
+ * facilitate testing tree operations that change the hierarchy.
+ * @return {!Array} The structure of this node's descendants as nested array
+ * of node keys. The number of unclosed opening brackets up to a particular
+ * node is proportional to the indentation of that node in the graphical
+ * representation of the tree. Example:
+ * <pre>
+ * this
+ * |- child1
+ * | L- grandchild
+ * L- child2
+ * </pre>
+ * is represented as ['child1', ['grandchild'], 'child2'].
+ */
+goog.structs.TreeNode.prototype.getSubtreeKeys = function() {
+ var ret = [];
+ this.forEachChild(function(child) {
+ ret.push(child.getKey());
+ if (!child.isLeaf()) {
+ ret.push(child.getSubtreeKeys());
+ }
+ });
+ return ret;
+};
+
+
+/**
+ * Tells whether this node is the ancestor of the given node.
+ * @param {!goog.structs.TreeNode} node A node.
+ * @return {boolean} Whether this node is the ancestor of {@code node}.
+ */
+goog.structs.TreeNode.prototype.contains = function(node) {
+ var current = node;
+ do {
+ current = current.getParent();
+ } while (current && current != this);
+ return Boolean(current);
+};
+
+
+/**
+ * Finds the deepest common ancestor of the given nodes. The concept of
+ * ancestor is not strict in this case, it includes the node itself.
+ * @param {...!goog.structs.TreeNode} var_args The nodes.
+ * @return {goog.structs.TreeNode} The common ancestor of the nodes or null if
+ * they are from different trees.
+ */
+goog.structs.TreeNode.findCommonAncestor = function(var_args) {
+ var ret = arguments[0];
+ if (!ret) {
+ return null;
+ }
+
+ var retDepth = ret.getDepth();
+ for (var i = 1; i < arguments.length; i++) {
+ var node = arguments[i];
+ var depth = node.getDepth();
+ while (node != ret) {
+ if (depth <= retDepth) {
+ ret = ret.getParent();
+ retDepth--;
+ }
+ if (depth > retDepth) {
+ node = node.getParent();
+ depth--;
+ }
+ }
+ }
+
+ return ret;
+};
+
+
+/**
+ * Traverses all child nodes.
+ * @param {function(!goog.structs.TreeNode, number,
+ * !Array.<!goog.structs.TreeNode>)} f Callback function. It takes the
+ * node, its index and the array of all child nodes as arguments.
+ * @param {Object=} opt_this The object to be used as the value of {@code this}
+ * within {@code f}.
+ */
+goog.structs.TreeNode.prototype.forEachChild = function(f, opt_this) {
+ goog.array.forEach(this.getChildren(), f, opt_this);
+};
+
+
+/**
+ * Traverses all child nodes recursively in preorder.
+ * @param {function(!goog.structs.TreeNode)} f Callback function. It takes the
+ * node as argument.
+ * @param {Object=} opt_this The object to be used as the value of {@code this}
+ * within {@code f}.
+ */
+goog.structs.TreeNode.prototype.forEachDescendant = function(f, opt_this) {
+ goog.array.forEach(this.getChildren(), function(child) {
+ f.call(opt_this, child);
+ child.forEachDescendant(f, opt_this);
+ });
+};
+
+
+/**
+ * Traverses the subtree with the possibility to skip branches. Starts with
+ * this node, and visits the descendant nodes depth-first, in preorder.
+ * @param {function(!goog.structs.TreeNode): (boolean|undefined)} f Callback
+ * function. It takes the node as argument. The children of this node will
+ * be visited if the callback returns true or undefined, and will be
+ * skipped if the callback returns false.
+ * @param {Object=} opt_this The object to be used as the value of {@code this}
+ * within {@code f}.
+ */
+goog.structs.TreeNode.prototype.traverse = function(f, opt_this) {
+ if (f.call(opt_this, this) !== false) {
+ goog.array.forEach(this.getChildren(), function(child) {
+ child.traverse(f, opt_this);
+ });
+ }
+};
+
+
+/**
+ * Sets the parent node of this node. The callers must ensure that the parent
+ * node and only that has this node among its children.
+ * @param {goog.structs.TreeNode} parent The parent to set. If null, the node
+ * will be detached from the tree.
+ * @protected
+ */
+goog.structs.TreeNode.prototype.setParent = function(parent) {
+ this.parent_ = parent;
+};
+
+
+/**
+ * Appends a child node to this node.
+ * @param {!goog.structs.TreeNode} child Orphan child node.
+ */
+goog.structs.TreeNode.prototype.addChild = function(child) {
+ this.addChildAt(child, this.children_ ? this.children_.length : 0);
+};
+
+
+/**
+ * Inserts a child node at the given index.
+ * @param {!goog.structs.TreeNode} child Orphan child node.
+ * @param {number} index The position to insert at.
+ */
+goog.structs.TreeNode.prototype.addChildAt = function(child, index) {
+ goog.asserts.assert(!child.getParent());
+ child.setParent(this);
+ this.children_ = this.children_ || [];
+ goog.asserts.assert(index >= 0 && index <= this.children_.length);
+ goog.array.insertAt(this.children_, child, index);
+};
+
+
+/**
+ * Replaces a child node at the given index.
+ * @param {!goog.structs.TreeNode} newChild Child node to set. It must not have
+ * parent node.
+ * @param {number} index Valid index of the old child to replace.
+ * @return {!goog.structs.TreeNode} The original child node, detached from its
+ * parent.
+ */
+goog.structs.TreeNode.prototype.replaceChildAt = function(newChild, index) {
+ goog.asserts.assert(!newChild.getParent(),
+ 'newChild must not have parent node');
+ var children = this.getChildren();
+ var oldChild = children[index];
+ goog.asserts.assert(oldChild, 'Invalid child or child index is given.');
+ oldChild.setParent(null);
+ children[index] = newChild;
+ newChild.setParent(this);
+ return oldChild;
+};
+
+
+/**
+ * Replaces the given child node.
+ * @param {!goog.structs.TreeNode} newChild New node to replace
+ * {@code oldChild}. It must not have parent node.
+ * @param {!goog.structs.TreeNode} oldChild Existing child node to be replaced.
+ * @return {!goog.structs.TreeNode} The replaced child node detached from its
+ * parent.
+ */
+goog.structs.TreeNode.prototype.replaceChild = function(newChild, oldChild) {
+ return this.replaceChildAt(newChild,
+ goog.array.indexOf(this.getChildren(), oldChild));
+};
+
+
+/**
+ * Removes the child node at the given index.
+ * @param {number} index The position to remove from.
+ * @return {goog.structs.TreeNode} The removed node if any.
+ */
+goog.structs.TreeNode.prototype.removeChildAt = function(index) {
+ var child = this.children_ && this.children_[index];
+ if (child) {
+ child.setParent(null);
+ goog.array.removeAt(this.children_, index);
+ if (this.children_.length == 0) {
+ delete this.children_;
+ }
+ return child;
+ }
+ return null;
+};
+
+
+/**
+ * Removes the given child node of this node.
+ * @param {goog.structs.TreeNode} child The node to remove.
+ * @return {goog.structs.TreeNode} The removed node if any.
+ */
+goog.structs.TreeNode.prototype.removeChild = function(child) {
+ return this.removeChildAt(goog.array.indexOf(this.getChildren(), child));
+};
+
+
+/**
+ * Removes all child nodes of this node.
+ */
+goog.structs.TreeNode.prototype.removeChildren = function() {
+ if (this.children_) {
+ goog.array.forEach(this.children_, function(child) {
+ child.setParent(null);
+ });
+ }
+ delete this.children_;
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/treenode_test.html b/contexts/data/lib/closure-library/closure/goog/structs/treenode_test.html
new file mode 100644
index 0000000..c858b29
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/treenode_test.html
@@ -0,0 +1,370 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2010 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<!--
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs.TreeNode</title>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.array');
+ goog.require('goog.structs.TreeNode');
+ goog.require('goog.testing.jsunit');
+</script>
+</head>
+<body>
+<script>
+
+function testConstructor() {
+ var node = new goog.structs.TreeNode('key', 'value');
+ assertEquals('key', 'key', node.getKey());
+ assertEquals('value', 'value', node.getValue());
+ assertNull('parent', node.getParent());
+ assertArrayEquals('children', [], node.getChildren());
+ assertTrue('leaf', node.isLeaf());
+}
+
+function testClone() {
+ var node1 = new goog.structs.TreeNode(1, '1');
+ var node2 = new goog.structs.TreeNode(2, '2');
+ var node3 = new goog.structs.TreeNode(3, '3');
+ node1.addChild(node2);
+ node2.addChild(node3);
+
+ var clone = node2.clone();
+ assertEquals('key', 2, clone.getKey());
+ assertEquals('value', '2', clone.getValue());
+ assertNull('parent', clone.getParent());
+ assertArrayEquals('children', [], clone.getChildren());
+}
+
+function testDeepClone() {
+ var node1 = new goog.structs.TreeNode(1, '1');
+ var node2 = new goog.structs.TreeNode(2, '2');
+ var node3 = new goog.structs.TreeNode(3, '3');
+ node1.addChild(node2);
+ node2.addChild(node3);
+
+ var clone = node2.deepClone();
+ assertEquals('key', 2, clone.getKey());
+ assertEquals('value', '2', clone.getValue());
+ assertNull('parent', clone.getParent());
+ assertEquals('number of children', 1, clone.getChildren().length);
+ assertEquals('first child key', 3, clone.getChildAt(0).getKey());
+ assertNotEquals('first child has been cloned', node3, clone.getChildAt(0));
+}
+
+function testGetParent() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ node1.addChild(node2);
+ assertEquals('parent', node1, node2.getParent());
+ assertNull('orphan', node1.getParent());
+}
+
+function testIsLeaf() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ node1.addChild(node2);
+ assertFalse('not leaf', node1.isLeaf());
+ assertTrue('leaf', node2.isLeaf());
+}
+
+function testIsLastChild() {
+ var node1 = new goog.structs.TreeNode(1, '1');
+ var node2 = new goog.structs.TreeNode(2, '2');
+ var node3 = new goog.structs.TreeNode(3, '3');
+ node1.addChild(node2);
+ node1.addChild(node3);
+ assertFalse('root', node1.isLastChild());
+ assertFalse('first child out of the two', node2.isLastChild());
+ assertTrue('second child out of the two', node3.isLastChild());
+}
+
+function testGetChildren() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ node1.addChild(node2);
+ assertArrayEquals('1 child', [node2], node1.getChildren());
+ assertArrayEquals('no children', [], node2.getChildren());
+}
+
+function testGetChildAt() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ node1.addChild(node2);
+ assertNull('index too low', node1.getChildAt(-1));
+ assertEquals('first child', node2, node1.getChildAt(0));
+ assertNull('index too high', node1.getChildAt(1));
+ assertNull('no children', node2.getChildAt(0));
+}
+
+function testGetChildCount() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ node1.addChild(node2);
+ assertEquals('child count of root node', 1, node1.getChildCount());
+ assertEquals('child count of leaf node', 0, node2.getChildCount());
+}
+
+function testGetDepth() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ var node3 = new goog.structs.TreeNode(3, null);
+ node1.addChild(node2);
+ node2.addChild(node3);
+ assertEquals('no parent', 0, node1.getDepth());
+ assertEquals('1 ancestor', 1, node2.getDepth());
+ assertEquals('2 ancestors', 2, node3.getDepth());
+}
+
+function testGetAncestors() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ var node3 = new goog.structs.TreeNode(3, null);
+ node1.addChild(node2);
+ node2.addChild(node3);
+ assertArrayEquals('no ancestors', [], node1.getAncestors());
+ assertArrayEquals('2 ancestors', [node2, node1], node3.getAncestors());
+}
+
+function testGetRoot() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ node1.addChild(node2);
+ assertEquals('no ancestors', node1, node1.getRoot());
+ assertEquals('has ancestors', node1, node2.getRoot());
+}
+
+function testGetSubtreeKeys() {
+ var root = new goog.structs.TreeNode('root', null);
+ var child1 = new goog.structs.TreeNode('child1', null);
+ var child2 = new goog.structs.TreeNode('child2', null);
+ var grandchild = new goog.structs.TreeNode('grandchild', null);
+ root.addChild(child1);
+ root.addChild(child2);
+ child1.addChild(grandchild);
+ assertArrayEquals('node hierarchy', ['child1', ['grandchild'], 'child2'],
+ root.getSubtreeKeys());
+}
+
+function testContains() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ var node3 = new goog.structs.TreeNode(3, null);
+ var node4 = new goog.structs.TreeNode(4, null);
+ node1.addChild(node2);
+ node2.addChild(node3);
+ node2.addChild(node4);
+
+ assertTrue('parent', node1.contains(node2));
+ assertTrue('grandparent', node1.contains(node3));
+ assertFalse('child', node2.contains(node1));
+ assertFalse('grandchild', node3.contains(node1));
+ assertFalse('sibling', node3.contains(node4));
+}
+
+function testFindCommonAncestor() {
+ var findCommonAncestor = goog.structs.TreeNode.findCommonAncestor;
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ var node3 = new goog.structs.TreeNode(3, null);
+ var node4 = new goog.structs.TreeNode(4, null);
+ var node5 = new goog.structs.TreeNode(5, null);
+ node1.addChild(node2);
+ node2.addChild(node3);
+ node1.addChild(node4);
+
+ assertNull('0 nodes', findCommonAncestor());
+ assertEquals('1 node', node2, findCommonAncestor(node2));
+ assertEquals('same nodes', node3, findCommonAncestor(node3, node3));
+ assertEquals('node and child node', node2, findCommonAncestor(node2, node3));
+ assertEquals('node and parent node', node1, findCommonAncestor(node2, node1));
+ assertEquals('siblings', node1, findCommonAncestor(node2, node4));
+ assertEquals('all nodes', node1,
+ findCommonAncestor(node2, node3, node4, node1));
+ assertNull('disconnected nodes', findCommonAncestor(node3, node5));
+}
+
+function testForEachChild() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ var node3 = new goog.structs.TreeNode(3, null);
+ node1.addChild(node2);
+ node1.addChild(node3);
+
+ var thisContext = {};
+ var visitedNodes = [];
+ var indices = [];
+ node1.forEachChild(function(node, index, children) {
+ assertEquals('value of this', thisContext, this);
+ visitedNodes.push(node);
+ indices.push(index);
+ assertArrayEquals('children argument', [node2, node3], children);
+ }, thisContext);
+ assertArrayEquals('visited nodes', [node2, node3], visitedNodes);
+ assertArrayEquals('index of visited nodes', [0, 1], indices);
+}
+
+function testForEachDescendant() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ var node3 = new goog.structs.TreeNode(3, null);
+ var node4 = new goog.structs.TreeNode(4, null);
+ node1.addChild(node2);
+ node2.addChild(node3);
+ node2.addChild(node4);
+
+ var thisContext = {};
+ var visitedNodes = [];
+ node1.forEachDescendant(function(node) {
+ assertEquals('value of this', thisContext, this);
+ visitedNodes.push(node);
+ }, thisContext);
+ assertArrayEquals('visited nodes', [node2, node3, node4], visitedNodes);
+}
+
+function testTraverse() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ var node3 = new goog.structs.TreeNode(3, null);
+ var node4 = new goog.structs.TreeNode(4, null);
+ node1.addChild(node2);
+ node2.addChild(node3);
+ node2.addChild(node4);
+
+ var thisContext = {};
+ var visitedNodes = [];
+ node1.traverse(function(node) {
+ assertEquals('value of this', thisContext, this);
+ visitedNodes.push(node);
+ }, thisContext);
+ assertArrayEquals('callback returns nothing => all nodes are visited',
+ [node1, node2, node3, node4], visitedNodes);
+
+ visitedNodes = [];
+ node1.traverse(function(node) {
+ visitedNodes.push(node);
+ return node != node2; // Cut off at node2.
+ });
+ assertArrayEquals('children of node2 are skipped',
+ [node1, node2], visitedNodes);
+}
+
+function testAddChild() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ var node3 = new goog.structs.TreeNode(3, null);
+ assertArrayEquals('0 children', [], node1.getChildren());
+ node1.addChild(node2);
+ assertArrayEquals('1 child', [node2], node1.getChildren());
+ assertEquals('parent is set', node1, node2.getParent());
+ node1.addChild(node3);
+ assertArrayEquals('2 children', [node2, node3], node1.getChildren());
+}
+
+function testAddChildAt() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ var node3 = new goog.structs.TreeNode(3, null);
+ var node4 = new goog.structs.TreeNode(4, null);
+ var node5 = new goog.structs.TreeNode(5, null);
+ node1.addChildAt(node2, 0);
+ assertArrayEquals('add first child', [node2], node1.getChildren());
+ assertEquals('parent is set', node1, node2.getParent());
+ node1.addChildAt(node3, 0);
+ assertArrayEquals('add to the front', [node3, node2],
+ node1.getChildren());
+ node1.addChildAt(node4, 1);
+ assertArrayEquals('add to the middle', [node3, node4, node2],
+ node1.getChildren());
+ node1.addChildAt(node5, 3);
+ assertArrayEquals('add to the end', [node3, node4, node2, node5],
+ node1.getChildren());
+}
+
+function testReplaceChildAt() {
+ var root = new goog.structs.TreeNode(0, null);
+ var node1 = new goog.structs.TreeNode(1, null);
+ root.addChild(node1);
+
+ var node2 = new goog.structs.TreeNode(2, null);
+ assertEquals('original node', node1, root.replaceChildAt(node2, 0));
+ assertEquals('parent is set', root, node2.getParent());
+ assertArrayEquals('children are updated', [node2], root.getChildren());
+ assertNull('old child node is detached', node1.getParent());
+}
+
+function testReplaceChild() {
+ var root = new goog.structs.TreeNode(0, null);
+ var node1 = new goog.structs.TreeNode(1, null);
+ root.addChild(node1);
+
+ var node2 = new goog.structs.TreeNode(2, null);
+ assertEquals('original node', node1, root.replaceChild(node2, node1));
+ assertEquals('parent is set', root, node2.getParent());
+ assertArrayEquals('children are updated', [node2], root.getChildren());
+ assertNull('old child node is detached', node1.getParent());
+}
+
+function testRemoveChildAt() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ var node3 = new goog.structs.TreeNode(3, null);
+ node1.addChild(node2);
+ node1.addChild(node3);
+
+ assertNull('index too low', node1.removeChildAt(-1));
+ assertNull('index too high', node1.removeChildAt(2));
+ assertArrayEquals('node1 is intact', [node2, node3], node1.getChildren());
+
+ assertEquals('remove first child', node2, node1.removeChildAt(0));
+ assertArrayEquals('remove from the front', [node3], node1.getChildren());
+ assertNull('parent is unset', node2.getParent());
+
+ assertEquals('remove last child', node3, node1.removeChildAt(0));
+ assertArrayEquals('remove last child', [], node1.getChildren());
+ assertTrue('node1 became leaf', node1.isLeaf());
+}
+
+function testRemoveChild() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ var node3 = new goog.structs.TreeNode(3, null);
+ node1.addChild(node2);
+ node1.addChild(node3);
+
+ assertNull('remove null', node1.removeChild(null));
+ assertNull('remove non-child', node1.removeChild(node1));
+ assertArrayEquals('node1 is intact', [node2, node3], node1.getChildren());
+
+ assertEquals('remove node3, return value', node3, node1.removeChild(node3));
+ assertArrayEquals('node is removed', [node2], node1.getChildren());
+}
+
+function testRemoveChildren() {
+ var node1 = new goog.structs.TreeNode(1, null);
+ var node2 = new goog.structs.TreeNode(2, null);
+ var node3 = new goog.structs.TreeNode(3, null);
+ node1.addChild(node2);
+ node1.addChild(node3);
+
+ node2.removeChildren();
+ assertArrayEquals('removing a leaf node\'s children has no effect', [],
+ node2.getChildren());
+ assertEquals('node still has parent', node1, node2.getParent());
+
+ node1.removeChildren();
+ assertArrayEquals('children have been removed', [], node1.getChildren());
+ assertNull('children\'s parents have been unset', node2.getParent());
+}
+
+</script>
+</body>
+</html>
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/trie.js b/contexts/data/lib/closure-library/closure/goog/structs/trie.js
new file mode 100644
index 0000000..bf365b0
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/trie.js
@@ -0,0 +1,368 @@
+// Copyright 2007 The Closure Library Authors. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS-IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/**
+ * @fileoverview Datastructure: Trie.
+ *
+ *
+ * This file provides the implementation of a trie data structure. A trie is a
+ * data structure that stores key/value pairs in a prefix tree. See:
+ * http://en.wikipedia.org/wiki/Trie
+ */
+
+
+goog.provide('goog.structs.Trie');
+
+goog.require('goog.object');
+goog.require('goog.structs');
+
+
+
+/**
+ * Class for a Trie datastructure. Trie data structures are made out of trees
+ * of Trie classes.
+ *
+ * @param {Object=} opt_trie Optional goog.structs.Trie or Object to initialize
+ * trie with.
+ * @constructor
+ */
+goog.structs.Trie = function(opt_trie) {
+ /**
+ * This trie's child nodes.
+ * @private
+ * @type {Object.<goog.structs.Trie>}
+ */
+ this.childNodes_ = {};
+
+ if (opt_trie) {
+ this.setAll(opt_trie);
+ }
+};
+
+
+/**
+ * This trie's value. For the base trie, this will be the value of the
+ * empty key, if defined.
+ * @private
+ * @type {*}
+ */
+goog.structs.Trie.prototype.value_ = undefined;
+
+
+/**
+ * Sets the given key/value pair in the trie. O(L), where L is the length
+ * of the key.
+ * @param {string} key The key.
+ * @param {*} value The value.
+ */
+goog.structs.Trie.prototype.set = function(key, value) {
+ this.setOrAdd_(key, value, false);
+};
+
+
+/**
+ * Adds the given key/value pair in the trie. Throw an exception if the key
+ * already exists in the trie. O(L), where L is the length of the key.
+ * @param {string} key The key.
+ * @param {*} value The value.
+ */
+goog.structs.Trie.prototype.add = function(key, value) {
+ this.setOrAdd_(key, value, true);
+};
+
+
+/**
+ * Helper function for set and add. Adds the given key/value pair to
+ * the trie, or, if the key already exists, sets the value of the key. If
+ * opt_add is true, then throws an exception if the key already has a value in
+ * the trie. O(L), where L is the length of the key.
+ * @param {string} key The key.
+ * @param {*} value The value.
+ * @param {boolean=} opt_add Throw exception if key is already in the trie.
+ * @private
+ */
+goog.structs.Trie.prototype.setOrAdd_ = function(key, value, opt_add) {
+ var node = this;
+ for (var characterPosition = 0; characterPosition < key.length;
+ characterPosition++) {
+ var currentCharacter = key.charAt(characterPosition);
+ if (!node.childNodes_[currentCharacter]) {
+ node.childNodes_[currentCharacter] = new goog.structs.Trie();
+ }
+ node = node.childNodes_[currentCharacter];
+ }
+ if (opt_add && node.value_ !== undefined) {
+ throw Error('The collection already contains the key "' + key + '"');
+ } else {
+ node.value_ = value;
+ }
+};
+
+
+/**
+ * Adds multiple key/value pairs from another goog.structs.Trie or Object.
+ * O(N) where N is the number of nodes in the trie.
+ * @param {Object|goog.structs.Trie} trie Object containing the data to add.
+ */
+goog.structs.Trie.prototype.setAll = function(trie) {
+ var keys = goog.structs.getKeys(trie);
+ var values = goog.structs.getValues(trie);
+
+ for (var i = 0; i < keys.length; i++) {
+ this.set(keys[i], values[i]);
+ }
+};
+
+
+/**
+ * Retrieves a value from the trie given a key. O(L), where L is the length of
+ * the key.
+ * @param {string} key The key to retrieve from the trie.
+ * @return {*} The value of the key in the trie, or undefined if the trie does
+ * not contain this key.
+ */
+goog.structs.Trie.prototype.get = function(key) {
+ var node = this;
+ for (var characterPosition = 0; characterPosition < key.length;
+ characterPosition++) {
+ var currentCharacter = key.charAt(characterPosition);
+ if (!node.childNodes_[currentCharacter]) {
+ return undefined;
+ }
+ node = node.childNodes_[currentCharacter];
+ }
+ return node.value_;
+};
+
+
+/**
+ * Retrieves all values from the trie that correspond to prefixes of the given
+ * input key. O(L), where L is the length of the key.
+ *
+ * @param {string} key The key to use for lookup. The given key as well as all
+ * prefixes of the key are retrieved.
+ * @param {?number=} opt_keyStartIndex Optional position in key to start lookup
+ * from. Defaults to 0 if not specified.
+ * @return {Object} Map of end index of matching prefixes and corresponding
+ * values. Empty if no match found.
+ */
+goog.structs.Trie.prototype.getKeyAndPrefixes = function(key,
+ opt_keyStartIndex) {
+ var node = this;
+ var matches = {};
+ var characterPosition = opt_keyStartIndex || 0;
+
+ if (node.value_ !== undefined) {
+ matches[characterPosition] = node.value_;
+ }
+
+ for (; characterPosition < key.length; characterPosition++) {
+ var currentCharacter = key.charAt(characterPosition);
+ if (!(currentCharacter in node.childNodes_)) {
+ break;
+ }
+ node = node.childNodes_[currentCharacter];
+ if (node.value_ !== undefined) {
+ matches[characterPosition] = node.value_;
+ }
+ }
+
+ return matches;
+};
+
+
+/**
+ * Gets the values of the trie. Not returned in any reliable order. O(N) where
+ * N is the number of nodes in the trie. Calls getValuesInternal_.
+ * @return {Array} The values in the trie.
+ */
+goog.structs.Trie.prototype.getValues = function() {
+ var allValues = [];
+ this.getValuesInternal_(allValues);
+ return allValues;
+};
+
+
+/**
+ * Gets the values of the trie. Not returned in any reliable order. O(N) where
+ * N is the number of nodes in the trie. Builds the values as it goes.
+ * @param {Array.<string>} allValues Array to place values into.
+ * @private
+ */
+goog.structs.Trie.prototype.getValuesInternal_ = function(allValues) {
+ if (this.value_ !== undefined) {
+ allValues.push(this.value_);
+ }
+ for (var childNode in this.childNodes_) {
+ this.childNodes_[childNode].getValuesInternal_(allValues);
+ }
+};
+
+
+/**
+ * Gets the keys of the trie. Not returned in any reliable order. O(N) where
+ * N is the number of nodes in the trie (or prefix subtree).
+ * @param {string=} opt_prefix Find only keys with this optional prefix.
+ * @return {Array} The keys in the trie.
+ */
+goog.structs.Trie.prototype.getKeys = function(opt_prefix) {
+ var allKeys = [];
+ if (opt_prefix) {
+ // Traverse to the given prefix, then call getKeysInternal_ to dump the
+ // keys below that point.
+ var node = this;
+ for (var characterPosition = 0; characterPosition < opt_prefix.length;
+ characterPosition++) {
+ var currentCharacter = opt_prefix.charAt(characterPosition);
+ if (!node.childNodes_[currentCharacter]) {
+ return [];
+ }
+ node = node.childNodes_[currentCharacter];
+ }
+ node.getKeysInternal_(opt_prefix, allKeys);
+ } else {
+ this.getKeysInternal_('', allKeys);
+ }
+ return allKeys;
+};
+
+
+/**
+ * Private method to get keys from the trie. Builds the keys as it goes.
+ * @param {string} keySoFar The partial key (prefix) traversed so far.
+ * @param {Array} allKeys The partially built array of keys seen so far.
+ * @private
+ */
+goog.structs.Trie.prototype.getKeysInternal_ = function(keySoFar, allKeys) {
+ if (this.value_ !== undefined) {
+ allKeys.push(keySoFar);
+ }
+ for (var childNode in this.childNodes_) {
+ this.childNodes_[childNode].getKeysInternal_(keySoFar + childNode, allKeys);
+ }
+};
+
+
+/**
+ * Checks to see if a certain key is in the trie. O(L), where L is the length
+ * of the key.
+ * @param {string} key A key that may be in the trie.
+ * @return {boolean} Whether the trie contains key.
+ */
+goog.structs.Trie.prototype.containsKey = function(key) {
+ return this.get(key) !== undefined;
+};
+
+
+/**
+ * Checks to see if a certain value is in the trie. Worst case is O(N) where
+ * N is the number of nodes in the trie.
+ * @param {*} value A value that may be in the trie.
+ * @return {boolean} Whether the trie contains the value.
+ */
+goog.structs.Trie.prototype.containsValue = function(value) {
+ if (this.value_ === value) {
+ return true;
+ }
+ for (var childNode in this.childNodes_) {
+ if (this.childNodes_[childNode].containsValue(value)) {
+ return true;
+ }
+ }
+ return false;
+};
+
+
+/**
+ * Completely empties a trie of all keys and values. ~O(1)
+ */
+goog.structs.Trie.prototype.clear = function() {
+ this.childNodes_ = {};
+ this.value_ = undefined;
+};
+
+
+/**
+ * Removes a key from the trie or throws an exception if the key is not in the
+ * trie. O(L), where L is the length of the key.
+ * @param {string} key A key that should be removed from the trie.
+ * @return {*} The value whose key was removed.
+ */
+goog.structs.Trie.prototype.remove = function(key) {
+ var node = this;
+ var parents = [];
+ for (var characterPosition = 0; characterPosition < key.length;
+ characterPosition++) {
+ var currentCharacter = key.charAt(characterPosition);
+ if (!node.childNodes_[currentCharacter]) {
+ throw Error('The collection does not have the key "' + key + '"');
+ }
+
+ // Archive the current parent and child name (key in childNodes_) so that
+ // we may remove the following node and its parents if they are empty.
+ parents.push([node, currentCharacter]);
+
+ node = node.childNodes_[currentCharacter];
+ }
+ var oldValue = node.value_;
+ delete node.value_;
+
+ while (parents.length > 0) {
+ var currentParentAndCharacter = parents.pop();
+ var currentParent = currentParentAndCharacter[0];
+ var currentCharacter = currentParentAndCharacter[1];
+ if (goog.object.isEmpty(
+ currentParent.childNodes_[currentCharacter].childNodes_)) {
+ // If we have no child nodes, then remove this node.
+ delete currentParent.childNodes_[currentCharacter];
+ } else {
+ // No point of traversing back any further, since we can't remove this
+ // path.
+ break;
+ }
+ }
+ return oldValue;
+};
+
+
+/**
+ * Clones a trie and returns a new trie. O(N), where N is the number of nodes
+ * in the trie.
+ * @return {goog.structs.Trie} A new goog.structs.Trie with the same key value
+ * pairs.
+ */
+goog.structs.Trie.prototype.clone = function() {
+ return new goog.structs.Trie(this);
+};
+
+
+/**
+ * Returns the number of key value pairs in the trie. O(N), where N is the
+ * number of nodes in the trie.
+ * TODO: This could be optimized by storing a weight (count below) in every
+ * node.
+ * @return {number} The number of pairs.
+ */
+goog.structs.Trie.prototype.getCount = function() {
+ return goog.structs.getCount(this.getValues());
+};
+
+
+/**
+ * Returns true if this trie contains no elements. ~O(1).
+ * @return {boolean} True iff this trie contains no elements.
+ */
+goog.structs.Trie.prototype.isEmpty = function() {
+ return this.value_ === undefined && goog.structs.isEmpty(this.childNodes_);
+};
diff --git a/contexts/data/lib/closure-library/closure/goog/structs/trie_test.html b/contexts/data/lib/closure-library/closure/goog/structs/trie_test.html
new file mode 100644
index 0000000..3b180a5
--- /dev/null
+++ b/contexts/data/lib/closure-library/closure/goog/structs/trie_test.html
@@ -0,0 +1,378 @@
+<!DOCTYPE html>
+<html>
+<!--
+Copyright 2007 The Closure Library Authors. All Rights Reserved.
+
+Use of this source code is governed by the Apache License, Version 2.0.
+See the COPYING file for details.
+-->
+<!--
+-->
+<head>
+<meta http-equiv="X-UA-Compatible" content="IE=edge">
+<title>Closure Unit Tests - goog.structs.Trie</title>
+</script>
+<script src="../base.js"></script>
+<script>
+ goog.require('goog.object');
+ goog.require('goog.structs');
+ goog.require('goog.structs.Trie');
+ goog.require('goog.testing.jsunit');
+</script>
+</head>
+<body>
+<script>
+
+function makeTrie() {
+ var trie = new goog.structs.Trie();
+ trie.add('hello', 1);
+ trie.add('hi', 'howdy');
+ trie.add('', 'an empty string key');
+ trie.add('empty value', '');
+ trie.add('zero', 0);
+ trie.add('object', {});
+ trie.add('null', null);
+ trie.add('hello, world', 2);
+ trie.add('world', {});
+ return trie;
+}
+
+function checkTrie(trie) {
+ assertEquals('get, should be 1', trie.get('hello'), 1);
+ assertEquals('get, should be "howdy"', trie.get('hi'), 'howdy');
+ assertEquals('get, should be "an empty string key"', trie.get(''),
+ 'an empty string key');
+ assertEquals('get, should be ""', trie.get('empty value'), '');
+ assertEquals('get, should be ""', typeof trie.get('empty value'), 'string');
+ assertEquals('get, should be an object', typeof trie.get('object'), 'object');
+ assertEquals('get, should be 0', trie.get('zero'), 0);
+ assertEquals('get "null", should be null', trie.get('null'), null);
+ assertEquals('get, should be 2', trie.get('hello, world'), 2);
+ assertEquals('get, should be an object', typeof trie.get('world'), 'object');
+}
+
+function testTrieFormation() {
+ var t = makeTrie();
+ checkTrie(t);
+}
+
+function testFailureOfMultipleAdds() {
+ var t = new goog.structs.Trie();
+ t.add('hello', 'testing');
+ assertThrows('Error should be thrown when same key added twice.', function() {
+ t.add('hello', 'test');
+ });
+
+ t = new goog.structs.Trie();
+ t.add('null', null);
+ assertThrows('Error should be thrown when same key added twice.', function() {
+ t.add('null', 'hi!');
+ });
+
+ t = new goog.structs.Trie();
+ t.add('null', 'blah');
+ assertThrows('Error should be thrown when same key added twice.', function() {
+ t.add('null', null);
+ });
+}
+
+function testTrieClone() {
+ var trieOne = makeTrie();
+ var trieTwo = new goog.structs.Trie(trieOne);
+ checkTrie(trieTwo);
+}
+
+function testTrieFromObject() {
+ var someObject = {'hello' : 1,
+ 'hi' : 'howdy',
+ '' : 'an empty string key',
+ 'empty value' : '',
+ 'object' : {},
+ 'zero' : 0,
+ 'null' : null,
+ 'hello, world' : 2,
+ 'world' : {}};
+ var trie = new goog.structs.Trie(someObject);
+ checkTrie(trie);
+}
+
+function testTrieGetValues() {
+ var trie = makeTrie();
+ var values = trie.getValues();
+ assertTrue('getValues, should contain "howdy"',
+ goog.object.contains(values, 'howdy'));
+ assertTrue('getValues, should contain 1', goog.object.contains(values, 1));
+ assertTrue('getValues, should contain 0', goog.object.contains(values, 0));
+ assertTrue('getValues, should contain ""', goog.object.contains(values, ''));
+ assertTrue('getValues, should contain null',
+ goog.object.contains(values, null));
+ assertEquals('goog.structs.getCount(getValues()) should be 9',
+ goog.structs.getCount(values), 9);
+}
+
+function testTrieGetKeys() {
+ var trie = makeTrie();
+ var keys = trie.getKeys();
+ assertTrue('getKeys, should contain "hello"',
+ goog.object.contains(keys, 'hello'));
+ assertTrue('getKeys, should contain "empty value"',
+ goog.object.contains(keys, 'empty value'));
+ assertTrue('getKeys, should contain ""', goog.object.contains(keys, ''));
+ assertTrue('getKeys, should contain "zero"',
+ goog.object.contains(keys, 'zero'));
+ assertEquals('goog.structs.getCount(getKeys()) should be 9',
+ goog.structs.getCount(keys), 9);
+}
+
+
+function testTrieCount() {
+ var trieOne = makeTrie();
+ var trieTwo = new goog.structs.Trie();
+ assertEquals('count, should be 9', trieOne.getCount(), 9);
+ assertEquals('count, should be 0', trieTwo.getCount(), 0);
+}
+
+function testRemoveKeyFromTrie() {
+ var trie = new goog.structs.Trie();
+ trie.add('key1', 'value1');
+ trie.add('key2', 'value2');
+ trie.add('ke', 'value3');
+ trie.add('zero', 0);
+ trie.remove('key2');
+ assertEquals('get "key1", should be "value1"', trie.get('key1'), 'value1');
+ assertUndefined('get "key2", should be undefined', trie.get('key2'));
+ trie.remove('zero');
+ assertUndefined('get "zero", should be undefined', trie.get('zero'));
+ trie.remove('ke');
+ assertUndefined('get "ke", should be undefined', trie.get('ke'));
+ assertEquals('get "key1", should be "value1"', trie.get('key1'), 'value1');
+ trie.add('a', 'value4');
+ assertTrue('testing internal structure, a should be a child',
+ 'a' in trie.childNodes_);
+ trie.remove('a');
+ assertFalse('testing internal structure, a should no longer be a child',
+ 'a' in trie.childNodes_);
+
+ trie.add('xyza', 'value');
+ trie.remove('xyza', 'value');
+ assertFalse('Should not have "x"', 'x' in trie.childNodes_);
+
+ trie.add('xyza', null);
+ assertTrue('Should have "x"', 'x' in trie.childNodes_);
+ trie.remove('xyza');
+ assertFalse('Should not have "x"', 'x' in trie.childNodes_);
+
+ trie.add('xyza', 'value');
+ trie.add('xb', 'value');
+ trie.remove('xyza');
+ assertTrue('get "x" should be defined', 'x' in trie.childNodes_);
+ assertFalse('get "y" should be undefined',
+ 'y' in trie.childNodes_['x'].childNodes_);
+}
+
+function testRemoveKeyFromTrieWithNulls() {
+ var trie = new goog.structs.Trie();
+ trie.add('key1', null);
+ trie.add('key2', 'value2');
+ trie.add('ke', 'value3');
+ trie.add('zero', 0);
+ trie.remove('key2');
+ assertEquals('get "key1", should be null', trie.get('key1'), null);
+ assertUndefined('get "key2", should be undefined', trie.get('key2'));
+ trie.remove('zero');
+ assertUndefined('get "zero", should be undefined', trie.get('zero'));
+ trie.remove('ke');
+ assertUndefined('get "ke", should be undefined', trie.get('ke'));
+ assertEquals('get "key1", should be null', trie.get('key1'), null);
+ trie.add('a', 'value4');
+ assertTrue('testing internal structure, a should be a child',
+ 'a' in trie.childNodes_);
+ trie.remove('a');
+ assertFalse('testing internal structure, a should no longer be a child',
+ 'a' in trie.childNodes_);
+
+ trie.add('xyza', null);
+ trie.add('xb', 'value');
+ trie.remove('xyza');
+ assertTrue('Should have "x"', 'x' in trie.childNodes_);
+ assertFalse('Should not have "y"',
+ 'y' in trie.childNodes_['x'].childNodes_);
+}
+
+function testRemoveKeyException() {
+ var trie = new goog.structs.Trie();
+ trie.add('abcdefg', 'value');
+ trie.add('abcz', 'value');
+ trie.add('abc', 'value');
+
+ assertThrows('Remove should throw an error on removal of non-existent key',
+ function() {
+ trie.remove('abcdefge');
+ });
+}
+
+function testTrieIsEmpty() {
+ var trieOne = new goog.structs.Trie();
+ var trieTwo = makeTrie();
+ assertTrue('isEmpty, should be empty', trieOne.isEmpty());
+ assertFalse('isEmpty, should not be empty', trieTwo.isEmpty());
+ trieOne.add('', 1);
+ assertFalse('isEmpty, should not be empty', trieTwo.isEmpty());
+ trieOne.remove('');
+ assertTrue('isEmpty, should be empty', trieOne.isEmpty());
+ trieOne.add('', 1);
+ trieOne.add('a', 1);
+ trieOne.remove('a');
+ assertFalse('isEmpty, should not be empty', trieOne.isEmpty());
+ trieOne.remove('');
+ assertTrue('isEmpty, should be empty', trieOne.isEmpty());
+ trieOne.add('', 1);
+ trieOne.add('a', 1);
+ trieOne.remove('');
+ assertFalse('isEmpty, should not be empty', trieOne.isEmpty());
+ trieOne.remove('a');
+ assertTrue('isEmpty, should be empty', trieOne.isEmpty());
+}
+
+function testTrieClear() {
+ var trie = new goog.structs.Trie();
+ trie.add('key1', 'value1');
+ trie.add('key2', 'value2');
+ trie.add('key3', null);
+ trie.clear();
+ assertUndefined('get key1, should be undefined', trie.get('key1'));
+ assertUndefined('get key2, should be undefined', trie.get('key2'));
+ assertUndefined('get key3, should be undefined', trie.get('key3'));
+}
+
+function testTrieContainsKey() {
+ var trie = makeTrie();
+ assertTrue('containsKey, should contain "hello"', trie.containsKey('hello'));
+ assertTrue('containsKey, should contain "hi"', trie.containsKey('hi'));
+ assertTrue('containsKey, should contain ""', trie.containsKey(''));
+ assertTrue('containsKey, should contain "empty value"',
+ trie.containsKey('empty value'));
+ assertTrue('containsKey, should contain "object"',
+ trie.containsKey('object'));
+ assertTrue('containsKey, should contain "zero"', trie.containsKey('zero'));
+ assertTrue('containsKey, should contain "null"', trie.containsKey('null'));
+ assertFalse('containsKey, should not contain "blah"',
+ trie.containsKey('blah'));
+ trie.remove('');
+ trie.remove('hi');
+ trie.remove('zero');
+ trie.remove('null');
+ assertFalse('containsKey, should not contain "zero"',
+ trie.containsKey('zero'));
+ assertFalse('containsKey, should not contain ""', trie.containsKey(''));
+ assertFalse('containsKey, should not contain "hi"', trie.containsKey('hi'));
+ assertFalse('containsKey, should not contain "null"',
+ trie.containsKey('null'));
+}
+
+function testTrieContainsValue() {
+ var trie = makeTrie();
+ assertTrue('containsValue, should be true, should contain 1',
+ trie.containsValue(1));
+ assertTrue('containsValue, should be true, should contain "howdy"',
+ trie.containsValue('howdy'));
+ assertTrue('containsValue, should be true, should contain ""',
+ trie.containsValue(''));
+ assertTrue('containsValue, should be true, should contain 0',
+ trie.containsValue(0));
+ assertTrue('containsValue, should be true, should contain null',
+ trie.containsValue(null));
+ assertTrue('containsValue, should be true, should ' +
+ 'contain "an empty string key"',
+ trie.containsValue('an empty string key'));
+ assertFalse('containsValue, should be false, should not contain "blah"',
+ trie.containsValue('blah'));
+ trie.remove('empty value');
+ trie.remove('zero');
+ assertFalse('containsValue, should be false, should not contain 0',
+ trie.containsValue(0));
+ assertFalse('containsValue, should be false, should not contain ""',
+ trie.containsValue(''));
+}
+
+function testTrieHandlingOfEmptyStrings() {
+ var trie = new goog.structs.Trie();
+ assertEquals('get, should be undefined', trie.get(''), undefined);
+ assertFalse('containsValue, should be false', trie.containsValue(''));
+ assertFalse('containsKey, should be false', trie.containsKey(''));
+ trie.add('', 'test');
+ trie.add('test2', '');
+ assertTrue('containsValue, should be true', trie.containsValue(''));
+ assertTrue('containsKey, should be true', trie.containsKey(''));
+ assertEquals('get, should be "test"', trie.get(''), 'test');
+ assertEquals('get, should be ""', trie.get('test2'), '');
+ trie.remove('');
+ trie.remove('test2');
+ assertEquals('get, should be undefined', trie.get(''), undefined);
+ assertFalse('containsValue, should be false', trie.containsValue(''));
+ assertFalse('containsKey, should be false', trie.containsKey(''));
+}
+
+function testPrefixOptionOnGetKeys() {
+ var trie = new goog.structs.Trie();
+ trie.add('abcdefg', 'one');
+ trie.add('abcdefghijk', 'two');
+ trie.add('abcde', 'three');
+ trie.add('abcq', null);
+ trie.add('abc', 'four');
+ trie.add('xyz', 'five');
+ assertEquals('getKeys, should be 1', trie.getKeys('xy').length, 1);
+ assertEquals('getKeys, should be 1', trie.getKeys('xyz').length, 1);
+ assertEquals('getKeys, should be 1', trie.getKeys('x').length, 1);
+ assertEquals('getKeys, should be 4', trie.getKeys('abc').length, 5);
+ assertEquals('getKeys, should be 2', trie.getKeys('abcdef').length, 2);
+ assertEquals('getKeys, should be 0', trie.getKeys('abcdefgi').length, 0);
+}
+
+function testGetKeyAndPrefixes() {
+ var trie = makeTrie();
+ // Note: trie has one of its keys as ''
+ assertEquals('getKeyAndPrefixes, should be 2',
+ 2,
+ goog.object.getCount(trie.getKeyAndPrefixes('world')));
+ assertEquals('getKeyAndPrefixes, should be 2',
+ 2,
+ goog.object.getCount(trie.getKeyAndPrefixes('hello')));
+ assertEquals('getKeyAndPrefixes, should be 2',
+ 2,
+ goog.object.getCount(trie.getKeyAndPrefixes('hello,')));
+ assertEquals('getKeyAndPrefixes, should be 3',
+ 3,
+ goog.object.getCount(trie.getKeyAndPrefixes('hello, world')));
+ assertEquals('getKeyAndPrefixes, should be 1',
+ 1,
+ goog.object.getCount(trie.getKeyAndPrefixes('hell')));
+}
+
+function testGetKeyAndPrefixesStartIndex() {
+ var trie = new goog.structs.Trie();
+ trie.add('abcdefg', 'one');
+ trie.add('bcdefg', 'two');
+ trie.add('abcdefghijk', 'three');
+ trie.add('abcde', 'four');
+ trie.add('abcq', null);
+ trie.add('q', null);
+ trie.add('abc', 'five');
+ trie.add('xyz', 'six');
+ assertEquals('getKeyAndPrefixes, should be 3',
+ 3,
+ goog.object.getCount(trie.getKeyAndPrefixes('abcdefg', 0)));
+ assertEquals('getKeyAndPrefixes, should be 1',
+ 1,
+ goog.object.getCount(trie.getKeyAndPrefixes('abcdefg', 1)));
+ assertEquals('getKeyAndPrefixes, should be 1',
+ 1,
+ goog.object.getCount(trie.getKeyAndPrefixes('abcq', 3)));
+ assertEquals('getKeyAndPrefixes, should be 0',
+ 0,
+ goog.object.getCount(trie.getKeyAndPrefixes('abcd', 3)));
+}
+
+</script>
+</body>
+</html>