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
@@ -20,7 +20,7 @@ module Fabulator
20
20
 
21
21
  def run(context, autovivify = false)
22
22
  @context.with(context) do |ctx|
23
- ctx.set_value(@path, @select.nil? ? @actions : @select )
23
+ ctx.set_value(self.path, @select.nil? ? @actions : @select )
24
24
  end
25
25
  end
26
26
  end
@@ -32,18 +32,16 @@ module Fabulator
32
32
  has_actions
33
33
 
34
34
  def run(context, autovivify = false)
35
- return [] if @name.nil?
35
+ return [] if self.name.nil?
36
36
  res = [ ]
37
37
  @context.with(context) do |ctx|
38
38
  if @select
39
- res = @select.run(ctx, autovivify)
40
- elsif !@actions.empty?
41
- @actions.each do |a|
42
- res = a.run(ctx, autovivify)
43
- end
39
+ res = self.select(ctx)
40
+ else
41
+ res = self.run_actions(ctx)
44
42
  end
45
43
  end
46
- context.set_var(@name, res)
44
+ context.set_var(self.name, res)
47
45
  res
48
46
  end
49
47
  end
@@ -9,6 +9,7 @@ module Fabulator
9
9
 
10
10
  def compile_xml(xml, ctx)
11
11
  super
12
+
12
13
  @constraints = [ ]
13
14
  @values = [ ]
14
15
  @params = [ ]
@@ -28,7 +29,7 @@ module Fabulator
28
29
  e_ctx = @context.merge(e)
29
30
  case e.name
30
31
  when 'param':
31
- pname = e_ctx.attribute(FAB_NS, 'name') # (e.get_attribute_ns(FAB_NS, 'name').value rescue nil)
32
+ pname = e_ctx.attribute(FAB_NS, 'name')
32
33
  if !pname.nil?
33
34
  v = e_ctx.attribute(FAB_NS, 'value', { :default => e_ctx.get_select })
34
35
  @params[pname] = v unless v.nil?
@@ -44,7 +45,6 @@ module Fabulator
44
45
  end
45
46
  end
46
47
  end
47
- self
48
48
  end
49
49
 
50
50
  def error_message(context)
@@ -4,19 +4,6 @@ module Fabulator
4
4
  namespace Fabulator::FAB_NS
5
5
  attribute :name, :static => true
6
6
 
7
- # def compile_xml(xml, context)
8
- # @context = context.merge(xml)
9
- # filter_type = @context.attribute(FAB_NS, 'name', {:static => true}).split(/:/, 2)
10
- # if filter_type.size == 2
11
- # @ns = @context.get_ns(filter_type[0])
12
- # @name = filter_type[1]
13
- # else
14
- # @ns = FAB_NS
15
- # @name = filter_type[0]
16
- # end
17
- # self
18
- # end
19
-
20
7
  def run(context)
21
8
  filtered = [ ]
22
9
  @context.with(context) do |ctx|
@@ -1,41 +1,37 @@
1
1
  module Fabulator
2
2
  module Core
3
- class Group < Fabulator::Action
3
+ class Group < Fabulator::Structural
4
4
  attr_accessor :name, :params, :tags, :required_params
5
5
 
6
6
  namespace Fabulator::FAB_NS
7
7
 
8
+ contains 'group', :as => :groups
9
+ contains 'param', :as => :params
10
+ contains 'constraint', :as => :constraints
11
+ contains 'filter', :as => :filters
12
+
8
13
  has_select
9
14
 
10
- def initialize
11
- @params = [ ]
12
- @constraints = [ ]
13
- @filters = [ ]
14
- @required_params = [ ]
15
- @tags = [ ]
16
- end
15
+ attribute :select, :as => :name, :static => true
17
16
 
18
17
  def compile_xml(xml, context)
19
18
  super
20
- xml.each_element do |e|
21
- next unless e.namespaces.namespace.href == FAB_NS
22
19
 
23
- case e.name
24
- when 'param':
25
- v = Parameter.new.compile_xml(e,@context)
26
- @params << v
27
- @required_params = @required_params + v.names if v.required?
28
- when 'group':
29
- v = Group.new.compile_xml(e,@context)
30
- @params << v
31
- @required_params = @required_params + v.required_params.collect{ |n| (@name + '/' + n).gsub(/\/+/, '/') }
32
- when 'constraint':
33
- @constraints << Constraint.new.compile_xml(e,@context)
34
- when 'filter':
35
- @filters << Filter.new.compile_xml(e,@context)
36
- end
20
+ @required_params = [ ]
21
+
22
+ @params.each do |p|
23
+ @required_params += p.names if p.required?
37
24
  end
38
- self
25
+
26
+ @name = '' if @name.nil?
27
+ @name.gsub!(/^\//, '')
28
+
29
+ @groups.each do |g|
30
+ @required_params += g.required_params.collect{ |n| (@name + '/' + n).gsub(/\/+/, '/') }
31
+ end
32
+
33
+ @params += @groups
34
+ @groups = nil
39
35
  end
40
36
 
41
37
  def apply_filters(context)
@@ -1,6 +1,6 @@
1
1
  module Fabulator
2
2
  module Core
3
- class Parameter < Fabulator::Action
3
+ class Parameter < Fabulator::Structural
4
4
  attr_accessor :name
5
5
 
6
6
  namespace Fabulator::FAB_NS
@@ -8,6 +8,10 @@ module Fabulator
8
8
  attribute :name, :eval => false, :static => true
9
9
  attribute :required, :static => true, :default => 'false'
10
10
 
11
+ contains :constraint
12
+ contains :filter
13
+ contains :value, :as => :constraints
14
+
11
15
  def required?
12
16
  @required
13
17
  end
@@ -23,9 +27,6 @@ module Fabulator
23
27
  def compile_xml(xml, context)
24
28
  super
25
29
 
26
- @constraints = [ ]
27
- @filters = [ ]
28
-
29
30
  case @required.downcase
30
31
  when 'yes':
31
32
  @required = true
@@ -36,19 +37,6 @@ module Fabulator
36
37
  when 'false':
37
38
  @required = false
38
39
  end
39
-
40
- xml.each_element do |e|
41
- next unless e.namespaces.namespace.href == FAB_NS
42
- case e.name
43
- when 'constraint':
44
- @constraints << Constraint.new.compile_xml(e, @context)
45
- when 'filter':
46
- @filters << Filter.new.compile_xml(e, @context)
47
- when 'value':
48
- @constraints << Constraint.new.compile_xml(e, @context)
49
- end
50
- end
51
- self
52
40
  end
53
41
 
54
42
  def get_context(context)
@@ -1,54 +1,13 @@
1
1
  module Fabulator
2
2
  module Core
3
- class State < Fabulator::Action
3
+ class State < Fabulator::Structural
4
4
  attr_accessor :name, :transitions
5
5
 
6
- def initialize
7
- @transitions = []
8
- @pre_actions = nil
9
- @post_actions = nil
10
- end
11
-
12
6
  namespace Fabulator::FAB_NS
13
- attribute :name, :static => true
14
-
15
7
 
16
- def compile_xml(xml, ctx)
17
- super
8
+ attribute :name, :static => true
18
9
 
19
- inheriting = !@transitions.empty?
20
- xml.each_element do |e|
21
- next unless e.namespaces.namespace.href == FAB_NS
22
- case e.name
23
- when 'goes-to':
24
- if inheriting
25
- target = e.attributes.get_attribute_ns(FAB_NS, 'view').value
26
- tags = (e.attributes.get_attribute_ns(FAB_NS, 'tag').value rescue '').split(/\s+/)
27
- old = @transitions.collect{ |t| t.state == target && (tags.empty? || !(tags & t.tags).empty?)}
28
- if old.empty?
29
- @transitions << Transition.new.compile_xml(e,@context)
30
- else
31
- old.each do |t|
32
- t.compile_xml(e,@context)
33
- end
34
- end
35
- else
36
- @transitions << Transition.new.compile_xml(e, @context)
37
- end
38
- when 'before':
39
- ActionLib.with_super(@pre_actions) do
40
- t = @context.compile_actions(e)
41
- @pre_actions = t if @pre_actions.nil? || !t.is_noop?
42
- end
43
- when 'after':
44
- ActionLib.with_super(@post_actions) do
45
- t = @context.compile_actions(e)
46
- @post_actions = t if @post_actions.nil? || !t.is_noop?
47
- end
48
- end
49
- end
50
- self
51
- end
10
+ contains 'goes-to', :as => :transitions
52
11
 
53
12
  def states
54
13
  @transitions.map { |t| t.state }.uniq
@@ -56,6 +15,7 @@ module Fabulator
56
15
 
57
16
  def select_transition(context,params)
58
17
  # we need hypthetical variables here :-/
18
+ return nil if @context.nil?
59
19
  best_match = nil
60
20
  @context.with(context) do |ctx|
61
21
  best_match = nil
@@ -2,63 +2,35 @@ require 'yaml'
2
2
  require 'xml/libxml'
3
3
 
4
4
  module Fabulator
5
- FAB_NS='http://dh.tamu.edu/ns/fabulator/1.0#'
6
- RDFS_NS = 'http://www.w3.org/2000/01/rdf-schema#'
7
- RDF_NS = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#'
8
- RDFA_NS = 'http://dh.tamu.edu/ns/fabulator/rdf/1.0#'
9
-
10
5
  class StateChangeException < Exception
11
6
  end
12
7
 
13
8
  module Core
14
9
 
15
- class StateMachine
10
+ class StateMachine < Structural
16
11
  attr_accessor :states, :missing_params, :errors, :namespaces, :updated_at
17
12
  attr_accessor :state
18
13
 
14
+ namespace FAB_NS
15
+
16
+ contains :view, :as => :states, :storage => :hash
17
+
18
+ has_actions
19
+
19
20
  def initialize
20
21
  @states = { }
21
22
  @context = Fabulator::Expr::Context.new
22
23
  @state = 'start'
23
24
  end
24
25
 
25
- def compile_xml(xml, context = nil, callbacks = { })
26
- # /statemachine/states
27
- XML.default_line_numbers = true
28
- if xml.is_a?(String)
29
- xml = LibXML::XML::Document.string xml
30
- end
31
-
32
- if context.nil?
33
- @context = @context.merge(xml.root)
34
- else
35
- @context = context.merge(xml.root)
36
- end
37
-
38
- ActionLib.with_super(@actions) do
39
- p_actions = @context.compile_actions(xml.root)
40
- @actions = p_actions if @actions.nil? || !p_actions.is_noop?
41
- end
42
-
43
- xml.root.each_element do |child|
44
- next unless child.namespaces.namespace.href == FAB_NS
45
- case child.name
46
- when 'view':
47
- nom = (child.attributes.get_attribute_ns(FAB_NS, 'name').value rescue nil)
48
- if !@states[nom].nil?
49
- @states[nom].compile_xml(child, @context)
50
- else
51
- @states[nom] = State.new.compile_xml(child, @context)
52
- end
53
- end
54
- end
26
+ def compile_xml(xml, context = nil)
27
+ super
55
28
 
56
29
  if @states.empty?
57
30
  s = State.new
58
31
  s.name = 'start'
59
- @states['start'] = s
32
+ @states = { 'start' => s }
60
33
  end
61
- self
62
34
  end
63
35
 
64
36
  def clone
@@ -1,49 +1,16 @@
1
1
  module Fabulator
2
2
  module Core
3
- class Transition < Fabulator::Action
3
+ class Transition < Fabulator::Structural
4
4
  attr_accessor :state, :validations, :tags
5
5
 
6
- namespace Fabulator::FAB_NS
7
- attribute :view, :as => :lstate, :static => true
8
- attribute :tag, :as => :ltags, :static => true, :default => ''
6
+ namespace FAB_NS
9
7
 
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
8
+ attribute :view, :as => :state, :static => true
9
+ #attribute :tag, :as => :ltags, :static => true, :default => ''
20
10
 
21
- inheriting = !@state.nil?
22
-
23
- if !inheriting
24
- @state = @lstate
25
- @tags = @ltags
26
- end
11
+ contains :params, :as => :params
27
12
 
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
- @params << Group.new.compile_xml(e, @context)
43
- end
44
- end
45
- self
46
- end
13
+ has_actions
47
14
 
48
15
  def param_names
49
16
  (@params.collect{|w| w.param_names}.flatten).uniq
@@ -23,8 +23,8 @@ module Fabulator
23
23
  if @root.nil? || @root == ''
24
24
  return @axis.run(context, autovivify)
25
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)
26
+ if context.root.roots[@root].nil? && !Fabulator::TagLib.axes[@root].nil?
27
+ context.root.roots[@root] = Fabulator::TagLib.axes[@root].call(context)
28
28
  end
29
29
  return context.root.roots[@root].nil? ? [ ] :
30
30
  @axis.nil? ? [ context.root.roots[@root] ] :
@@ -9,7 +9,7 @@ module Fabulator
9
9
  def expr_type(context)
10
10
  lt = @left.expr_type(context)
11
11
  rt = @right.expr_type(context)
12
- Fabulator::ActionLib.unify_types([ lt, rt ])
12
+ Fabulator::TagLib.unify_types([ lt, rt ])
13
13
  end
14
14
 
15
15
  def run(context, autovivify = false)
@@ -23,8 +23,8 @@ module Fabulator
23
23
 
24
24
  l.each do |i|
25
25
  r.each do |j|
26
- ut = Fabulator::ActionLib.unify_types([ i.vtype, j.vtype ])
27
- op = ActionLib.find_op(ut, self.op)
26
+ ut = Fabulator::TagLib.unify_types([ i.vtype, j.vtype ])
27
+ op = TagLib.find_op(ut, self.op)
28
28
  if(op && op[:proc])
29
29
  calc = op[:proc].call(i.to(ut), j.to(ut))
30
30
  else
@@ -318,8 +318,13 @@ module Fabulator
318
318
  end
319
319
  end
320
320
  d.each do |i|
321
- c = root_context.create_child(node_name)
322
- self.with_root(c).merge_data(i)
321
+ next if i.nil?
322
+ if i.is_a?(Array) || i.is_a?(Hash)
323
+ c = root_context.create_child(node_name)
324
+ self.with_root(c).merge_data(i)
325
+ else
326
+ root_context.create_child(node_name, i)
327
+ end
323
328
  end
324
329
  elsif d.is_a?(Hash)
325
330
  d.each_pair do |k,v|
@@ -338,10 +343,12 @@ module Fabulator
338
343
 
339
344
  def compile_actions(xml)
340
345
  actions = Fabulator::Expr::StatementList.new
346
+ return actions if xml.nil?
347
+
341
348
  local_ctx = self.merge(xml)
342
349
  xml.each_element do |e|
343
350
  ns = e.namespaces.namespace.href
344
- next unless Fabulator::ActionLib.namespaces.include?(ns)
351
+ next unless Fabulator::TagLib.namespaces.include?(ns)
345
352
  if ns == FAB_NS && e.name == 'ensure'
346
353
  actions.add_ensure(local_ctx.compile_actions(e))
347
354
  elsif ns == FAB_NS && e.name == 'catch'
@@ -355,8 +362,32 @@ module Fabulator
355
362
 
356
363
  def compile_action(e)
357
364
  ns = e.namespaces.namespace.href
358
- return unless Fabulator::ActionLib.namespaces.include?(ns)
359
- Fabulator::ActionLib.namespaces[ns].compile_action(e, self)
365
+ return unless Fabulator::TagLib.namespaces.include?(ns)
366
+ Fabulator::TagLib.namespaces[ns].compile_action(e, self)
367
+ end
368
+
369
+ def compile_structurals(xml)
370
+ #local_ctx = self.merge(xml)
371
+ structs = { }
372
+ our_ns = xml.namespaces.namespace.href
373
+ our_nom = xml.name
374
+ xml.each_element do |e|
375
+ ns = e.namespaces.namespace.href
376
+ nom = e.name.to_sym
377
+ allowed = (Fabulator::TagLib.namespaces[our_ns].structural_class(our_nom).accepts_structural?(ns, nom) rescue false)
378
+ next unless allowed
379
+ structs[ns] ||= { }
380
+ structs[ns][nom] ||= [ ]
381
+ structs[ns][nom] << self.compile_structural(e)
382
+ structs[ns][nom] -= [ nil ]
383
+ end
384
+ return structs
385
+ end
386
+
387
+ def compile_structural(e)
388
+ ns = e.namespaces.namespace.href
389
+ return unless Fabulator::TagLib.namespaces.include?(ns)
390
+ Fabulator::TagLib.namespaces[ns].compile_structural(e, self)
360
391
  end
361
392
 
362
393
  def in_context(&block)
@@ -381,7 +412,7 @@ module Fabulator
381
412
  end
382
413
 
383
414
  def run_filter(ns, name)
384
- handler = Fabulator::ActionLib.namespaces[ns]
415
+ handler = Fabulator::TagLib.namespaces[ns]
385
416
  return [] if handler.nil?
386
417
  handler.run_filter(self, name)
387
418
  end