fabulator 0.0.6 → 0.0.7
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.
- 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
|