-
Notifications
You must be signed in to change notification settings - Fork 12
/
uuTreeWalk.r
145 lines (141 loc) · 5.2 KB
/
uuTreeWalk.r
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# \file uuTreeWalk.r
# \brief Generic function to walk collection trees
# \author Ton Smeele
# \copyright Copyright (c) 2015, Utrecht University. All rights reserved.
# \license GPLv3, see LICENSE.
# \brief Walks through a collection tree and calls an arbitrary rule for each tree-item.
#
# \param[in] direction can be "forward" or "reverse"
# forward means process collection itself, then children
# reverse means process children first
# reverse is useful e.g. to delete collection trees
# \param[in] topLevelCollection pathname of the root of the tree, must be collection
# NB: the root itself is also processed
# \param[in] ruleToProcess name of the rule that can perform an action on tree items
# Requirement: rule must be preloaded in rulebase
# The rule should expect the following parameters:
# itemParent = full iRODS path to the parent of this object
# itemName = basename of collection or dataobject
# itemIsCollection = true if the item is a collection
# buffer = in/out Key-Value variable
# the buffer is maintained by treewalk and passed
# on to the processing rule. can be used by the rule
# to communicate data to subsequent rule invocations
# buffer."error" can be updated by the rule to indicate
# an error, the treewalk will stop
# \param[in/out] buffer an arbitrary buffer variable that is passed on to the rule
# \param[out] error error result as may be set by the rule that is processed
# a value of 0 means no error
# other values indicate an error and process is interrupted
#
uuTreeWalk(*direction, *topLevelCollection, *ruleToProcess, *buffer, *error) {
*error = 0;
# start walking at the root of the tree...
uuTreeWalkCollection(
*direction,
*topLevelCollection,
*buffer,
*ruleToProcess,
*error
);
}
# \brief Walk a subtree.
#
# \param [in] direction can be "forward" or "reverse"
# \param [in] path
# \param [in/out] buffer (exclusively to be used by the rule we will can)
# \param [in] rule name of the rule to be executed in the context of a tree-item
# \param [out] error 0 if ok else nonzero
#
uuTreeWalkCollection(
*direction,
*path,
*buffer,
*ruleToProcess,
*error
) {
uuChopPath(*path, *parentCollection, *collection);
if (*direction == "forward") {
# first process this collection itself
if (*error == 0) {
# ugly: need to use many if's, irods offers no means to break to end of action
eval("{ *ruleToProcess(\*parentCollection,\*collection,true,\*buffer,\*error); }");
}
# and the dataobjects located directly within the collection
if (*error == 0 ) {
foreach (*row in SELECT DATA_NAME WHERE COLL_NAME = *path) {
msiGetValByKey(*row, "DATA_NAME", *dataObject);
eval("{ *ruleToProcess(\*path,\*dataObject,false,\*buffer,\*error); }");
if (*error != 0 ) {
break;
}
}
}
if (*error == 0 ) {
# then increase depth to walk through the subcollections
*listList = list();
*list = list();
foreach (*row in SELECT ORDER_DESC(COLL_NAME) WHERE COLL_PARENT_NAME = *path) {
msiGetValByKey(*row, "COLL_NAME", *subCollectionPath);
if (size(*list) == 100) {
*listList = cons(*list, *listList);
*list = list();
}
*list = cons(*subCollectionPath, *list);
}
*listList = cons(*list, *listList);
foreach(*list in *listList) {
foreach (*subCollectionPath in *list) {
uuTreeWalkCollection(
*direction,
*subCollectionPath,
*buffer,
*ruleToProcess,
*error
);
}
}
}
}
if (*direction == "reverse") {
# first deal with any subcollections within this collection
if (*error == 0) {
*listList = list();
*list = list();
foreach (*row in SELECT ORDER_DESC(COLL_NAME) WHERE COLL_PARENT_NAME = *path) {
msiGetValByKey(*row, "COLL_NAME", *subCollectionPath);
if (size(*list) == 100) {
*listList = cons(*list, *listList);
*list = list();
}
*list = cons(*subCollectionPath, *list);
}
*listList = cons(*list, *listList);
foreach(*list in *listList) {
foreach (*subCollectionPath in *list) {
uuTreeWalkCollection(
*direction,
*subCollectionPath,
*buffer,
*ruleToProcess,
*error
);
}
}
}
# when done then process the dataobjects directly located within this collection
if (*error == 0) {
foreach (*row in SELECT DATA_NAME WHERE COLL_NAME = *path) {
msiGetValByKey(*row, "DATA_NAME", *dataObject);
eval("{ *ruleToProcess(\*path,\*dataObject,false,\*buffer,\*error); }");
if (*error != 0 ) {
break;
}
}
}
# and lastly process the collection itself
if (*error == 0) {
eval("{ *ruleToProcess(\*parentCollection,\*collection,true,\*buffer,\*error); }");
}
}
}