duxml 0.8.8 → 0.8.9

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 (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