fabulator 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
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