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.
- 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
data/lib/duxml/meta/grammar.rb
CHANGED
@@ -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
|