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,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