fabulator 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,164 @@
1
+ module Fabulator
2
+ module Core
3
+ class Transition < Fabulator::Action
4
+ attr_accessor :state, :validations, :tags
5
+
6
+ namespace Fabulator::FAB_NS
7
+ attribute :view, :as => :lstate, :static => true
8
+ attribute :tag, :as => :ltags, :static => true, :default => ''
9
+
10
+ def initialize
11
+ @state = nil
12
+ @tags = nil
13
+ @groups = { }
14
+ @params = [ ]
15
+ @actions = nil
16
+ end
17
+
18
+ def compile_xml(xml, ctx)
19
+ super
20
+
21
+ inheriting = !@state.nil?
22
+
23
+ if !inheriting
24
+ @state = @lstate
25
+ @tags = @ltags
26
+ end
27
+
28
+ # TODO: figure out some way to reference inherited actions
29
+ # figure out 'super' vs. 'inner' -- only supporting 'super'
30
+ # for now
31
+ ActionLib.with_super(@actions) do
32
+ t = @context.compile_actions(xml)
33
+ @actions = t if @actions.nil? || !t.is_noop?
34
+ end
35
+ parser = Fabulator::Expr::Parser.new
36
+
37
+ xml.each_element do |e|
38
+ next unless e.namespaces.namespace.href == FAB_NS
39
+ case e.name
40
+ # TODO: handle parameters when inheriting
41
+ when 'params':
42
+ p_ctx = @context.merge(e)
43
+ @select = p_ctx.get_select('/')
44
+
45
+ e.each_element do |ee|
46
+ next unless ee.namespaces.namespace.href == FAB_NS
47
+ case ee.name
48
+ when 'group':
49
+ if !inheriting
50
+ g = Group.new.compile_xml(ee, p_ctx)
51
+ @params << g
52
+ else
53
+ tags = (ee.attributes.get_attribute_ns(FAB_NS, 'tag').value rescue '').split(/\s+/)
54
+ end
55
+ when 'param':
56
+ if !inheriting
57
+ p = Parameter.new.compile_xml(ee, p_ctx)
58
+ @params << p
59
+ else
60
+ tags = (ee.attributes.get_attribute_ns(FAB_NS, 'tag').value rescue '').split(/\s+/)
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ self
67
+ end
68
+
69
+ def param_names
70
+ (@params.collect{|w| w.param_names}.flatten).uniq
71
+ end
72
+
73
+ def validate_params(context,params)
74
+ ctx = @context.merge(context)
75
+ my_params = params
76
+
77
+ param_context = Fabulator::Expr::Node.new(
78
+ 'ext',
79
+ ctx.root.roots,
80
+ nil,
81
+ []
82
+ )
83
+ ctx.root.roots['ext'] = param_context
84
+ p_ctx = ctx.with_root(param_context)
85
+ p_ctx.merge_data(my_params)
86
+
87
+ if @select.nil?
88
+ self.apply_filters(p_ctx)
89
+ else
90
+ @select.run(p_ctx).each{ |c| self.apply_filters(p_ctx.with_root(c)) }
91
+ end
92
+
93
+ res = {
94
+ :unknown => [ ],
95
+ :valid => [ ],
96
+ :invalid => [ ],
97
+ :missing => [ ],
98
+ :messages => [ ],
99
+ }
100
+
101
+ if @select.nil?
102
+ rr = self.apply_constraints(p_ctx)
103
+ res[:invalid] += rr[:invalid]
104
+ res[:valid] += rr[:valid]
105
+ res[:unknown] += rr[:unknown]
106
+ res[:messages] += rr[:messages]
107
+ else
108
+ @select.run(p_ctx).each do |c|
109
+ rr = self.apply_constraints(p_ctx.with_root(c))
110
+ res[:invalid] += rr[:invalid]
111
+ res[:valid] += rr[:valid]
112
+ res[:unknown] += rr[:unknown]
113
+ res[:messages] += rr[:messages]
114
+ end
115
+ end
116
+
117
+ res[:unknown] = [ ]
118
+
119
+ res[:invalid].uniq!
120
+ res[:invalid].each do |k|
121
+ res[:valid].delete(k.path)
122
+ res[:unknown].delete(k.path)
123
+ end
124
+ #res[:unknown] = res[:unknown].collect{|k| @select + k}
125
+ res[:unknown].each do |k|
126
+ res[:valid].delete(k)
127
+ end
128
+
129
+ res[:score] = (res[:valid].size+1)*(params.size)
130
+ res[:score] = res[:score] / (res[:missing].size + 1)
131
+ res[:score] = res[:score] / (res[:invalid].size + 1)
132
+ res[:score] = res[:score] / (res[:unknown].size + 1)
133
+ return res
134
+ end
135
+
136
+ def apply_filters(ctx)
137
+ @params.collect { |p|
138
+ p.apply_filters(ctx)
139
+ }.flatten
140
+ end
141
+
142
+ def apply_constraints(ctx)
143
+ invalid = [ ]
144
+ missing = [ ]
145
+ valid = [ ]
146
+ msgs = [ ]
147
+ @params.each do |p|
148
+ res = p.apply_constraints(ctx)
149
+ invalid = invalid + res[:invalid]
150
+ missing = missing + res[:missing]
151
+ valid = valid + res[:valid]
152
+ msgs = msgs + res[:messages]
153
+ end
154
+ return { :missing => missing, :invalid => invalid, :valid => valid, :messages => msgs, :unknown => [ ] }
155
+ end
156
+
157
+ def run(context)
158
+ # do queries, denials, assertions in the order given
159
+ @actions.run(@context.merge(context))
160
+ return []
161
+ end
162
+ end
163
+ end
164
+ end
@@ -0,0 +1,37 @@
1
+ require 'fabulator/expr/context'
2
+ require 'fabulator/expr/axis_descendent_or_self'
3
+ require 'fabulator/expr/axis'
4
+ require 'fabulator/expr/bin_expr'
5
+ require 'fabulator/expr/node_logic'
6
+ require 'fabulator/expr/node'
7
+ require 'fabulator/expr/parser'
8
+ require 'fabulator/expr/path_expr'
9
+ require 'fabulator/expr/step'
10
+ require 'fabulator/expr/unary_expr'
11
+ require 'fabulator/expr/union_expr'
12
+ require 'fabulator/expr/literal'
13
+
14
+ require 'fabulator/expr/for_expr'
15
+ require 'fabulator/expr/function'
16
+ require 'fabulator/expr/if_expr'
17
+ require 'fabulator/expr/let_expr'
18
+ require 'fabulator/expr/path_expr'
19
+ require 'fabulator/expr/predicates'
20
+ require 'fabulator/expr/step'
21
+
22
+ require 'fabulator/expr/statement_list'
23
+
24
+ module Fabulator
25
+ module Expr
26
+ class ParserError < StandardError
27
+ end
28
+
29
+ class Exception < StandardError
30
+ attr_accessor :node
31
+
32
+ def initialize(n)
33
+ @node = n
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,133 @@
1
+ module Fabulator
2
+ module Expr
3
+ class Axis
4
+ def initialize(axis, n = nil)
5
+ case axis
6
+ when 'attribute':
7
+ @axis = AxisAttribute.new(n)
8
+ when 'child':
9
+ @axis = AxisChild.new(n)
10
+ when 'child-or-self':
11
+ when 'descendent':
12
+ when 'descendent-or-self':
13
+ @axis = AxisDescendentOrSelf.new(n)
14
+ when 'parent':
15
+ @axis = AxisParent.new(n)
16
+ else
17
+ @root = axis
18
+ @axis = n.nil? ? nil : AxisChild.new(n)
19
+ end
20
+ end
21
+
22
+ def run(context, autovivify = false)
23
+ if @root.nil? || @root == ''
24
+ return @axis.run(context, autovivify)
25
+ else
26
+ if context.root.roots[@root].nil? && !Fabulator::ActionLib.axes[@root].nil?
27
+ context.root.roots[@root] = Fabulator::ActionLib.axes[@root].call(context)
28
+ end
29
+ return context.root.roots[@root].nil? ? [ ] :
30
+ @axis.nil? ? [ context.root.roots[@root] ] :
31
+ [ @axis.run(context.with_root(context.root.roots[@root])) ]
32
+ end
33
+ end
34
+ end
35
+
36
+ class AxisChild
37
+ def initialize(n)
38
+ @node_test = n
39
+ end
40
+
41
+ def run(context, autovivify = false)
42
+ if @node_test.is_a?(String)
43
+ n = @node_test
44
+ else
45
+ n = (@node_test.run(context).last.to_s rescue nil)
46
+ end
47
+ return [ ] if n.nil?
48
+ if n == '*'
49
+ possible = context.is_a?(Array) ? context.collect{|c| c.root.children}.flatten : context.root.children
50
+ else
51
+ possible = context.is_a?(Array) ? context.collect{|c| c.root.children(n)}.flatten : context.root.children(n)
52
+ if possible.empty? && autovivify
53
+ possible = context.traverse_path([ n ], true)
54
+ end
55
+ end
56
+ return possible
57
+ end
58
+ end
59
+
60
+ class AxisDescendentOrSelf
61
+ def initialize(step = nil)
62
+ @step = step
63
+ end
64
+
65
+ def run(context, autovivify = false)
66
+ if context.is_a?(Array)
67
+ stack = context.collect{ |c| c.root }
68
+ else
69
+ stack = [ context.root ]
70
+ end
71
+ possible = [ ]
72
+ while !stack.empty?
73
+ c = stack.shift
74
+
75
+ stack = stack + c.children
76
+
77
+ possible = possible + @step.run(context.with_root(c), autovivify)
78
+ end
79
+ return possible.uniq
80
+ end
81
+ end
82
+
83
+ class AxisParent
84
+ def run(context, autovivify = false)
85
+ if context.is_a?(Array)
86
+ context.collect { |c| c.root.parent }.uniq
87
+ else
88
+ context.root.parent
89
+ end
90
+ end
91
+ end
92
+
93
+ class AxisAttribute
94
+ def initialize(n)
95
+ @name = n
96
+ end
97
+
98
+ def run(context, autovivify = false)
99
+ res = [ ]
100
+ context = [ context ] unless context.is_a?(Array)
101
+
102
+ res = context.collect { |c|
103
+ if @name.is_a?(String)
104
+ nom = @name
105
+ else
106
+ nom = (@name.run(c).last.to_s rescue nil)
107
+ end
108
+ if nom == 'type'
109
+ if c.root.vtype.nil?
110
+ nil
111
+ else
112
+ n = c.root.anon_node(nil)
113
+ n.parent = c.root
114
+ n.set_attribute('namespace', c.root.vtype[0])
115
+ n.set_attribute('name', c.root.vtype[1])
116
+ n.name = 'type'
117
+ n.vtype = [ FAB_NS, 'uri' ]
118
+ n
119
+ end
120
+ else
121
+ t = c.root.get_attribute(nom)
122
+ if(t.nil? && autovivify)
123
+ c.root.set_attribute(nom, nil)
124
+ t = c.root.get_attribute(nom)
125
+ end
126
+ t
127
+ end
128
+ }
129
+ res = res - [ nil ]
130
+ end
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,26 @@
1
+ module Fabulator
2
+ module Expr
3
+ class AxisDescendentOrSelf
4
+ def initialize(step = nil)
5
+ @step = step
6
+ end
7
+
8
+ def run(context, autovivify = false)
9
+ if context.is_a?(Array)
10
+ stack = context.root
11
+ else
12
+ stack = [ context.root ]
13
+ end
14
+ possible = [ ]
15
+ while !stack.empty?
16
+ c = stack.shift
17
+
18
+ stack = stack + c.children
19
+
20
+ possible = possible + context.with_root(c).run(@step, autovivify)
21
+ end
22
+ return possible.uniq
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,178 @@
1
+ module Fabulator
2
+ module Expr
3
+ class BinExpr
4
+ def initialize(left, right)
5
+ @left = left
6
+ @right = right
7
+ end
8
+
9
+ def expr_type(context)
10
+ lt = @left.expr_type(context)
11
+ rt = @right.expr_type(context)
12
+ Fabulator::ActionLib.unify_types([ lt, rt ])
13
+ end
14
+
15
+ def run(context, autovivify = false)
16
+ l = @left.run(context, autovivify)
17
+ r = @right.run(context, autovivify)
18
+
19
+ l = [ l ] unless l.is_a?(Array)
20
+ r = [ r ] unless r.is_a?(Array)
21
+
22
+ res = []
23
+
24
+ l.each do |i|
25
+ r.each do |j|
26
+ ut = Fabulator::ActionLib.unify_types([ i.vtype, j.vtype ])
27
+ op = ActionLib.find_op(ut, self.op)
28
+ if(op && op[:proc])
29
+ calc = op[:proc].call(i.to(ut), j.to(ut))
30
+ else
31
+ calc = self.calculate(i.to(ut).value,j.to(ut).value)
32
+ end
33
+ calc = [ calc ] unless calc.is_a?(Array)
34
+
35
+ rut = self.result_type(ut)
36
+ res = res + calc.collect { |c| c.is_a?(Fabulator::Expr::Node) ? c : context.root.anon_node(c, rut) }
37
+ end
38
+ end
39
+ return res
40
+ end
41
+
42
+ def result_type(t)
43
+ t
44
+ end
45
+ end
46
+
47
+ class AddExpr < BinExpr
48
+ def op
49
+ :plus
50
+ end
51
+
52
+ def calculate(a,b)
53
+ return nil if a.nil? || b.nil?
54
+ a + b
55
+ end
56
+ end
57
+
58
+ class SubExpr < BinExpr
59
+ def op
60
+ :minus
61
+ end
62
+
63
+ def calculate(a,b)
64
+ return nil if a.nil? || b.nil?
65
+ a - b
66
+ end
67
+ end
68
+
69
+ class BoolBinExpr < BinExpr
70
+ def expr_type(context)
71
+ [ FAB_NS, 'boolean' ]
72
+ end
73
+
74
+ def result_type(t)
75
+ [ FAB_NS, 'boolean' ]
76
+ end
77
+ end
78
+
79
+ class LtExpr < BoolBinExpr
80
+ def op
81
+ :lt
82
+ end
83
+
84
+ def calculate(a,b)
85
+ return nil if a.nil? || b.nil?
86
+ a < b
87
+ end
88
+ end
89
+
90
+ class LteExpr < BoolBinExpr
91
+ def op
92
+ :lte
93
+ end
94
+
95
+ def calculate(a,b)
96
+ return nil if a.nil? || b.nil?
97
+ a <= b
98
+ end
99
+ end
100
+
101
+ class EqExpr < BoolBinExpr
102
+ def op
103
+ :eq
104
+ end
105
+
106
+ def calculate(a,b)
107
+ a == b
108
+ end
109
+ end
110
+
111
+ class NeqExpr < BoolBinExpr
112
+ def op
113
+ :neq
114
+ end
115
+
116
+ def calculate(a,b)
117
+ a != b
118
+ end
119
+ end
120
+
121
+ class MpyExpr < BinExpr
122
+ def op
123
+ :times
124
+ end
125
+
126
+ def calculate(a,b)
127
+ return nil if a.nil? || b.nil?
128
+ a * b
129
+ end
130
+ end
131
+
132
+ class DivExpr < BinExpr
133
+ def op
134
+ :div
135
+ end
136
+
137
+ def calculate(a,b)
138
+ return nil if b.nil? || a.nil?
139
+ a / b
140
+ end
141
+ end
142
+
143
+ class ModExpr < BinExpr
144
+ def op
145
+ :mod
146
+ end
147
+
148
+ def calculate(a,b)
149
+ return nil if a.nil? || b.nil?
150
+ a % b
151
+ end
152
+ end
153
+
154
+ class RangeExpr < BinExpr
155
+ def op
156
+ :range
157
+ end
158
+
159
+ def expr_type(context)
160
+ [ FAB_NS, 'numeric' ]
161
+ end
162
+
163
+ def result_type(t)
164
+ [ FAB_NS, 'numeric' ]
165
+ end
166
+
167
+ def calculate(a,b)
168
+ return nil if a.nil? || b.nil?
169
+ if a < b
170
+ r = (a.to_i .. b.to_i).to_a
171
+ else
172
+ r = (b.to_i .. a.to_i).to_a.reverse
173
+ end
174
+ return r
175
+ end
176
+ end
177
+ end
178
+ end