fabulator 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -0
- data/Manifest.txt +41 -0
- data/README.rdoc +61 -0
- data/Rakefile +54 -0
- data/lib/fabulator.rb +5 -0
- data/lib/fabulator/action.rb +46 -0
- data/lib/fabulator/action_lib.rb +438 -0
- data/lib/fabulator/context.rb +39 -0
- data/lib/fabulator/core.rb +8 -0
- data/lib/fabulator/core/actions.rb +514 -0
- data/lib/fabulator/core/actions/choose.rb +167 -0
- data/lib/fabulator/core/actions/for_each.rb +105 -0
- data/lib/fabulator/core/actions/variables.rb +52 -0
- data/lib/fabulator/core/constraint.rb +117 -0
- data/lib/fabulator/core/filter.rb +41 -0
- data/lib/fabulator/core/group.rb +123 -0
- data/lib/fabulator/core/parameter.rb +128 -0
- data/lib/fabulator/core/state.rb +91 -0
- data/lib/fabulator/core/state_machine.rb +153 -0
- data/lib/fabulator/core/transition.rb +164 -0
- data/lib/fabulator/expr.rb +37 -0
- data/lib/fabulator/expr/axis.rb +133 -0
- data/lib/fabulator/expr/axis_descendent_or_self.rb +26 -0
- data/lib/fabulator/expr/bin_expr.rb +178 -0
- data/lib/fabulator/expr/context.rb +368 -0
- data/lib/fabulator/expr/for_expr.rb +74 -0
- data/lib/fabulator/expr/function.rb +52 -0
- data/lib/fabulator/expr/if_expr.rb +22 -0
- data/lib/fabulator/expr/let_expr.rb +17 -0
- data/lib/fabulator/expr/literal.rb +39 -0
- data/lib/fabulator/expr/node.rb +216 -0
- data/lib/fabulator/expr/node_logic.rb +99 -0
- data/lib/fabulator/expr/parser.rb +1470 -0
- data/lib/fabulator/expr/path_expr.rb +49 -0
- data/lib/fabulator/expr/predicates.rb +45 -0
- data/lib/fabulator/expr/statement_list.rb +96 -0
- data/lib/fabulator/expr/step.rb +43 -0
- data/lib/fabulator/expr/unary_expr.rb +30 -0
- data/lib/fabulator/expr/union_expr.rb +21 -0
- data/lib/fabulator/template.rb +9 -0
- data/lib/fabulator/template/context.rb +51 -0
- data/lib/fabulator/template/parse_result.rb +153 -0
- data/lib/fabulator/template/parser.rb +17 -0
- data/lib/fabulator/template/standard_tags.rb +95 -0
- data/lib/fabulator/template/taggable.rb +88 -0
- data/lib/fabulator/version.rb +14 -0
- data/test/test_fabulator.rb +17 -0
- data/test/test_helper.rb +24 -0
- data/xslt/form.xsl +2161 -0
- 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
|