duxml 0.8.8 → 0.8.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/validate_xml +30 -30
- data/lib/duxml.rb +76 -76
- data/lib/duxml/doc.rb +108 -91
- data/lib/duxml/doc/element.rb +250 -250
- data/lib/duxml/doc/lazy_ox.rb +167 -167
- data/lib/duxml/doc/node_set.rb +38 -38
- data/lib/duxml/meta.rb +72 -72
- data/lib/duxml/meta/grammar.rb +133 -133
- data/lib/duxml/meta/grammar/pattern.rb +111 -111
- data/lib/duxml/meta/grammar/pattern/attr_name_pattern.rb +36 -36
- data/lib/duxml/meta/grammar/pattern/attr_val_pattern.rb +36 -36
- data/lib/duxml/meta/grammar/pattern/child_pattern.rb +60 -60
- data/lib/duxml/meta/grammar/pattern/text_pattern.rb +31 -31
- data/lib/duxml/meta/grammar/pattern_maker.rb +68 -68
- data/lib/duxml/meta/grammar/relax_ng.rb +39 -39
- data/lib/duxml/meta/grammar/relax_ng/attrs_rule.rb +58 -58
- data/lib/duxml/meta/grammar/relax_ng/children_rule.rb +82 -82
- data/lib/duxml/meta/grammar/relax_ng/value_rule.rb +44 -44
- data/lib/duxml/meta/grammar/rule.rb +58 -58
- data/lib/duxml/meta/grammar/rule/attrs_rule.rb +77 -77
- data/lib/duxml/meta/grammar/rule/children_rule.rb +135 -135
- data/lib/duxml/meta/grammar/rule/text_rule.rb +39 -39
- data/lib/duxml/meta/grammar/rule/value_rule.rb +110 -110
- data/lib/duxml/meta/grammar/spreadsheet.rb +34 -34
- data/lib/duxml/meta/history.rb +88 -88
- data/lib/duxml/meta/history/add.rb +30 -30
- data/lib/duxml/meta/history/change.rb +70 -70
- data/lib/duxml/meta/history/change_attr.rb +33 -33
- data/lib/duxml/meta/history/change_text.rb +32 -32
- data/lib/duxml/meta/history/error.rb +24 -24
- data/lib/duxml/meta/history/new_attr.rb +32 -32
- data/lib/duxml/meta/history/new_text.rb +36 -36
- data/lib/duxml/meta/history/qualify_error.rb +21 -21
- data/lib/duxml/meta/history/remove.rb +27 -27
- data/lib/duxml/meta/history/undo.rb +23 -23
- data/lib/duxml/meta/history/validate_error.rb +20 -20
- data/lib/duxml/reportable.rb +28 -28
- data/lib/duxml/ruby_ext/fixnum.rb +55 -55
- data/lib/duxml/ruby_ext/module.rb +11 -11
- data/lib/duxml/ruby_ext/object.rb +13 -13
- data/lib/duxml/ruby_ext/regexp.rb +19 -19
- data/lib/duxml/ruby_ext/string.rb +37 -37
- data/lib/duxml/saxer.rb +75 -75
- metadata +12 -12
@@ -1,40 +1,40 @@
|
|
1
|
-
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
-
|
3
|
-
require File.expand_path(File.dirname(__FILE__) + '/../rule')
|
4
|
-
|
5
|
-
module Duxml
|
6
|
-
module TextRule; end
|
7
|
-
|
8
|
-
class TextRuleClass < RuleClass
|
9
|
-
include TextRule
|
10
|
-
end
|
11
|
-
|
12
|
-
module TextRule
|
13
|
-
# @param change_or_pattern [Duxml::Change, Duxml::Pattern] change or pattern that rule may apply to
|
14
|
-
# @return [Boolean] whether this rule does in fact apply
|
15
|
-
def applies_to?(change_or_pattern)
|
16
|
-
super(change_or_pattern) &&
|
17
|
-
change_or_pattern.respond_to?(:text)
|
18
|
-
end
|
19
|
-
|
20
|
-
# applies Regexp statement to text content of this node; returns false if content has XML
|
21
|
-
def qualify(change_or_pattern)
|
22
|
-
@object = change_or_pattern
|
23
|
-
result = pass
|
24
|
-
super change_or_pattern unless result
|
25
|
-
@object = nil
|
26
|
-
result
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
def pass
|
32
|
-
return false unless object.text.is_a?(String)
|
33
|
-
get_scanner.match(object.text).to_s == object.text
|
34
|
-
end
|
35
|
-
|
36
|
-
def get_scanner
|
37
|
-
Regexp.new(statement)
|
38
|
-
end
|
39
|
-
end # module TextRule
|
1
|
+
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
+
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/../rule')
|
4
|
+
|
5
|
+
module Duxml
|
6
|
+
module TextRule; end
|
7
|
+
|
8
|
+
class TextRuleClass < RuleClass
|
9
|
+
include TextRule
|
10
|
+
end
|
11
|
+
|
12
|
+
module TextRule
|
13
|
+
# @param change_or_pattern [Duxml::Change, Duxml::Pattern] change or pattern that rule may apply to
|
14
|
+
# @return [Boolean] whether this rule does in fact apply
|
15
|
+
def applies_to?(change_or_pattern)
|
16
|
+
super(change_or_pattern) &&
|
17
|
+
change_or_pattern.respond_to?(:text)
|
18
|
+
end
|
19
|
+
|
20
|
+
# applies Regexp statement to text content of this node; returns false if content has XML
|
21
|
+
def qualify(change_or_pattern)
|
22
|
+
@object = change_or_pattern
|
23
|
+
result = pass
|
24
|
+
super change_or_pattern unless result
|
25
|
+
@object = nil
|
26
|
+
result
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def pass
|
32
|
+
return false unless object.text.is_a?(String)
|
33
|
+
get_scanner.match(object.text).to_s == object.text
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_scanner
|
37
|
+
Regexp.new(statement)
|
38
|
+
end
|
39
|
+
end # module TextRule
|
40
40
|
end # module Duxml
|
@@ -1,111 +1,111 @@
|
|
1
|
-
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
-
|
3
|
-
require File.expand_path(File.dirname(__FILE__) + '/../rule')
|
4
|
-
|
5
|
-
module Duxml
|
6
|
-
module ValueRule; end
|
7
|
-
|
8
|
-
# rule that states what values a given attribute name is allowed to have
|
9
|
-
class ValueRuleClass < RuleClass
|
10
|
-
include ValueRule
|
11
|
-
|
12
|
-
# @param _attr_name [String] the attribute name
|
13
|
-
# @param _statement [String] data type or expression of the rule for the given attribute's value
|
14
|
-
def initialize(_attr_name, _statement)
|
15
|
-
@attr_name, @statement = _attr_name, _statement
|
16
|
-
end
|
17
|
-
|
18
|
-
attr_reader :attr_name
|
19
|
-
end
|
20
|
-
|
21
|
-
module ValueRule
|
22
|
-
CDATA_EXPR = /(\]\]>)/
|
23
|
-
ENTITY_EXPR = /(\b[\S]+\b)/
|
24
|
-
ID_EXPR = Regexp.nmtoken
|
25
|
-
NMTOKEN_EXPR = ID_EXPR
|
26
|
-
NOTATION_EXPR = //
|
27
|
-
|
28
|
-
# @return [true]
|
29
|
-
def abstract?
|
30
|
-
true
|
31
|
-
end
|
32
|
-
|
33
|
-
# @return [String] description of this rule
|
34
|
-
def description
|
35
|
-
%(#{relationship.capitalize} Rule that @#{attr_name}'s #{relationship} must match '#{statement}')
|
36
|
-
end
|
37
|
-
|
38
|
-
# @param change_or_pattern [Duxml::Pattern, Duxml::Change] change or pattern to be evaluated
|
39
|
-
# @return [Boolean] whether change_or_pattern#subject is allowed to have value of type #object
|
40
|
-
# if false, reports Error to History
|
41
|
-
def qualify(change_or_pattern)
|
42
|
-
value = change_or_pattern.value
|
43
|
-
s = change_or_pattern.subject
|
44
|
-
raise Exception if value.nil?
|
45
|
-
result = pass value
|
46
|
-
super change_or_pattern unless result
|
47
|
-
result
|
48
|
-
end
|
49
|
-
|
50
|
-
# @param change_or_pattern [Duxml::Change, Duxml::Pattern] change or pattern that rule may apply to
|
51
|
-
# @return [Boolean] whether this rule does in fact apply
|
52
|
-
def applies_to?(change_or_pattern)
|
53
|
-
return false unless change_or_pattern.respond_to?(:attr_name)
|
54
|
-
return false unless change_or_pattern.respond_to?(:value)
|
55
|
-
change_or_pattern.attr_name == attr_name
|
56
|
-
end
|
57
|
-
|
58
|
-
private
|
59
|
-
|
60
|
-
def pass(value)
|
61
|
-
matcher = find_method_or_expr
|
62
|
-
if matcher.respond_to?(:match)
|
63
|
-
matcher.match(value).to_s == value
|
64
|
-
else
|
65
|
-
matcher.call(value)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def find_method_or_expr
|
70
|
-
s = statement
|
71
|
-
case s
|
72
|
-
when 'CDATA' # unparsed character data e.g. '<not-xml>'; may not contain string ']]>'
|
73
|
-
proc do |val| val.match(CDATA_EXPR).nil? end
|
74
|
-
when 'ID' then ID_EXPR # does not check for uniqueness!
|
75
|
-
when 'IDREF' # id of another doc
|
76
|
-
proc do |val| val.match(ID_EXPR) && resolve_ref(val, subject.meta) end
|
77
|
-
when 'IDREFS' # ids of other elements
|
78
|
-
proc do |val|
|
79
|
-
separate_list val do |sub_val|
|
80
|
-
sub_val.match(ID_EXPR) && resolve_ref(sub_val, subject.meta)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
when 'NMTOKEN' then NMTOKEN_EXPR # valid XML name
|
84
|
-
when 'NMTOKENS' # a list of valid XML names
|
85
|
-
proc do |val|
|
86
|
-
separate_list val do |sub_val|
|
87
|
-
sub_val.match NMTOKEN_EXPR
|
88
|
-
end
|
89
|
-
end
|
90
|
-
when 'ENTITY' then ENTITY_EXPR # an entity
|
91
|
-
when 'ENTITIES' # list of entities
|
92
|
-
proc do |val|
|
93
|
-
separate_list val do |sub_val|
|
94
|
-
sub_val.match ENTITY_EXPR
|
95
|
-
end
|
96
|
-
end
|
97
|
-
when 'NOTATION' then // # TODO name of a notation
|
98
|
-
when 'xml:' then // # TODO predefined XML value
|
99
|
-
else # '|'-separated list of allowable values i.e. Regexp-style DTD declaration
|
100
|
-
Regexp.new(s)
|
101
|
-
end
|
102
|
-
end # def find_method_or_expr
|
103
|
-
|
104
|
-
def separate_list(spc_sep_vals, &block)
|
105
|
-
spc_sep_vals.split(' ').any? do |sub_val|
|
106
|
-
result = block.call sub_val
|
107
|
-
!result
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end # module ValueRule
|
1
|
+
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
+
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/../rule')
|
4
|
+
|
5
|
+
module Duxml
|
6
|
+
module ValueRule; end
|
7
|
+
|
8
|
+
# rule that states what values a given attribute name is allowed to have
|
9
|
+
class ValueRuleClass < RuleClass
|
10
|
+
include ValueRule
|
11
|
+
|
12
|
+
# @param _attr_name [String] the attribute name
|
13
|
+
# @param _statement [String] data type or expression of the rule for the given attribute's value
|
14
|
+
def initialize(_attr_name, _statement)
|
15
|
+
@attr_name, @statement = _attr_name, _statement
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_reader :attr_name
|
19
|
+
end
|
20
|
+
|
21
|
+
module ValueRule
|
22
|
+
CDATA_EXPR = /(\]\]>)/
|
23
|
+
ENTITY_EXPR = /(\b[\S]+\b)/
|
24
|
+
ID_EXPR = Regexp.nmtoken
|
25
|
+
NMTOKEN_EXPR = ID_EXPR
|
26
|
+
NOTATION_EXPR = //
|
27
|
+
|
28
|
+
# @return [true]
|
29
|
+
def abstract?
|
30
|
+
true
|
31
|
+
end
|
32
|
+
|
33
|
+
# @return [String] description of this rule
|
34
|
+
def description
|
35
|
+
%(#{relationship.capitalize} Rule that @#{attr_name}'s #{relationship} must match '#{statement}')
|
36
|
+
end
|
37
|
+
|
38
|
+
# @param change_or_pattern [Duxml::Pattern, Duxml::Change] change or pattern to be evaluated
|
39
|
+
# @return [Boolean] whether change_or_pattern#subject is allowed to have value of type #object
|
40
|
+
# if false, reports Error to History
|
41
|
+
def qualify(change_or_pattern)
|
42
|
+
value = change_or_pattern.value
|
43
|
+
s = change_or_pattern.subject
|
44
|
+
raise Exception if value.nil?
|
45
|
+
result = pass value
|
46
|
+
super change_or_pattern unless result
|
47
|
+
result
|
48
|
+
end
|
49
|
+
|
50
|
+
# @param change_or_pattern [Duxml::Change, Duxml::Pattern] change or pattern that rule may apply to
|
51
|
+
# @return [Boolean] whether this rule does in fact apply
|
52
|
+
def applies_to?(change_or_pattern)
|
53
|
+
return false unless change_or_pattern.respond_to?(:attr_name)
|
54
|
+
return false unless change_or_pattern.respond_to?(:value)
|
55
|
+
change_or_pattern.attr_name == attr_name
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def pass(value)
|
61
|
+
matcher = find_method_or_expr
|
62
|
+
if matcher.respond_to?(:match)
|
63
|
+
matcher.match(value).to_s == value
|
64
|
+
else
|
65
|
+
matcher.call(value)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def find_method_or_expr
|
70
|
+
s = statement
|
71
|
+
case s
|
72
|
+
when 'CDATA' # unparsed character data e.g. '<not-xml>'; may not contain string ']]>'
|
73
|
+
proc do |val| val.match(CDATA_EXPR).nil? end
|
74
|
+
when 'ID' then ID_EXPR # does not check for uniqueness!
|
75
|
+
when 'IDREF' # id of another doc
|
76
|
+
proc do |val| val.match(ID_EXPR) && resolve_ref(val, subject.meta) end
|
77
|
+
when 'IDREFS' # ids of other elements
|
78
|
+
proc do |val|
|
79
|
+
separate_list val do |sub_val|
|
80
|
+
sub_val.match(ID_EXPR) && resolve_ref(sub_val, subject.meta)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
when 'NMTOKEN' then NMTOKEN_EXPR # valid XML name
|
84
|
+
when 'NMTOKENS' # a list of valid XML names
|
85
|
+
proc do |val|
|
86
|
+
separate_list val do |sub_val|
|
87
|
+
sub_val.match NMTOKEN_EXPR
|
88
|
+
end
|
89
|
+
end
|
90
|
+
when 'ENTITY' then ENTITY_EXPR # an entity
|
91
|
+
when 'ENTITIES' # list of entities
|
92
|
+
proc do |val|
|
93
|
+
separate_list val do |sub_val|
|
94
|
+
sub_val.match ENTITY_EXPR
|
95
|
+
end
|
96
|
+
end
|
97
|
+
when 'NOTATION' then // # TODO name of a notation
|
98
|
+
when 'xml:' then // # TODO predefined XML value
|
99
|
+
else # '|'-separated list of allowable values i.e. Regexp-style DTD declaration
|
100
|
+
Regexp.new(s)
|
101
|
+
end
|
102
|
+
end # def find_method_or_expr
|
103
|
+
|
104
|
+
def separate_list(spc_sep_vals, &block)
|
105
|
+
spc_sep_vals.split(' ').any? do |sub_val|
|
106
|
+
result = block.call sub_val
|
107
|
+
!result
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end # module ValueRule
|
111
111
|
end # module Duxml
|
@@ -1,35 +1,35 @@
|
|
1
|
-
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
-
|
3
|
-
require 'rubyXL'
|
4
|
-
|
5
|
-
module Duxml
|
6
|
-
# contains helper methods to convert spreadsheet of DTD rules into Duxml::Rules
|
7
|
-
module Spreadsheet
|
8
|
-
private
|
9
|
-
# @param path [String] spreadsheet file
|
10
|
-
def self.sheet_to_xml(path)
|
11
|
-
worksheet = RubyXL::Parser.parse(path)[0]
|
12
|
-
attr_val_rule_hash = {}
|
13
|
-
g = GrammarClass.new
|
14
|
-
worksheet.each_with_index do |row, index|
|
15
|
-
next if index == 0
|
16
|
-
break if row[3].nil? || row[4].nil?
|
17
|
-
element_name = row[3].value
|
18
|
-
statement_str = row[4].value
|
19
|
-
g << ChildrenRuleClass.new(element_name, statement_str)
|
20
|
-
attribute_rules = row[5].value.split(/\n/)
|
21
|
-
attribute_rules.each_with_index do |rule, i|
|
22
|
-
next if i == 0 or rule.empty?
|
23
|
-
attr_name, value_expr, attr_req = *rule.split
|
24
|
-
next if [attr_name, value_expr, attr_req].any? do |s| s.empty? or s.match(/\w/).nil? end
|
25
|
-
g << AttrsRuleClass.new(element_name, attr_name, attr_req)
|
26
|
-
unless attr_val_rule_hash[attr_name]
|
27
|
-
g << ValueRuleClass.new(attr_name, value_expr)
|
28
|
-
attr_val_rule_hash[attr_name] = true
|
29
|
-
end
|
30
|
-
end # attribute_rules.each_with_index
|
31
|
-
end # worksheet.each_with_index
|
32
|
-
g
|
33
|
-
end # def sheet_to_xml(path)
|
34
|
-
end # module Spreadsheet
|
1
|
+
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
+
|
3
|
+
require 'rubyXL'
|
4
|
+
|
5
|
+
module Duxml
|
6
|
+
# contains helper methods to convert spreadsheet of DTD rules into Duxml::Rules
|
7
|
+
module Spreadsheet
|
8
|
+
private
|
9
|
+
# @param path [String] spreadsheet file
|
10
|
+
def self.sheet_to_xml(path)
|
11
|
+
worksheet = RubyXL::Parser.parse(path)[0]
|
12
|
+
attr_val_rule_hash = {}
|
13
|
+
g = GrammarClass.new
|
14
|
+
worksheet.each_with_index do |row, index|
|
15
|
+
next if index == 0
|
16
|
+
break if row[3].nil? || row[4].nil?
|
17
|
+
element_name = row[3].value
|
18
|
+
statement_str = row[4].value
|
19
|
+
g << ChildrenRuleClass.new(element_name, statement_str)
|
20
|
+
attribute_rules = row[5].value.split(/\n/)
|
21
|
+
attribute_rules.each_with_index do |rule, i|
|
22
|
+
next if i == 0 or rule.empty?
|
23
|
+
attr_name, value_expr, attr_req = *rule.split
|
24
|
+
next if [attr_name, value_expr, attr_req].any? do |s| s.empty? or s.match(/\w/).nil? end
|
25
|
+
g << AttrsRuleClass.new(element_name, attr_name, attr_req)
|
26
|
+
unless attr_val_rule_hash[attr_name]
|
27
|
+
g << ValueRuleClass.new(attr_name, value_expr)
|
28
|
+
attr_val_rule_hash[attr_name] = true
|
29
|
+
end
|
30
|
+
end # attribute_rules.each_with_index
|
31
|
+
end # worksheet.each_with_index
|
32
|
+
g
|
33
|
+
end # def sheet_to_xml(path)
|
34
|
+
end # module Spreadsheet
|
35
35
|
end # module Duxml
|
data/lib/duxml/meta/history.rb
CHANGED
@@ -1,89 +1,89 @@
|
|
1
|
-
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
-
|
3
|
-
require File.expand_path(File.dirname(__FILE__) + '/history/add')
|
4
|
-
require File.expand_path(File.dirname(__FILE__) + '/history/remove')
|
5
|
-
require File.expand_path(File.dirname(__FILE__) + '/history/validate_error')
|
6
|
-
require File.expand_path(File.dirname(__FILE__) + '/history/qualify_error')
|
7
|
-
require File.expand_path(File.dirname(__FILE__) + '/history/new_attr')
|
8
|
-
require File.expand_path(File.dirname(__FILE__) + '/history/change_attr')
|
9
|
-
require File.expand_path(File.dirname(__FILE__) + '/history/new_text')
|
10
|
-
require File.expand_path(File.dirname(__FILE__) + '/history/change_text')
|
11
|
-
require File.expand_path(File.dirname(__FILE__) + '/history/undo')
|
12
|
-
require File.expand_path(File.dirname(__FILE__) + '/../doc')
|
13
|
-
require 'forwardable'
|
14
|
-
|
15
|
-
module Duxml
|
16
|
-
# monitors XML Elements for changes and GrammarClass for errors, recording them and saving to Meta file
|
17
|
-
module History
|
18
|
-
include Duxml
|
19
|
-
include Reportable
|
20
|
-
end
|
21
|
-
|
22
|
-
# as an object, HistoryClass holds events latest first, earliest last
|
23
|
-
# it also has delegators that allow the use of Array-style notation e.g. '[]' and #each to search the history.
|
24
|
-
class HistoryClass
|
25
|
-
include History
|
26
|
-
extend Forwardable
|
27
|
-
|
28
|
-
def_delegators :@nodes, :[], :each
|
29
|
-
|
30
|
-
# @param strict_or_false [Boolean] by default strict i.e. true so that if this History detects an error it will raise an Exception; otherwise not
|
31
|
-
def initialize(strict_or_false = true)
|
32
|
-
@nodes = []
|
33
|
-
@strict = strict_or_false
|
34
|
-
end
|
35
|
-
|
36
|
-
attr_reader :nodes
|
37
|
-
alias_method :events, :nodes
|
38
|
-
end
|
39
|
-
|
40
|
-
module History
|
41
|
-
# used when creating a new metadata file for a static XML file
|
42
|
-
#
|
43
|
-
# @return [Doc] returns self as XML document
|
44
|
-
def xml
|
45
|
-
h = Element.new('history')
|
46
|
-
events.each do |event| h << event.xml end
|
47
|
-
h
|
48
|
-
end
|
49
|
-
|
50
|
-
# @return [Boolean] toggles (true by default) whether History will raise exception or tolerate qualify errors
|
51
|
-
def strict?(strict_or_false=nil)
|
52
|
-
@strict = strict_or_false.nil? ? @strict : strict_or_false
|
53
|
-
end
|
54
|
-
|
55
|
-
# @return [ChangeClass, ErrorClass] the latest event
|
56
|
-
def latest
|
57
|
-
events[0]
|
58
|
-
end
|
59
|
-
|
60
|
-
# @return [GrammarClass] grammar that is observing this history's events
|
61
|
-
def grammar
|
62
|
-
@observer_peers.first.first if @observer_peers and @observer_peers.any? and @observer_peers.first.any?
|
63
|
-
end
|
64
|
-
|
65
|
-
# @return [String] shortened self description for debugging
|
66
|
-
def inspect
|
67
|
-
"#<#{self.class.to_s} #{object_id}: @events=#{nodes.size}>"
|
68
|
-
end
|
69
|
-
|
70
|
-
# @return [String] returns entire history, calling #description on each event in chronological order
|
71
|
-
def description
|
72
|
-
"history follows: \n" +
|
73
|
-
events.reverse.collect do |change_or_error|
|
74
|
-
change_or_error.description
|
75
|
-
end.join("\n")
|
76
|
-
end
|
77
|
-
|
78
|
-
# @param type [Symbol] category i.e. class symbol of changes/errors reported
|
79
|
-
# @param *args [*several_variants] information needed to accurately log the event; varies by change/error class
|
80
|
-
def update(type, *args)
|
81
|
-
change_class = Duxml::const_get "#{type.to_s}Class".to_sym
|
82
|
-
change_comp = change_class.new *args
|
83
|
-
@nodes.unshift change_comp
|
84
|
-
changed
|
85
|
-
notify_observers(change_comp) unless change_comp.respond_to?(:error?)
|
86
|
-
raise(Exception, change_comp.description) if strict? && type == :QualifyError
|
87
|
-
end
|
88
|
-
end # module History
|
1
|
+
# Copyright (c) 2016 Freescale Semiconductor Inc.
|
2
|
+
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + '/history/add')
|
4
|
+
require File.expand_path(File.dirname(__FILE__) + '/history/remove')
|
5
|
+
require File.expand_path(File.dirname(__FILE__) + '/history/validate_error')
|
6
|
+
require File.expand_path(File.dirname(__FILE__) + '/history/qualify_error')
|
7
|
+
require File.expand_path(File.dirname(__FILE__) + '/history/new_attr')
|
8
|
+
require File.expand_path(File.dirname(__FILE__) + '/history/change_attr')
|
9
|
+
require File.expand_path(File.dirname(__FILE__) + '/history/new_text')
|
10
|
+
require File.expand_path(File.dirname(__FILE__) + '/history/change_text')
|
11
|
+
require File.expand_path(File.dirname(__FILE__) + '/history/undo')
|
12
|
+
require File.expand_path(File.dirname(__FILE__) + '/../doc')
|
13
|
+
require 'forwardable'
|
14
|
+
|
15
|
+
module Duxml
|
16
|
+
# monitors XML Elements for changes and GrammarClass for errors, recording them and saving to Meta file
|
17
|
+
module History
|
18
|
+
include Duxml
|
19
|
+
include Reportable
|
20
|
+
end
|
21
|
+
|
22
|
+
# as an object, HistoryClass holds events latest first, earliest last
|
23
|
+
# it also has delegators that allow the use of Array-style notation e.g. '[]' and #each to search the history.
|
24
|
+
class HistoryClass
|
25
|
+
include History
|
26
|
+
extend Forwardable
|
27
|
+
|
28
|
+
def_delegators :@nodes, :[], :each
|
29
|
+
|
30
|
+
# @param strict_or_false [Boolean] by default strict i.e. true so that if this History detects an error it will raise an Exception; otherwise not
|
31
|
+
def initialize(strict_or_false = true)
|
32
|
+
@nodes = []
|
33
|
+
@strict = strict_or_false
|
34
|
+
end
|
35
|
+
|
36
|
+
attr_reader :nodes
|
37
|
+
alias_method :events, :nodes
|
38
|
+
end
|
39
|
+
|
40
|
+
module History
|
41
|
+
# used when creating a new metadata file for a static XML file
|
42
|
+
#
|
43
|
+
# @return [Doc] returns self as XML document
|
44
|
+
def xml
|
45
|
+
h = Element.new('history')
|
46
|
+
events.each do |event| h << event.xml end
|
47
|
+
h
|
48
|
+
end
|
49
|
+
|
50
|
+
# @return [Boolean] toggles (true by default) whether History will raise exception or tolerate qualify errors
|
51
|
+
def strict?(strict_or_false=nil)
|
52
|
+
@strict = strict_or_false.nil? ? @strict : strict_or_false
|
53
|
+
end
|
54
|
+
|
55
|
+
# @return [ChangeClass, ErrorClass] the latest event
|
56
|
+
def latest
|
57
|
+
events[0]
|
58
|
+
end
|
59
|
+
|
60
|
+
# @return [GrammarClass] grammar that is observing this history's events
|
61
|
+
def grammar
|
62
|
+
@observer_peers.first.first if @observer_peers and @observer_peers.any? and @observer_peers.first.any?
|
63
|
+
end
|
64
|
+
|
65
|
+
# @return [String] shortened self description for debugging
|
66
|
+
def inspect
|
67
|
+
"#<#{self.class.to_s} #{object_id}: @events=#{nodes.size}>"
|
68
|
+
end
|
69
|
+
|
70
|
+
# @return [String] returns entire history, calling #description on each event in chronological order
|
71
|
+
def description
|
72
|
+
"history follows: \n" +
|
73
|
+
events.reverse.collect do |change_or_error|
|
74
|
+
change_or_error.description
|
75
|
+
end.join("\n")
|
76
|
+
end
|
77
|
+
|
78
|
+
# @param type [Symbol] category i.e. class symbol of changes/errors reported
|
79
|
+
# @param *args [*several_variants] information needed to accurately log the event; varies by change/error class
|
80
|
+
def update(type, *args)
|
81
|
+
change_class = Duxml::const_get "#{type.to_s}Class".to_sym
|
82
|
+
change_comp = change_class.new *args
|
83
|
+
@nodes.unshift change_comp
|
84
|
+
changed
|
85
|
+
notify_observers(change_comp) unless change_comp.respond_to?(:error?)
|
86
|
+
raise(Exception, change_comp.description) if strict? && type == :QualifyError
|
87
|
+
end
|
88
|
+
end # module History
|
89
89
|
end # module Duxml
|