fabulator 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/History.txt +4 -0
  2. data/Manifest.txt +41 -0
  3. data/README.rdoc +61 -0
  4. data/Rakefile +54 -0
  5. data/lib/fabulator.rb +5 -0
  6. data/lib/fabulator/action.rb +46 -0
  7. data/lib/fabulator/action_lib.rb +438 -0
  8. data/lib/fabulator/context.rb +39 -0
  9. data/lib/fabulator/core.rb +8 -0
  10. data/lib/fabulator/core/actions.rb +514 -0
  11. data/lib/fabulator/core/actions/choose.rb +167 -0
  12. data/lib/fabulator/core/actions/for_each.rb +105 -0
  13. data/lib/fabulator/core/actions/variables.rb +52 -0
  14. data/lib/fabulator/core/constraint.rb +117 -0
  15. data/lib/fabulator/core/filter.rb +41 -0
  16. data/lib/fabulator/core/group.rb +123 -0
  17. data/lib/fabulator/core/parameter.rb +128 -0
  18. data/lib/fabulator/core/state.rb +91 -0
  19. data/lib/fabulator/core/state_machine.rb +153 -0
  20. data/lib/fabulator/core/transition.rb +164 -0
  21. data/lib/fabulator/expr.rb +37 -0
  22. data/lib/fabulator/expr/axis.rb +133 -0
  23. data/lib/fabulator/expr/axis_descendent_or_self.rb +26 -0
  24. data/lib/fabulator/expr/bin_expr.rb +178 -0
  25. data/lib/fabulator/expr/context.rb +368 -0
  26. data/lib/fabulator/expr/for_expr.rb +74 -0
  27. data/lib/fabulator/expr/function.rb +52 -0
  28. data/lib/fabulator/expr/if_expr.rb +22 -0
  29. data/lib/fabulator/expr/let_expr.rb +17 -0
  30. data/lib/fabulator/expr/literal.rb +39 -0
  31. data/lib/fabulator/expr/node.rb +216 -0
  32. data/lib/fabulator/expr/node_logic.rb +99 -0
  33. data/lib/fabulator/expr/parser.rb +1470 -0
  34. data/lib/fabulator/expr/path_expr.rb +49 -0
  35. data/lib/fabulator/expr/predicates.rb +45 -0
  36. data/lib/fabulator/expr/statement_list.rb +96 -0
  37. data/lib/fabulator/expr/step.rb +43 -0
  38. data/lib/fabulator/expr/unary_expr.rb +30 -0
  39. data/lib/fabulator/expr/union_expr.rb +21 -0
  40. data/lib/fabulator/template.rb +9 -0
  41. data/lib/fabulator/template/context.rb +51 -0
  42. data/lib/fabulator/template/parse_result.rb +153 -0
  43. data/lib/fabulator/template/parser.rb +17 -0
  44. data/lib/fabulator/template/standard_tags.rb +95 -0
  45. data/lib/fabulator/template/taggable.rb +88 -0
  46. data/lib/fabulator/version.rb +14 -0
  47. data/test/test_fabulator.rb +17 -0
  48. data/test/test_helper.rb +24 -0
  49. data/xslt/form.xsl +2161 -0
  50. metadata +182 -0
@@ -0,0 +1,368 @@
1
+ module Fabulator
2
+ module Expr
3
+ class Context
4
+
5
+ def initialize(parent_c = nil, xml = nil)
6
+ @parent = parent_c
7
+ @run_time_parent = nil
8
+ @ns = { }
9
+ @attributes = { }
10
+ @variables = { }
11
+ @position = nil
12
+ @last = nil
13
+
14
+ if parent_c.nil?
15
+ if xml.nil? || (xml.root rescue nil).nil?
16
+ roots = { }
17
+ roots['data'] = Fabulator::Expr::Node.new('data', roots, nil, [])
18
+ @root = roots['data']
19
+ end
20
+ end
21
+
22
+ if !xml.nil?
23
+ if xml.is_a?(self.class)
24
+ @run_time_parent = xml
25
+ else
26
+ parser = Fabulator::Expr::Parser.new
27
+
28
+ xml.namespaces.each do |ns|
29
+ @ns[ns.prefix] = ns.href
30
+ end
31
+ begin
32
+ @ns[''] = xml.namespaces.default.href
33
+ rescue
34
+ end
35
+
36
+ xml.each_attr do |attr|
37
+ v = attr.value
38
+ if !v.nil?
39
+ @attributes[attr.ns.href.to_s] ||= {}
40
+ @attributes[attr.ns.href.to_s][attr.name.to_s] = v
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ def last?
48
+ return @last unless @last.nil?
49
+ return @last if @run_time_parent.nil?
50
+ return @run_time_parent.last?
51
+ end
52
+
53
+ def last=(l)
54
+ @last = !!l
55
+ end
56
+
57
+ def position
58
+ return @position unless @position.nil?
59
+ return @position if @run_time_parent.nil?
60
+ return @run_time_parent.position
61
+ end
62
+
63
+ def position=(p)
64
+ @position = p
65
+ end
66
+
67
+ def merge(s = nil)
68
+ self.class.new(self, s)
69
+ end
70
+
71
+ def attribute(ns, attr, popts = { })
72
+ opts = { :static => !@run_time_parent.nil? && !self.root.nil? }.update(popts)
73
+ value = nil
74
+ if @attributes.nil? || @attributes[ns].nil? || @attributes[ns].empty? || @attributes[ns][attr].nil?
75
+ if opts[:inherited]
76
+ value = @parent.nil? ? nil : @parent.attribute(ns, attr, opts)
77
+ end
78
+ else
79
+ value = @attributes[ns][attr]
80
+ end
81
+ if value.nil? && !opts[:default].nil?
82
+ value = opts[:default]
83
+ end
84
+
85
+ if !value.nil? && value.is_a?(String)
86
+ e = nil
87
+ if !opts[:eval]
88
+ if value =~ /^\{(.*)\}$/
89
+ e = $1
90
+ end
91
+ else
92
+ e = value
93
+ end
94
+ if !e.nil?
95
+ p = Fabulator::Expr::Parser.new
96
+ value = p.parse(e, self)
97
+ else
98
+ value = Fabulator::Expr::Literal.new(value, [ FAB_NS, value =~ /^\d+$/ ? 'numeric' : value =~ /^\d*\.\d+$/ || value =~ /^\d+\.\d*$/ ? 'numeric' : 'string' ])
99
+ end
100
+ if opts[:static]
101
+ value = value.run(self).collect{ |v| v.value }
102
+ if value.empty?
103
+ value = nil
104
+ elsif value.size == 1
105
+ value = value.first
106
+ end
107
+ end
108
+ end
109
+
110
+ value
111
+ end
112
+
113
+ def get_select(default = nil)
114
+ self.attribute(FAB_NS, 'select', { :eval => true, :static => false, :default => default })
115
+ end
116
+
117
+ def with_root(r)
118
+ ctx = self.class.new(self)
119
+ ctx.root = r
120
+ ctx
121
+ end
122
+
123
+ def root
124
+ if @root.nil?
125
+ return @run_time_parent.nil? ?
126
+ ( @parent.nil? ? nil : @parent.root ) : @run_time_parent.root
127
+ end
128
+ @root
129
+ end
130
+
131
+ def root=(r)
132
+ @root = r
133
+ end
134
+
135
+ def get_var(v)
136
+ if !@variables.has_key?(v)
137
+ if @run_time_parent.nil?
138
+ if @parent.nil?
139
+ nil
140
+ else
141
+ @parent.get_var(v)
142
+ end
143
+ else
144
+ @run_time_parent.get_var(v)
145
+ end
146
+ else
147
+ @variables[v]
148
+ end
149
+ end
150
+
151
+ def set_var(v,vv)
152
+ @variables[v] = vv
153
+ end
154
+
155
+ def get_ns(n)
156
+ return @ns[n] if @ns.has_key?(n)
157
+ return @parent.get_ns(n) unless @parent.nil?
158
+ return nil
159
+ end
160
+
161
+ def set_ns(n,h)
162
+ @ns[n] = h
163
+ end
164
+
165
+ def each_namespace(&block)
166
+ if !@parent.nil?
167
+ @parent.each_namespace do |k,v|
168
+ yield k, v
169
+ end
170
+ end
171
+ @ns.each_pair do |k,v|
172
+ yield k, v
173
+ end
174
+ end
175
+
176
+ def eval_expression(selection)
177
+ if selection.is_a?(String)
178
+ p = Fabulator::Expr::Parser.new
179
+ selection = p.parse(selection, self)
180
+ end
181
+
182
+ if selection.nil?
183
+ res = [ ]
184
+ else
185
+ # run selection against current context
186
+ res = selection.run(self)
187
+ end
188
+ return res
189
+ end
190
+
191
+ def run(action, autovivify = false)
192
+ action.run(self, autovivify)
193
+ end
194
+
195
+ def traverse_path(path, autovivify = false)
196
+ return [ self.root ] if path.nil? || path.is_a?(Array) && path.empty?
197
+
198
+ path = [ path ] unless path.is_a?(Array)
199
+
200
+ current = [ self.root ]
201
+
202
+ path.each do |c|
203
+ set = [ ]
204
+ current.each do |cc|
205
+ if c.is_a?(String)
206
+ cset = cc.children(c)
207
+ else
208
+ cset = c.run(self.with_root(cc), autovivify)
209
+ end
210
+ if cset.nil? || cset.empty?
211
+ if autovivify
212
+ if c.is_a?(String)
213
+ cset = [ cc.create_child(c) ]
214
+ else
215
+ cset = [ c.create_node(cc) ]
216
+ end
217
+ end
218
+ end
219
+ set = set + cset
220
+ end
221
+ current = set
222
+ end
223
+ return current
224
+ end
225
+
226
+ def set_value(p, v)
227
+ if p.is_a?(String) || v.is_a?(String)
228
+ parser = Fabulator::Expr::Parser.new
229
+ p = parser.parse(p,self) if p.is_a?(String)
230
+ v = parser.parse(v,self) if v.is_a?(String)
231
+ end
232
+
233
+ return [] if p.nil?
234
+
235
+ p = [ p ] unless p.is_a?(Array)
236
+
237
+ ret = [ ]
238
+
239
+ p.each do |pp|
240
+ tgts = pp.run(self, true)
241
+ src = nil
242
+ if !v.nil?
243
+ src = v.run(self)
244
+ end
245
+
246
+ tgts.each do |tgt|
247
+ tgt.prune
248
+ if src.nil? || src.empty?
249
+ tgt.value = nil
250
+ ret << tgt
251
+ elsif src.size == 1
252
+ tgt.copy(src.first)
253
+ ret << tgt
254
+ else
255
+ pp = tgt.parent
256
+ nom = tgt.name
257
+ pp.prune(pp.children(nom))
258
+ src.each do |s|
259
+ tgt = pp.create_child(nom,nil)
260
+ tgt.copy(s)
261
+ ret << tgt
262
+ end
263
+ end
264
+ end
265
+ end
266
+ ret
267
+ end
268
+
269
+ def get_values(ln = nil)
270
+ return [] if ln.nil?
271
+ self.eval_expression(ln).collect{ |c| c.value} - [ nil ]
272
+ end
273
+
274
+ def merge_data(d,p = nil)
275
+ # we have a hash or array based on root (r)
276
+ if p.nil?
277
+ root_context = [ self.root ]
278
+ else
279
+ root_context = self.traverse_path(p,true)
280
+ end
281
+ if root_context.size > 1
282
+ # see if we need to prune
283
+ new_rc = [ ]
284
+ root_context.each do |c|
285
+ if c.children.size == 0 && c.value.nil?
286
+ c.parent.prune(c) if c.parent
287
+ else
288
+ new_rc << c
289
+ end
290
+ end
291
+ if new_rc.size > 0
292
+ raise "Unable to merge data into multiple places simultaneously"
293
+ else
294
+ root_context = new_rc
295
+ end
296
+ else
297
+ root_context = root_context.first
298
+ end
299
+ if d.is_a?(Array)
300
+ node_name = root_context.name
301
+ root_context = root_context.parent
302
+ # get rid of empty children so we don't have problems later
303
+ root_context.children.each do |c|
304
+ if c.children.size == 0 && c.name == node_name && c.value.nil?
305
+ c.parent.prune(c)
306
+ end
307
+ end
308
+ d.each do |i|
309
+ c = root_context.create_child(node_name)
310
+ self.with_root(c).merge_data(i)
311
+ end
312
+ elsif d.is_a?(Hash)
313
+ d.each_pair do |k,v|
314
+ bits = k.split('.')
315
+ c = self.with_root(root_context).traverse_path(bits,true).first
316
+ if v.is_a?(Hash) || v.is_a?(Array)
317
+ self.with_root(c).merge_data(v)
318
+ else
319
+ c.value = v
320
+ end
321
+ end
322
+ else
323
+ c = root_context.parent.create_child(root_context.name, d)
324
+ end
325
+ end
326
+
327
+ def compile_actions(xml)
328
+ actions = Fabulator::Expr::StatementList.new
329
+ local_ctx = self.merge(xml)
330
+ xml.each_element do |e|
331
+ ns = e.namespaces.namespace.href
332
+ next unless Fabulator::ActionLib.namespaces.include?(ns)
333
+ if ns == FAB_NS && e.name == 'ensure'
334
+ actions.add_ensure(local_ctx.compile_actions(e))
335
+ elsif ns == FAB_NS && e.name == 'catch'
336
+ actions.add_catch(local_ctx.compile_action(e))
337
+ else
338
+ actions.add_statement(local_ctx.compile_action(e)) # rescue nil)
339
+ end
340
+ end
341
+ return actions
342
+ end
343
+
344
+ def compile_action(e)
345
+ ns = e.namespaces.namespace.href
346
+ return unless Fabulator::ActionLib.namespaces.include?(ns)
347
+ Fabulator::ActionLib.namespaces[ns].compile_action(e, self)
348
+ end
349
+
350
+ def in_context(&block)
351
+ ctx = self.merge
352
+ yield ctx
353
+ end
354
+
355
+ def with(ctx2, &block)
356
+ ctx = self.merge(ctx2)
357
+ yield ctx
358
+ end
359
+
360
+ def run_filter(ns, name)
361
+ handler = Fabulator::ActionLib.namespaces[ns]
362
+ return [] if handler.nil?
363
+ handler.run_filter(self, name)
364
+ end
365
+
366
+ end
367
+ end
368
+ end
@@ -0,0 +1,74 @@
1
+ module Fabulator
2
+ module Expr
3
+ class ForExpr
4
+ def initialize(v, e)
5
+ if v.size > 1
6
+ @var = v.shift
7
+ @expr = Fabulator::Expr::ForExpr.new(v, e)
8
+ else
9
+ @var = v.first
10
+ @expr = e
11
+ end
12
+ end
13
+
14
+ def expr_type(context)
15
+ @expr.expr_type(context)
16
+ end
17
+
18
+ def run(context, autovivify = false)
19
+ result = [ ]
20
+ return result if @var.nil? || @expr.nil?
21
+
22
+ @var.each_binding(context, autovivify) do |b|
23
+ result = result + @expr.run(b)
24
+ end
25
+ return result
26
+ end
27
+ end
28
+
29
+ class EveryExpr < ForExpr
30
+ def expr_type(context)
31
+ [ FAB_NS, 'boolean' ]
32
+ end
33
+
34
+ def run(context, autovivify = false)
35
+ result = super
36
+ result.each do |r|
37
+ return [ context.root.anon_node(false) ] unless !!r.value
38
+ end
39
+ return [ context.root.anon_node(true) ]
40
+ end
41
+ end
42
+
43
+ class SomeExpr < ForExpr
44
+ def expr_type(context)
45
+ [ FAB_NS, 'boolean' ]
46
+ end
47
+
48
+ def run(context, autovivify = false)
49
+ result = super
50
+ result.each do |r|
51
+ return [ context.root.anon_node(true) ] if !!r.value
52
+ end
53
+ return [ context.root.anon_node(false) ]
54
+ end
55
+ end
56
+
57
+ class ForVar
58
+ def initialize(n, e)
59
+ n =~ /^\$?(.*)$/
60
+ @var_name = $1
61
+ @expr = e
62
+ end
63
+
64
+ def each_binding(context, autovivify = false, &block)
65
+ @expr.run(context, autovivify).each do |e|
66
+ context.in_context do |ctx|
67
+ ctx.set_var(@var_name, e)
68
+ yield ctx
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,52 @@
1
+ module Fabulator
2
+ module Expr
3
+ class Function
4
+ def initialize(ctx, nom, args)
5
+ bits = nom.split(/:/, 2)
6
+ @ns = ctx.get_ns(bits[0])
7
+ @name = bits[1]
8
+ @args = args
9
+ @ctx = ctx
10
+ end
11
+
12
+ def expr_type(context)
13
+ klass = ActionLib.namespaces[@ns]
14
+ (klass.function_return_type(@name) rescue nil)
15
+ end
16
+
17
+ def run(context, autovivify = false)
18
+ klass = ActionLib.namespaces[@ns]
19
+ return [] if klass.nil?
20
+ ctx = @ctx.merge(context)
21
+ return klass.run_function(
22
+ ctx, @name, @args.run(ctx)
23
+ )
24
+ end
25
+ end
26
+
27
+ class List
28
+ def initialize(args)
29
+ @args = args
30
+ end
31
+
32
+ def run(context, autovivify = false)
33
+ @args.collect{ |arg| arg.run(context, autovivify).flatten }
34
+ end
35
+ end
36
+
37
+ class Tuple
38
+ def initialize(args)
39
+ @args = args
40
+ end
41
+
42
+ def run(context, autovivify = false)
43
+ items = @args.collect{ |arg| arg.run(context, autovivify).flatten }.flatten
44
+ ret = context.root.anon_node(nil, [ FAB_NS, 'tuple' ])
45
+ ret.value = items
46
+ ret.vtype = [ FAB_NS, 'tuple' ]
47
+ ret.set_attribute('size', items.size)
48
+ [ ret ]
49
+ end
50
+ end
51
+ end
52
+ end