fabulator 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +20 -0
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/features/step_definitions/expression_steps.rb +1 -1
- data/features/step_definitions/xml_steps.rb +2 -1
- data/features/support/env.rb +1 -0
- data/lib/fabulator.rb +13 -5
- data/lib/fabulator/action.rb +86 -19
- data/lib/fabulator/core/actions.rb +21 -6
- data/lib/fabulator/core/actions/choose.rb +16 -35
- data/lib/fabulator/core/actions/for_each.rb +20 -30
- data/lib/fabulator/core/actions/variables.rb +6 -8
- data/lib/fabulator/core/constraint.rb +2 -2
- data/lib/fabulator/core/filter.rb +0 -13
- data/lib/fabulator/core/group.rb +21 -25
- data/lib/fabulator/core/parameter.rb +5 -17
- data/lib/fabulator/core/state.rb +4 -44
- data/lib/fabulator/core/state_machine.rb +10 -38
- data/lib/fabulator/core/transition.rb +6 -39
- data/lib/fabulator/expr/axis.rb +2 -2
- data/lib/fabulator/expr/bin_expr.rb +3 -3
- data/lib/fabulator/expr/context.rb +37 -6
- data/lib/fabulator/expr/function.rb +9 -3
- data/lib/fabulator/expr/literal.rb +1 -1
- data/lib/fabulator/expr/node.rb +1 -1
- data/lib/fabulator/expr/node_logic.rb +1 -1
- data/lib/fabulator/expr/parser.rb +1 -1
- data/lib/fabulator/expr/predicates.rb +1 -1
- data/lib/fabulator/expr/statement_list.rb +4 -0
- data/lib/fabulator/expr/union_expr.rb +1 -1
- data/lib/fabulator/lib.rb +69 -0
- data/lib/fabulator/lib/action.rb +13 -0
- data/lib/fabulator/lib/attribute.rb +9 -0
- data/lib/fabulator/lib/lib.rb +47 -0
- data/lib/fabulator/lib/structural.rb +13 -0
- data/lib/fabulator/structural.rb +92 -0
- data/lib/fabulator/{action_lib.rb → tag_lib.rb} +89 -51
- data/lib/fabulator/template/standard_tags.rb +4 -3
- data/xsm_expression_parser.racc +1 -1
- metadata +27 -8
- data/TODO +0 -7
- data/features/xsm-inheritance.feature +0 -46
data/History.txt
CHANGED
@@ -1,3 +1,23 @@
|
|
1
|
+
=== 0.0.7 2010-09-07
|
2
|
+
|
3
|
+
* 5 major enhancement:
|
4
|
+
* Structural elements are easier to code - similar to actions
|
5
|
+
* Fabulator::ActionLib is now Fabulator::TagLib to reflect the more
|
6
|
+
generic nature of the libraries
|
7
|
+
* More robust Structural and Action base classes
|
8
|
+
* Added '?' as a suffix character for expression function names
|
9
|
+
A function with a name ending in '?' will have its return values
|
10
|
+
automatically converted to boolean
|
11
|
+
* Default run-time behavior for Action classes is to run any embedded
|
12
|
+
actions
|
13
|
+
|
14
|
+
* 5 minor enhancement:
|
15
|
+
* Fabulator now depends on the active_support gem
|
16
|
+
* Inheritance is not fully supported, so removing until later
|
17
|
+
* Simpler access to attributes that require evaluation
|
18
|
+
* Simpler access to f:select values and actions
|
19
|
+
* Beginning support for libraries written in XML (testing only for now)
|
20
|
+
|
1
21
|
=== 0.0.6 2010-08-27
|
2
22
|
|
3
23
|
* 4 minor enhancement:
|
data/Rakefile
CHANGED
@@ -11,6 +11,7 @@ begin
|
|
11
11
|
gem.add_dependency(%q<libxslt-ruby>, [">= 0.9.7"])
|
12
12
|
gem.add_dependency(%q<radius>, [">= 0.6.1"])
|
13
13
|
gem.add_dependency(%q<RedCloth>, [">= 4.2.0"])
|
14
|
+
gem.add_dependency(%q<activesupport>, [">=2.3.0"])
|
14
15
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
15
16
|
end
|
16
17
|
rescue LoadError
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.7
|
@@ -56,7 +56,7 @@ When /I unify the types? (.*)/ do |ts|
|
|
56
56
|
pn = t.split(/:/, 2)
|
57
57
|
[ @context.get_ns(pn[0]), pn[1] ]
|
58
58
|
}
|
59
|
-
@type_result = Fabulator::
|
59
|
+
@type_result = Fabulator::TagLib.unify_types(
|
60
60
|
types.collect { |t|
|
61
61
|
pn = t.split(/:/, 2)
|
62
62
|
[ @context.get_ns(pn[0]), pn[1] ]
|
@@ -2,7 +2,8 @@ Given /the statemachine/ do |doc_xml|
|
|
2
2
|
@context ||= Fabulator::Expr::Context.new
|
3
3
|
|
4
4
|
if @sm.nil?
|
5
|
-
@sm = Fabulator::Core::StateMachine.new
|
5
|
+
@sm = Fabulator::Core::StateMachine.new
|
6
|
+
@sm.compile_xml(doc_xml)
|
6
7
|
else
|
7
8
|
@sm.compile_xml(doc_xml)
|
8
9
|
end
|
data/features/support/env.rb
CHANGED
data/lib/fabulator.rb
CHANGED
@@ -1,5 +1,13 @@
|
|
1
|
-
require '
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
require 'active_support/inflector'
|
2
|
+
|
3
|
+
module Fabulator
|
4
|
+
FAB_NS='http://dh.tamu.edu/ns/fabulator/1.0#'
|
5
|
+
FAB_LIB_NS='http://dh.tamu.edu/ns/fabulator/library/1.0#'
|
6
|
+
|
7
|
+
require 'fabulator/expr'
|
8
|
+
require 'fabulator/tag_lib'
|
9
|
+
require 'fabulator/action'
|
10
|
+
require 'fabulator/structural'
|
11
|
+
require 'fabulator/core'
|
12
|
+
require 'fabulator/version'
|
13
|
+
end
|
data/lib/fabulator/action.rb
CHANGED
@@ -3,34 +3,38 @@ module Fabulator
|
|
3
3
|
|
4
4
|
def compile_xml(xml, context)
|
5
5
|
@context = context.merge(xml)
|
6
|
-
|
7
|
-
if @@attributes[klass]
|
8
|
-
@@attributes[klass].each_pair do |nom, opts|
|
9
|
-
as = "@" + (opts[:as] || nom).to_s
|
10
|
-
self.instance_variable_set(as.to_sym, @context.attribute(opts[:namespace] || @@namespace[klass], nom.to_s, opts))
|
11
|
-
end
|
12
|
-
end
|
13
|
-
@select = @context.get_select(@@has_select[klass]) if @@has_select.has_key?(klass)
|
14
|
-
if @@has_actions[klass]
|
15
|
-
case @@has_actions[klass]
|
16
|
-
when :simple:
|
17
|
-
@actions = @context.compile_actions(xml)
|
18
|
-
when :super:
|
19
|
-
@actions = ActionLib.current_super
|
20
|
-
end
|
21
|
-
end
|
6
|
+
self.setup(xml)
|
22
7
|
self
|
23
8
|
end
|
24
9
|
|
25
|
-
def
|
10
|
+
def has_actions?
|
11
|
+
!@actions.nil? && !@actions.empty?
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.namespace(href = nil)
|
15
|
+
return @@namespace[self.name] if href.nil?
|
26
16
|
@@namespace ||= { }
|
27
17
|
@@namespace[self.name] = href
|
28
18
|
end
|
29
19
|
|
30
|
-
def self.attribute(
|
20
|
+
def self.attribute(e_nom, opts = { })
|
31
21
|
@@attributes ||= { }
|
32
22
|
@@attributes[self.name] ||= { }
|
33
|
-
@@attributes[self.name][
|
23
|
+
@@attributes[self.name][e_nom.to_s] = opts
|
24
|
+
nom = (opts[:as].nil? ? e_nom : opts[:as]).to_sym
|
25
|
+
if opts[:static]
|
26
|
+
self.instance_eval {
|
27
|
+
attr_reader nom.to_sym
|
28
|
+
}
|
29
|
+
else
|
30
|
+
at_nom = ('@' + nom.to_s).to_sym
|
31
|
+
self.class_eval {
|
32
|
+
define_method(nom.to_s) { |ctx|
|
33
|
+
v = instance_variable_get(at_nom)
|
34
|
+
v.nil? ? [] : v.run(ctx,false)
|
35
|
+
}
|
36
|
+
}
|
37
|
+
end
|
34
38
|
end
|
35
39
|
|
36
40
|
def self.has_actions(t = :simple)
|
@@ -38,9 +42,72 @@ module Fabulator
|
|
38
42
|
@@has_actions[self.name] = t
|
39
43
|
end
|
40
44
|
|
45
|
+
def self.has_actions?
|
46
|
+
!@@has_actions.nil? && @@has_actions.has_key?(self.name)
|
47
|
+
end
|
48
|
+
|
49
|
+
def run_actions(ctx)
|
50
|
+
self.has_actions? ? @actions.run(ctx) : [ ]
|
51
|
+
end
|
52
|
+
|
41
53
|
def self.has_select(default = '.')
|
42
54
|
@@has_select ||= { }
|
43
55
|
@@has_select[self.name] = default
|
44
56
|
end
|
57
|
+
|
58
|
+
def select(ctx)
|
59
|
+
self.class.has_select? && !@select.nil? ? @select.run(ctx) : [ ]
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.has_select?
|
63
|
+
!@@has_select.nil? && @@has_select.has_key?(self.name)
|
64
|
+
end
|
65
|
+
|
66
|
+
# def self.at_runtime(&block)
|
67
|
+
# @@run_time ||= { }
|
68
|
+
# @@run_time[self.name] = block
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
|
72
|
+
def run(context, autovivify = false)
|
73
|
+
self.run_actions(@context.merge(context))
|
74
|
+
end
|
75
|
+
|
76
|
+
# def run(context, autovivify = false)
|
77
|
+
# ret = []
|
78
|
+
# @context.with(context) do |ctx|
|
79
|
+
# proc = @@run_time[self.class.name]
|
80
|
+
# if !proc.nil?
|
81
|
+
# ret = self.instance_eval {
|
82
|
+
# proc.call(ctx, autovivify)
|
83
|
+
# }
|
84
|
+
# end
|
85
|
+
# end
|
86
|
+
# ret
|
87
|
+
# end
|
88
|
+
|
89
|
+
protected
|
90
|
+
|
91
|
+
def setup(xml)
|
92
|
+
klass = self.class.name
|
93
|
+
if @@attributes[klass]
|
94
|
+
@@attributes[klass].each_pair do |nom, opts|
|
95
|
+
as = "@" + (opts[:as] || nom).to_s
|
96
|
+
self.instance_variable_set(as.to_sym, @context.attribute(opts[:namespace] || @@namespace[klass], nom.to_s, opts))
|
97
|
+
end
|
98
|
+
end
|
99
|
+
if self.class.has_select?
|
100
|
+
@select = @context.get_select(@@has_select[klass])
|
101
|
+
end
|
102
|
+
@actions = nil
|
103
|
+
if @@has_actions[klass]
|
104
|
+
case @@has_actions[klass]
|
105
|
+
when :simple:
|
106
|
+
@actions = @context.compile_actions(xml)
|
107
|
+
when :super:
|
108
|
+
@actions = TagLib.current_super
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
45
112
|
end
|
46
113
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'fabulator/
|
1
|
+
require 'fabulator/tag_lib'
|
2
2
|
require 'fabulator/core/actions/choose'
|
3
3
|
require 'fabulator/core/actions/for_each'
|
4
4
|
require 'fabulator/core/actions/variables'
|
@@ -6,9 +6,24 @@ require 'fabulator/core/actions/variables'
|
|
6
6
|
module Fabulator
|
7
7
|
module Core
|
8
8
|
module Actions
|
9
|
-
class Lib
|
10
|
-
|
11
|
-
|
9
|
+
class Lib < TagLib
|
10
|
+
namespace FAB_NS
|
11
|
+
|
12
|
+
structural 'application', Fabulator::Core::StateMachine
|
13
|
+
structural 'view', Fabulator::Core::State
|
14
|
+
structural 'goes-to', Fabulator::Core::Transition
|
15
|
+
#structural 'before',
|
16
|
+
#structural 'after',
|
17
|
+
structural 'params', Fabulator::Core::Group
|
18
|
+
structural 'group', Fabulator::Core::Group
|
19
|
+
structural 'param', Fabulator::Core::Parameter
|
20
|
+
structural 'value', Fabulator::Core::Constraint
|
21
|
+
structural 'constraint', Fabulator::Core::Constraint
|
22
|
+
structural 'filter', Fabulator::Core::Filter
|
23
|
+
structural 'sort', Sort
|
24
|
+
structural 'when', When
|
25
|
+
structural 'otherwise', When
|
26
|
+
|
12
27
|
|
13
28
|
action 'choose', Choose
|
14
29
|
action 'for-each', ForEach
|
@@ -122,14 +137,14 @@ module Fabulator
|
|
122
137
|
end
|
123
138
|
|
124
139
|
reduction 'sum', { :scaling => :log } do |ctx, args|
|
125
|
-
zero =
|
140
|
+
zero = TagLib.find_op(args.first.vtype, :zero)
|
126
141
|
if(zero && zero[:proc])
|
127
142
|
res = zero[:proc].call(ctx)
|
128
143
|
end
|
129
144
|
res = 0 if res.nil?
|
130
145
|
return [ res ] if args.empty?
|
131
146
|
|
132
|
-
op =
|
147
|
+
op = TagLib.find_op(args.first.vtype, :plus)
|
133
148
|
|
134
149
|
if op.nil? || op[:proc].nil?
|
135
150
|
args.each do |a|
|
@@ -1,24 +1,12 @@
|
|
1
1
|
module Fabulator
|
2
2
|
module Core
|
3
3
|
module Actions
|
4
|
-
class Choose < Fabulator::
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
xml.each_element do |e|
|
12
|
-
next unless e.namespaces.namespace.href == FAB_NS
|
13
|
-
case e.name
|
14
|
-
when 'when':
|
15
|
-
@choices << When.new.compile_xml(e, @context)
|
16
|
-
when 'otherwise':
|
17
|
-
@default = When.new.compile_xml(e, @context)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
self
|
21
|
-
end
|
4
|
+
class Choose < Fabulator::Structural
|
5
|
+
|
6
|
+
namespace FAB_NS
|
7
|
+
|
8
|
+
contains :when, :as => :choices
|
9
|
+
contains :otherwise, :as => :default
|
22
10
|
|
23
11
|
def run(context, autovivify = false)
|
24
12
|
@context.with(context) do |ctx|
|
@@ -27,7 +15,7 @@ module Fabulator
|
|
27
15
|
return c.run(ctx)
|
28
16
|
end
|
29
17
|
end
|
30
|
-
return @default.run(ctx) unless @default.
|
18
|
+
return @default.first.run(ctx) unless @default.empty?
|
31
19
|
return []
|
32
20
|
end
|
33
21
|
end
|
@@ -41,14 +29,10 @@ module Fabulator
|
|
41
29
|
|
42
30
|
def run_test(context)
|
43
31
|
return true if @test.nil?
|
44
|
-
result =
|
32
|
+
result = self.test(@context.merge(context)).collect{ |a| !!a.value }
|
45
33
|
return false if result.nil? || result.empty? || !result.include?(true)
|
46
34
|
return true
|
47
35
|
end
|
48
|
-
|
49
|
-
def run(context, autovivify = false)
|
50
|
-
return @actions.run(@context.merge(context))
|
51
|
-
end
|
52
36
|
end
|
53
37
|
|
54
38
|
class If < Fabulator::Action
|
@@ -60,9 +44,9 @@ module Fabulator
|
|
60
44
|
def run(context, autovivify = false)
|
61
45
|
return [ ] if @test.nil?
|
62
46
|
@context.with(context) do |ctx|
|
63
|
-
test_res =
|
47
|
+
test_res = self.test(ctx).collect{ |a| !!a.value }
|
64
48
|
return [ ] if test_res.nil? || test_res.empty? || !test_res.include?(true)
|
65
|
-
return
|
49
|
+
return self.run_actions(ctx)
|
66
50
|
end
|
67
51
|
end
|
68
52
|
end
|
@@ -72,9 +56,6 @@ module Fabulator
|
|
72
56
|
namespace Fabulator::FAB_NS
|
73
57
|
has_actions
|
74
58
|
|
75
|
-
def run(context, autovivify = false)
|
76
|
-
return @actions.run(@context.merge(context),autovivify)
|
77
|
-
end
|
78
59
|
end
|
79
60
|
|
80
61
|
class Goto < Fabulator::Action
|
@@ -101,7 +82,7 @@ module Fabulator
|
|
101
82
|
return true if @test.nil?
|
102
83
|
@context.with(context) do |ctx|
|
103
84
|
ctx.set_var(@as, context) if @as
|
104
|
-
result =
|
85
|
+
result = self.test(context).collect{ |a| !!a.value }
|
105
86
|
return false if result.nil? || result.empty? || !result.include?(true)
|
106
87
|
return true
|
107
88
|
end
|
@@ -109,8 +90,8 @@ module Fabulator
|
|
109
90
|
|
110
91
|
def run(context, autovivify = false)
|
111
92
|
@context.with(context) do |ctx|
|
112
|
-
ctx.set_var(
|
113
|
-
return
|
93
|
+
ctx.set_var(self.as, context) if self.as
|
94
|
+
return self.run_actions(context)
|
114
95
|
end
|
115
96
|
end
|
116
97
|
end
|
@@ -125,12 +106,12 @@ module Fabulator
|
|
125
106
|
@context.with(context) do |ctx|
|
126
107
|
select = ctx.get_select
|
127
108
|
if !@test.nil?
|
128
|
-
test_res =
|
109
|
+
test_res = self.test(ctx).collect{ |a| !!a.value }
|
129
110
|
return [ ] if test_res.nil? || test_res.empty? || !test_res.include?(true)
|
130
111
|
end
|
131
112
|
res = [ ]
|
132
|
-
if select.nil? &&
|
133
|
-
res =
|
113
|
+
if select.nil? && self.has_actions?
|
114
|
+
res = self.run_actions(ctx)
|
134
115
|
elsif !select.nil?
|
135
116
|
res = select.run(ctx, autovivify)
|
136
117
|
else
|
@@ -1,41 +1,31 @@
|
|
1
1
|
module Fabulator
|
2
2
|
module Core
|
3
3
|
module Actions
|
4
|
-
class ForEach < Fabulator::
|
4
|
+
class ForEach < Fabulator::Structural
|
5
5
|
namespace Fabulator::FAB_NS
|
6
|
+
|
6
7
|
attribute :as, :static => true
|
7
|
-
has_select
|
8
|
-
has_actions
|
9
8
|
|
10
|
-
|
11
|
-
super
|
12
|
-
@sort = [ ]
|
9
|
+
contains :sort
|
13
10
|
|
14
|
-
|
15
|
-
|
16
|
-
case e.name
|
17
|
-
when 'sort-by':
|
18
|
-
@sort << Sort.new.compile_xml(e, @context)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
self
|
22
|
-
end
|
11
|
+
has_select
|
12
|
+
has_actions
|
23
13
|
|
24
14
|
def run(context, autovivify = false)
|
25
15
|
@context.with(context) do |ctx|
|
26
|
-
items =
|
16
|
+
items = self.select(ctx) #@select.run(ctx)
|
27
17
|
res = nil
|
28
18
|
ctx.in_context do |c|
|
29
|
-
if !@
|
19
|
+
if !@sorts.empty?
|
30
20
|
items = items.sort_by{ |i|
|
31
|
-
c.set_var(
|
32
|
-
@
|
21
|
+
c.set_var(self.as, i) unless self.as.nil?
|
22
|
+
@sorts.collect{|s| s.run(c.with_root(i)) }.join("\0")
|
33
23
|
}
|
34
24
|
end
|
35
25
|
res = [ ]
|
36
26
|
items.each do |i|
|
37
|
-
c.set_var(
|
38
|
-
res = res +
|
27
|
+
c.set_var(self.as, i) unless self.as.nil?
|
28
|
+
res = res + self.run_actions(c.with_root(i))
|
39
29
|
end
|
40
30
|
end
|
41
31
|
return res
|
@@ -48,7 +38,7 @@ module Fabulator
|
|
48
38
|
has_select
|
49
39
|
|
50
40
|
def run(context, autovivify = false)
|
51
|
-
(
|
41
|
+
(self.select(@context.merge(context)).first.to_s rescue '')
|
52
42
|
end
|
53
43
|
end
|
54
44
|
|
@@ -62,19 +52,19 @@ module Fabulator
|
|
62
52
|
return [] if @select.nil?
|
63
53
|
res = [ ]
|
64
54
|
@context.with(context) do |ctx|
|
65
|
-
c =
|
55
|
+
c = self.select(ctx)
|
66
56
|
root = nil
|
67
|
-
if
|
57
|
+
if self.as.nil?
|
68
58
|
if c.size == 1
|
69
59
|
root = c.first
|
70
60
|
else
|
71
61
|
root = Fabulator::Expr::Node.new('data', context.root.roots, nil, c)
|
72
62
|
end
|
73
|
-
res =
|
63
|
+
res = self.run_actions(ctx.with_root(root))
|
74
64
|
else
|
75
65
|
ctx.in_context do |ctx2|
|
76
|
-
ctx2.set_var(
|
77
|
-
res =
|
66
|
+
ctx2.set_var(self.as, c)
|
67
|
+
res = self.run_actions(ctx2)
|
78
68
|
end
|
79
69
|
end
|
80
70
|
end
|
@@ -92,9 +82,9 @@ module Fabulator
|
|
92
82
|
res = [ ]
|
93
83
|
counter = 0
|
94
84
|
@context.with(context) do |ctx|
|
95
|
-
lim =
|
96
|
-
while counter <
|
97
|
-
res = res +
|
85
|
+
lim = self.limit(ctx) #@limit.nil? ? 1000 : @limit.run(ctx).first.value
|
86
|
+
while counter < lim && (!!self.test(ctx).first.value rescue false)
|
87
|
+
res = res + self.run_actions(ctx)
|
98
88
|
end
|
99
89
|
end
|
100
90
|
res
|