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.
Files changed (42) hide show
  1. data/History.txt +20 -0
  2. data/Rakefile +1 -0
  3. data/VERSION +1 -1
  4. data/features/step_definitions/expression_steps.rb +1 -1
  5. data/features/step_definitions/xml_steps.rb +2 -1
  6. data/features/support/env.rb +1 -0
  7. data/lib/fabulator.rb +13 -5
  8. data/lib/fabulator/action.rb +86 -19
  9. data/lib/fabulator/core/actions.rb +21 -6
  10. data/lib/fabulator/core/actions/choose.rb +16 -35
  11. data/lib/fabulator/core/actions/for_each.rb +20 -30
  12. data/lib/fabulator/core/actions/variables.rb +6 -8
  13. data/lib/fabulator/core/constraint.rb +2 -2
  14. data/lib/fabulator/core/filter.rb +0 -13
  15. data/lib/fabulator/core/group.rb +21 -25
  16. data/lib/fabulator/core/parameter.rb +5 -17
  17. data/lib/fabulator/core/state.rb +4 -44
  18. data/lib/fabulator/core/state_machine.rb +10 -38
  19. data/lib/fabulator/core/transition.rb +6 -39
  20. data/lib/fabulator/expr/axis.rb +2 -2
  21. data/lib/fabulator/expr/bin_expr.rb +3 -3
  22. data/lib/fabulator/expr/context.rb +37 -6
  23. data/lib/fabulator/expr/function.rb +9 -3
  24. data/lib/fabulator/expr/literal.rb +1 -1
  25. data/lib/fabulator/expr/node.rb +1 -1
  26. data/lib/fabulator/expr/node_logic.rb +1 -1
  27. data/lib/fabulator/expr/parser.rb +1 -1
  28. data/lib/fabulator/expr/predicates.rb +1 -1
  29. data/lib/fabulator/expr/statement_list.rb +4 -0
  30. data/lib/fabulator/expr/union_expr.rb +1 -1
  31. data/lib/fabulator/lib.rb +69 -0
  32. data/lib/fabulator/lib/action.rb +13 -0
  33. data/lib/fabulator/lib/attribute.rb +9 -0
  34. data/lib/fabulator/lib/lib.rb +47 -0
  35. data/lib/fabulator/lib/structural.rb +13 -0
  36. data/lib/fabulator/structural.rb +92 -0
  37. data/lib/fabulator/{action_lib.rb → tag_lib.rb} +89 -51
  38. data/lib/fabulator/template/standard_tags.rb +4 -3
  39. data/xsm_expression_parser.racc +1 -1
  40. metadata +27 -8
  41. data/TODO +0 -7
  42. data/features/xsm-inheritance.feature +0 -46
@@ -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.6
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::ActionLib.unify_types(
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.compile_xml(doc_xml)
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
@@ -4,4 +4,5 @@ $: << File.expand_path(File.dirname(__FILE__))+'/../../lib'
4
4
 
5
5
  require 'fabulator'
6
6
  require 'fabulator/template'
7
+ require 'fabulator/lib'
7
8
  require 'spec/expectations'
@@ -1,5 +1,13 @@
1
- require 'fabulator/expr'
2
- require 'fabulator/action_lib'
3
- require 'fabulator/action'
4
- require 'fabulator/core'
5
- require 'fabulator/version'
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
@@ -3,34 +3,38 @@ module Fabulator
3
3
 
4
4
  def compile_xml(xml, context)
5
5
  @context = context.merge(xml)
6
- klass = self.class.name
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 self.namespace(href)
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(nom, opts = { })
20
+ def self.attribute(e_nom, opts = { })
31
21
  @@attributes ||= { }
32
22
  @@attributes[self.name] ||= { }
33
- @@attributes[self.name][nom.to_s] = opts
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/action_lib'
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
- include ActionLib
11
- register_namespace FAB_NS
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 = ActionLib.find_op(args.first.vtype, :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 = ActionLib.find_op(args.first.vtype, :plus)
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::Action
5
- def compile_xml(xml, context)
6
- super
7
-
8
- @choices = [ ]
9
- @default = nil
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.nil?
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 = @test.run(@context.merge(context)).collect{ |a| !!a.value }
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 = @test.run(ctx).collect{ |a| !!a.value }
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 @actions.run(ctx)
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 = @test.run(context).collect{ |a| !!a.value }
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(@as, context) if @as
113
- return @actions.run(context)
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 = @test.run(ctx).collect{ |a| !!a.value }
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? && !@actions.nil?
133
- res = @actions.run(ctx, autovivify)
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::Action
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
- def compile_xml(xml, context)
11
- super
12
- @sort = [ ]
9
+ contains :sort
13
10
 
14
- xml.each_element do |e|
15
- next unless e.namespaces.namespace.href == FAB_NS
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 = @select.run(ctx)
16
+ items = self.select(ctx) #@select.run(ctx)
27
17
  res = nil
28
18
  ctx.in_context do |c|
29
- if !@sort.empty?
19
+ if !@sorts.empty?
30
20
  items = items.sort_by{ |i|
31
- c.set_var(@as, i) unless @as.nil?
32
- @sort.collect{|s| s.run(c.with_root(i)) }.join("\0")
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(@as, i) unless @as.nil?
38
- res = res + @actions.run(c.with_root(i))
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
- (@select.run(@context.merge(context)).first.to_s rescue '')
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 = @select.run(ctx)
55
+ c = self.select(ctx)
66
56
  root = nil
67
- if @as.nil?
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 = @actions.run(ctx.with_root(root))
63
+ res = self.run_actions(ctx.with_root(root))
74
64
  else
75
65
  ctx.in_context do |ctx2|
76
- ctx2.set_var(@as, c)
77
- res = @actions.run(ctx2)
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 = @limit.nil? ? 1000 : @limit.run(ctx).first.value
96
- while counter < @limit && (!!@test.run(ctx).first.value rescue false)
97
- res = res + @actions.run(ctx)
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