duxml 0.8.8 → 0.8.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/bin/validate_xml +30 -30
  3. data/lib/duxml.rb +76 -76
  4. data/lib/duxml/doc.rb +108 -91
  5. data/lib/duxml/doc/element.rb +250 -250
  6. data/lib/duxml/doc/lazy_ox.rb +167 -167
  7. data/lib/duxml/doc/node_set.rb +38 -38
  8. data/lib/duxml/meta.rb +72 -72
  9. data/lib/duxml/meta/grammar.rb +133 -133
  10. data/lib/duxml/meta/grammar/pattern.rb +111 -111
  11. data/lib/duxml/meta/grammar/pattern/attr_name_pattern.rb +36 -36
  12. data/lib/duxml/meta/grammar/pattern/attr_val_pattern.rb +36 -36
  13. data/lib/duxml/meta/grammar/pattern/child_pattern.rb +60 -60
  14. data/lib/duxml/meta/grammar/pattern/text_pattern.rb +31 -31
  15. data/lib/duxml/meta/grammar/pattern_maker.rb +68 -68
  16. data/lib/duxml/meta/grammar/relax_ng.rb +39 -39
  17. data/lib/duxml/meta/grammar/relax_ng/attrs_rule.rb +58 -58
  18. data/lib/duxml/meta/grammar/relax_ng/children_rule.rb +82 -82
  19. data/lib/duxml/meta/grammar/relax_ng/value_rule.rb +44 -44
  20. data/lib/duxml/meta/grammar/rule.rb +58 -58
  21. data/lib/duxml/meta/grammar/rule/attrs_rule.rb +77 -77
  22. data/lib/duxml/meta/grammar/rule/children_rule.rb +135 -135
  23. data/lib/duxml/meta/grammar/rule/text_rule.rb +39 -39
  24. data/lib/duxml/meta/grammar/rule/value_rule.rb +110 -110
  25. data/lib/duxml/meta/grammar/spreadsheet.rb +34 -34
  26. data/lib/duxml/meta/history.rb +88 -88
  27. data/lib/duxml/meta/history/add.rb +30 -30
  28. data/lib/duxml/meta/history/change.rb +70 -70
  29. data/lib/duxml/meta/history/change_attr.rb +33 -33
  30. data/lib/duxml/meta/history/change_text.rb +32 -32
  31. data/lib/duxml/meta/history/error.rb +24 -24
  32. data/lib/duxml/meta/history/new_attr.rb +32 -32
  33. data/lib/duxml/meta/history/new_text.rb +36 -36
  34. data/lib/duxml/meta/history/qualify_error.rb +21 -21
  35. data/lib/duxml/meta/history/remove.rb +27 -27
  36. data/lib/duxml/meta/history/undo.rb +23 -23
  37. data/lib/duxml/meta/history/validate_error.rb +20 -20
  38. data/lib/duxml/reportable.rb +28 -28
  39. data/lib/duxml/ruby_ext/fixnum.rb +55 -55
  40. data/lib/duxml/ruby_ext/module.rb +11 -11
  41. data/lib/duxml/ruby_ext/object.rb +13 -13
  42. data/lib/duxml/ruby_ext/regexp.rb +19 -19
  43. data/lib/duxml/ruby_ext/string.rb +37 -37
  44. data/lib/duxml/saxer.rb +75 -75
  45. metadata +12 -12
@@ -1,134 +1,134 @@
1
- # Copyright (c) 2016 Freescale Semiconductor Inc.
2
-
3
- require File.expand_path(File.dirname(__FILE__) + '/../reportable')
4
- require File.expand_path(File.dirname(__FILE__) + '/grammar/spreadsheet')
5
- require File.expand_path(File.dirname(__FILE__) + '/grammar/pattern_maker')
6
- require File.expand_path(File.dirname(__FILE__) + '/grammar/rule/children_rule')
7
- require File.expand_path(File.dirname(__FILE__) + '/grammar/rule/attrs_rule')
8
- require File.expand_path(File.dirname(__FILE__) + '/grammar/rule/value_rule')
9
- require File.expand_path(File.dirname(__FILE__) + '/../doc/lazy_ox')
10
- require File.expand_path(File.dirname(__FILE__) + '/grammar/rule/text_rule')
11
- require File.expand_path(File.dirname(__FILE__) + '/grammar/relax_ng')
12
- require 'forwardable'
13
-
14
- module Duxml
15
- # module shares name with <grammar> to activate its methods when that XML Element is encountered in a Meta file
16
- module Grammar
17
- include Reportable
18
- include Duxml
19
- include Spreadsheet
20
- include PatternMaker
21
- include LazyOx
22
- include RelaxNG
23
- end
24
- # contains Duxml::Rules and can apply them by validating XML or qualifying user input
25
- # reporting Duxml::Errors to History as needed
26
- class GrammarClass
27
- extend Forwardable
28
- include Grammar
29
-
30
- # @param rules [[RuleClass]] optional, can initialize grammar with rules
31
- def initialize(rules=[])
32
- @rules = rules
33
- end
34
-
35
- def_delegators :@rules, :<<, :[], :each
36
- attr_reader :rules
37
- alias_method :nodes, :rules
38
- end
39
-
40
- module Grammar
41
- # @param path [String] path of grammar file; can be in .xlsx, .csv or Duxml GrammarClass file
42
- # @return [GrammarClass, Element] XML Element named <grammar> and GrammarClass object are functionally equivalent
43
- def self.import(path)
44
- if %w(.xlsx .csv).include?(File.extname path)
45
- doc = Spreadsheet.sheet_to_xml path
46
- File.write(File.basename(path)+'.xml', Ox.dump(doc)) #TODO make optional!
47
- doc
48
- else
49
- Ox.parse_obj(File.read path)
50
- end
51
- end
52
-
53
- # @return [Doc] returns self as XML document
54
- def xml
55
- Element.new('grammar') << rules.collect do |rule| rule.xml end
56
- end
57
-
58
- # @return [History] history that this grammar is currently reporting to
59
- def history
60
- @observer_peers.first.first if @observer_peers and @observer_peers.any? and @observer_peers.first.any?
61
- end
62
-
63
- # @return [Boolean] whether or not any rules have been defined yet in this grammar
64
- def defined?
65
- !rules.empty?
66
- end
67
-
68
- # @param obj [Object] object that will observe this grammar's rules, usually the History
69
- def add_observer(obj, sym=nil)
70
- super(obj, sym || :update)
71
- @rules.each do |r| r.add_observer(obj, :update)end
72
- end
73
-
74
- # @return [String] lists XML schema and content rules in order of precedence
75
- def description
76
- "grammar follows: \n" +
77
- rules.collect do |change_or_error|
78
- change_or_error.description
79
- end.join("\n")
80
- end
81
-
82
- # @return [String] formatted to appear in tight spaces e.g. debugger
83
- def inspect
84
- "#<#{self.class.to_s} #{object_id}: @rules=#{rules.size}>"
85
- end
86
-
87
- # @return [String] 'grammar'
88
- def name
89
- 'grammar'
90
- end
91
-
92
- # @param node [Duxml::Object] applies grammar rules to all relationships of the given object
93
- # @result [Boolean] whether all rules qualified
94
- def validate(node)
95
- rels = get_relationships(node)
96
- results = rels.collect do |rel|
97
- qualify rel
98
- end
99
- any_disqualified = results.any? do |qualified| !qualified end
100
- !any_disqualified
101
- end # def validate
102
-
103
- # @param change_or_pattern [Duxml::Change, Duxml::Pattern] applies applicable rule type and subject
104
- # to given change_or_pattern and generates errors when disqualified
105
- # @return [Boolean] false if any rule disqualifies; true if they all pass
106
- def qualify(change_or_pattern)
107
- return true unless self.defined?
108
- rules = get_rule(change_or_pattern)
109
-
110
- # define behaviors for when there are no rules applying to a given pattern
111
- if rules.empty?
112
-
113
- if change_or_pattern.respond_to?(:text) or
114
- change_or_pattern.respond_to?(:value) or
115
- change_or_pattern.subject.is_a?(Doc)
116
- return true
117
- end
118
- report(:ValidateError, change_or_pattern)
119
- return false
120
- end
121
- results = rules.collect do |rule|
122
- rule.qualify change_or_pattern
123
- end
124
- !results.any? do |qualified| !qualified end
125
- end # def qualify
126
-
127
- # @param change_or_pattern [Duxml::Change, Duxml::Pattern] change or pattern to be qualified
128
- # @return [Array[Duxml::Rule]] rules that match the pattern type (e.g. :change_content => :content_rule)
129
- # and subject (e.g. change_or_pattern.subject.type => 'blobs' && rule.subject => 'blobs')
130
- def get_rule(change_or_pattern)
131
- rules.select do |rule| rule.applies_to?(change_or_pattern) end
132
- end # def get_rules
133
- end # module Grammar
1
+ # Copyright (c) 2016 Freescale Semiconductor Inc.
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + '/../reportable')
4
+ require File.expand_path(File.dirname(__FILE__) + '/grammar/spreadsheet')
5
+ require File.expand_path(File.dirname(__FILE__) + '/grammar/pattern_maker')
6
+ require File.expand_path(File.dirname(__FILE__) + '/grammar/rule/children_rule')
7
+ require File.expand_path(File.dirname(__FILE__) + '/grammar/rule/attrs_rule')
8
+ require File.expand_path(File.dirname(__FILE__) + '/grammar/rule/value_rule')
9
+ require File.expand_path(File.dirname(__FILE__) + '/../doc/lazy_ox')
10
+ require File.expand_path(File.dirname(__FILE__) + '/grammar/rule/text_rule')
11
+ require File.expand_path(File.dirname(__FILE__) + '/grammar/relax_ng')
12
+ require 'forwardable'
13
+
14
+ module Duxml
15
+ # module shares name with <grammar> to activate its methods when that XML Element is encountered in a Meta file
16
+ module Grammar
17
+ include Reportable
18
+ include Duxml
19
+ include Spreadsheet
20
+ include PatternMaker
21
+ include LazyOx
22
+ include RelaxNG
23
+ end
24
+ # contains Duxml::Rules and can apply them by validating XML or qualifying user input
25
+ # reporting Duxml::Errors to History as needed
26
+ class GrammarClass
27
+ extend Forwardable
28
+ include Grammar
29
+
30
+ # @param rules [[RuleClass]] optional, can initialize grammar with rules
31
+ def initialize(rules=[])
32
+ @rules = rules
33
+ end
34
+
35
+ def_delegators :@rules, :<<, :[], :each
36
+ attr_reader :rules
37
+ alias_method :nodes, :rules
38
+ end
39
+
40
+ module Grammar
41
+ # @param path [String] path of grammar file; can be in .xlsx, .csv or Duxml GrammarClass file
42
+ # @return [GrammarClass, Element] XML Element named <grammar> and GrammarClass object are functionally equivalent
43
+ def self.import(path)
44
+ if %w(.xlsx .csv).include?(File.extname path)
45
+ doc = Spreadsheet.sheet_to_xml path
46
+ File.write(File.basename(path)+'.xml', Ox.dump(doc)) #TODO make optional!
47
+ doc
48
+ else
49
+ Ox.parse_obj(File.read path)
50
+ end
51
+ end
52
+
53
+ # @return [Doc] returns self as XML document
54
+ def xml
55
+ Element.new('grammar') << rules.collect do |rule| rule.xml end
56
+ end
57
+
58
+ # @return [History] history that this grammar is currently reporting to
59
+ def history
60
+ @observer_peers.first.first if @observer_peers and @observer_peers.any? and @observer_peers.first.any?
61
+ end
62
+
63
+ # @return [Boolean] whether or not any rules have been defined yet in this grammar
64
+ def defined?
65
+ !rules.empty?
66
+ end
67
+
68
+ # @param obj [Object] object that will observe this grammar's rules, usually the History
69
+ def add_observer(obj, sym=nil)
70
+ super(obj, sym || :update)
71
+ @rules.each do |r| r.add_observer(obj, :update)end
72
+ end
73
+
74
+ # @return [String] lists XML schema and content rules in order of precedence
75
+ def description
76
+ "grammar follows: \n" +
77
+ rules.collect do |change_or_error|
78
+ change_or_error.description
79
+ end.join("\n")
80
+ end
81
+
82
+ # @return [String] formatted to appear in tight spaces e.g. debugger
83
+ def inspect
84
+ "#<#{self.class.to_s} #{object_id}: @rules=#{rules.size}>"
85
+ end
86
+
87
+ # @return [String] 'grammar'
88
+ def name
89
+ 'grammar'
90
+ end
91
+
92
+ # @param node [Duxml::Object] applies grammar rules to all relationships of the given object
93
+ # @result [Boolean] whether all rules qualified
94
+ def validate(node)
95
+ rels = get_relationships(node)
96
+ results = rels.collect do |rel|
97
+ qualify rel
98
+ end
99
+ any_disqualified = results.any? do |qualified| !qualified end
100
+ !any_disqualified
101
+ end # def validate
102
+
103
+ # @param change_or_pattern [Duxml::Change, Duxml::Pattern] applies applicable rule type and subject
104
+ # to given change_or_pattern and generates errors when disqualified
105
+ # @return [Boolean] false if any rule disqualifies; true if they all pass
106
+ def qualify(change_or_pattern)
107
+ return true unless self.defined?
108
+ rules = get_rule(change_or_pattern)
109
+
110
+ # define behaviors for when there are no rules applying to a given pattern
111
+ if rules.empty?
112
+
113
+ if change_or_pattern.respond_to?(:text) or
114
+ change_or_pattern.respond_to?(:value) or
115
+ change_or_pattern.subject.is_a?(Doc)
116
+ return true
117
+ end
118
+ report(:ValidateError, change_or_pattern)
119
+ return false
120
+ end
121
+ results = rules.collect do |rule|
122
+ rule.qualify change_or_pattern
123
+ end
124
+ !results.any? do |qualified| !qualified end
125
+ end # def qualify
126
+
127
+ # @param change_or_pattern [Duxml::Change, Duxml::Pattern] change or pattern to be qualified
128
+ # @return [Array[Duxml::Rule]] rules that match the pattern type (e.g. :change_content => :content_rule)
129
+ # and subject (e.g. change_or_pattern.subject.type => 'blobs' && rule.subject => 'blobs')
130
+ def get_rule(change_or_pattern)
131
+ rules.select do |rule| rule.applies_to?(change_or_pattern) end
132
+ end # def get_rules
133
+ end # module Grammar
134
134
  end # module Duxml
@@ -1,112 +1,112 @@
1
- # Copyright (c) 2016 Freescale Semiconductor Inc.
2
-
3
- require File.expand_path(File.dirname(__FILE__) + '/../../ruby_ext/string')
4
-
5
- module Duxml
6
- # Patterns represent a relationship between a specific XML Element and
7
- # a specific or hypothetical attribute, attribute value, text value or child Element
8
- # For example, given an XML Element: '<element attr='value'/>', there exists a valid PatternClass
9
- # that represents the relationship betweeen <element> and the attribute value 'value'
10
- # There can also exists a hypothetical relationship between <element> and a new child <child/> that
11
- # is defined as an allowed child Element in the Rules that apply to this Element.
12
- module Pattern; end
13
-
14
- # as an object, a Pattern consists of a subject and may or may not have an object
15
- # a Pattern without an object represents a childless empty node with no attributes
16
- # this class must be subclassed to be used; there is one for each type of XML relationship
17
- # that an Element can have up to one degree of separation, that is, grandparent relationships are not considered
18
- # and neither are the attributes of children
19
- class PatternClass
20
- include Pattern
21
- @subject
22
-
23
- # @param subj [Element] specific Element that is the subject of this pattern
24
- def initialize(subj)
25
- @subject = subj
26
- end
27
-
28
- attr_reader :subject
29
- end
30
-
31
- module Pattern
32
- include Duxml
33
-
34
- def xml
35
- p = Element.new(simple_name)
36
- instance_variables.each do |sym|
37
- val = instance_variable_get(sym)
38
- if val.respond_to?(:nodes)
39
- d = Element.new(sym.to_s) << val
40
- p << d
41
- else
42
- p[sym.to_s[1..-1].to_sym] = val.to_s unless sym == :@observer_peers
43
- end
44
- end
45
- p
46
- end
47
-
48
- # @return [String] nmtoken name of this pattern without namespace prefix e.g. ChildPattern.new(parent, child).name => 'child_pattern'
49
- def simple_name
50
- name.split(':').last
51
- end
52
-
53
- # @return [Boolean] if either subject or object points to a name/type i.e. not an Element
54
- def abstract?
55
- subject.is_a?(String) or object.nil?
56
- end
57
-
58
- # @return [Boolean] if both subject and at least one object point to an actual XML Element
59
- def concrete?
60
- !abstract?
61
- end
62
-
63
- # @return [String] nmtoken name of this pattern e.g. ChildPattern.new(parent, child).name => 'duxml:child_pattern'
64
- def name
65
- c = self.class.to_s
66
- return c.nmtokenize unless c.include?('::')
67
- a = c.split('::')
68
- a[-2..-1].collect do |word|
69
- word.nmtokenize
70
- end.join(':')
71
- end
72
-
73
- # returns relationship description as string by subtracting super class name
74
- # (e.g. 'pattern' or 'rule') from simple_class
75
- # Duxml::ChildrenRule#relationship => 'children'
76
- # Duxml::TextPattern#relationship => 'text'
77
- # can be overridden if class name does not match human-readable string
78
- # @return [String] single word to describe relationship of subject to object
79
- def relationship
80
- simple_name.split('_').first
81
- end
82
-
83
- # @return [String] "#{object.description} is #{relationship} of #{subject.description}"
84
- def description
85
- "#{object.description} is #{relationship} of #{subject.description}"
86
- end
87
-
88
- # @return [Element] will only return non-nil value when pattern represents relationship with a child Element
89
- def object
90
- return @object if instance_variable_defined?(:@object)
91
- instance_variables.each do |var|
92
- target = instance_variable_get(var)
93
- return target unless target.is_a?(String) or target == subject
94
- end
95
- nil
96
- end
97
-
98
- # @param pattern [Duxml::Pattern] pattern or any subclass object
99
- # @return [Fixnum] first applies <=> to subjects, and if equal, applies <=> to objects
100
- def <=>(pattern)
101
- return 1 unless pattern.respond_to?(:subject)
102
- case subject <=> pattern.subject
103
- when -1 then
104
- -1
105
- when 0 then
106
- object <=> pattern.object
107
- else
108
- -1
109
- end
110
- end # def <=>
111
- end # module Pattern
1
+ # Copyright (c) 2016 Freescale Semiconductor Inc.
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + '/../../ruby_ext/string')
4
+
5
+ module Duxml
6
+ # Patterns represent a relationship between a specific XML Element and
7
+ # a specific or hypothetical attribute, attribute value, text value or child Element
8
+ # For example, given an XML Element: '<element attr='value'/>', there exists a valid PatternClass
9
+ # that represents the relationship betweeen <element> and the attribute value 'value'
10
+ # There can also exists a hypothetical relationship between <element> and a new child <child/> that
11
+ # is defined as an allowed child Element in the Rules that apply to this Element.
12
+ module Pattern; end
13
+
14
+ # as an object, a Pattern consists of a subject and may or may not have an object
15
+ # a Pattern without an object represents a childless empty node with no attributes
16
+ # this class must be subclassed to be used; there is one for each type of XML relationship
17
+ # that an Element can have up to one degree of separation, that is, grandparent relationships are not considered
18
+ # and neither are the attributes of children
19
+ class PatternClass
20
+ include Pattern
21
+ @subject
22
+
23
+ # @param subj [Element] specific Element that is the subject of this pattern
24
+ def initialize(subj)
25
+ @subject = subj
26
+ end
27
+
28
+ attr_reader :subject
29
+ end
30
+
31
+ module Pattern
32
+ include Duxml
33
+
34
+ def xml
35
+ p = Element.new(simple_name)
36
+ instance_variables.each do |sym|
37
+ val = instance_variable_get(sym)
38
+ if val.respond_to?(:nodes)
39
+ d = Element.new(sym.to_s) << val
40
+ p << d
41
+ else
42
+ p[sym.to_s[1..-1].to_sym] = val.to_s unless sym == :@observer_peers
43
+ end
44
+ end
45
+ p
46
+ end
47
+
48
+ # @return [String] nmtoken name of this pattern without namespace prefix e.g. ChildPattern.new(parent, child).name => 'child_pattern'
49
+ def simple_name
50
+ name.split(':').last
51
+ end
52
+
53
+ # @return [Boolean] if either subject or object points to a name/type i.e. not an Element
54
+ def abstract?
55
+ subject.is_a?(String) or object.nil?
56
+ end
57
+
58
+ # @return [Boolean] if both subject and at least one object point to an actual XML Element
59
+ def concrete?
60
+ !abstract?
61
+ end
62
+
63
+ # @return [String] nmtoken name of this pattern e.g. ChildPattern.new(parent, child).name => 'duxml:child_pattern'
64
+ def name
65
+ c = self.class.to_s
66
+ return c.nmtokenize unless c.include?('::')
67
+ a = c.split('::')
68
+ a[-2..-1].collect do |word|
69
+ word.nmtokenize
70
+ end.join(':')
71
+ end
72
+
73
+ # returns relationship description as string by subtracting super class name
74
+ # (e.g. 'pattern' or 'rule') from simple_class
75
+ # Duxml::ChildrenRule#relationship => 'children'
76
+ # Duxml::TextPattern#relationship => 'text'
77
+ # can be overridden if class name does not match human-readable string
78
+ # @return [String] single word to describe relationship of subject to object
79
+ def relationship
80
+ simple_name.split('_').first
81
+ end
82
+
83
+ # @return [String] "#{object.description} is #{relationship} of #{subject.description}"
84
+ def description
85
+ "#{object.description} is #{relationship} of #{subject.description}"
86
+ end
87
+
88
+ # @return [Element] will only return non-nil value when pattern represents relationship with a child Element
89
+ def object
90
+ return @object if instance_variable_defined?(:@object)
91
+ instance_variables.each do |var|
92
+ target = instance_variable_get(var)
93
+ return target unless target.is_a?(String) or target == subject
94
+ end
95
+ nil
96
+ end
97
+
98
+ # @param pattern [Duxml::Pattern] pattern or any subclass object
99
+ # @return [Fixnum] first applies <=> to subjects, and if equal, applies <=> to objects
100
+ def <=>(pattern)
101
+ return 1 unless pattern.respond_to?(:subject)
102
+ case subject <=> pattern.subject
103
+ when -1 then
104
+ -1
105
+ when 0 then
106
+ object <=> pattern.object
107
+ else
108
+ -1
109
+ end
110
+ end # def <=>
111
+ end # module Pattern
112
112
  end # module Duxml