masterview 0.2.5 → 0.3.0
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.
- data/CHANGELOG +31 -1
- data/README +70 -69
- data/RELEASE_NOTES +70 -64
- data/Rakefile +26 -27
- data/TODO +13 -29
- data/doc/about.html +246 -0
- data/doc/configuration.html +49 -36
- data/doc/developer.html +423 -41
- data/doc/directives.html +139 -51
- data/doc/guide.html +19 -9
- data/doc/index.html +90 -224
- data/doc/installation.html +36 -28
- data/doc/media_list.html +30 -20
- data/doc/simple_diagram.html +3 -5
- data/doc/stylesheets/masterview.css +16 -1
- data/examples/rails_app_config/masterview/settings.rb +2 -1
- data/init.rb +1 -1
- data/lib/#ChangeLog# +6 -0
- data/lib/masterview/analyzer.rb +48 -34
- data/lib/masterview/attr_string_parser.rb +5 -1
- data/lib/masterview/case_insensitive_hash.rb +69 -0
- data/lib/masterview/{pathname_extensions.rb → core_ext/pathname.rb} +0 -0
- data/lib/masterview/{string_extensions.rb → core_ext/string.rb} +0 -0
- data/lib/masterview/deprecated/directive_base.rb +362 -0
- data/lib/masterview/directive_base.rb +201 -179
- data/lib/masterview/directive_dsl.rb +457 -0
- data/lib/masterview/directive_helpers.rb +28 -141
- data/lib/masterview/directive_load_path.rb +388 -0
- data/lib/masterview/directive_metadata.rb +377 -0
- data/lib/masterview/directive_registry.rb +259 -69
- data/lib/masterview/directives/.metadata +16 -0
- data/lib/masterview/directives/attr.rb +9 -8
- data/lib/masterview/directives/block.rb +11 -14
- data/lib/masterview/directives/check_box.rb +13 -18
- data/lib/masterview/directives/collection_select.rb +15 -29
- data/lib/masterview/directives/content.rb +9 -3
- data/lib/masterview/directives/else.rb +15 -13
- data/lib/masterview/directives/elsif.rb +14 -13
- data/lib/masterview/directives/eval.rb +20 -0
- data/lib/masterview/directives/form.rb +56 -9
- data/lib/masterview/directives/form_remote.rb +26 -0
- data/lib/masterview/directives/global_inline_erb.rb +10 -14
- data/lib/masterview/directives/hidden_field.rb +11 -20
- data/lib/masterview/directives/if.rb +13 -12
- data/lib/masterview/directives/image_tag.rb +20 -28
- data/lib/masterview/directives/import.rb +5 -12
- data/lib/masterview/directives/import_render.rb +7 -19
- data/lib/masterview/directives/insert_generated_comment.rb +8 -11
- data/lib/masterview/directives/javascript_include.rb +21 -12
- data/lib/masterview/directives/link_to.rb +14 -8
- data/lib/masterview/directives/link_to_function.rb +22 -0
- data/lib/masterview/directives/link_to_if.rb +15 -13
- data/lib/masterview/directives/link_to_remote.rb +13 -8
- data/lib/masterview/directives/omit_tag.rb +32 -16
- data/lib/masterview/directives/password_field.rb +10 -22
- data/lib/masterview/directives/radio_button.rb +11 -22
- data/lib/masterview/directives/replace.rb +7 -8
- data/lib/masterview/directives/select.rb +11 -24
- data/lib/masterview/directives/stylesheet_link.rb +20 -12
- data/lib/masterview/directives/submit.rb +11 -5
- data/lib/masterview/directives/text_area.rb +10 -23
- data/lib/masterview/directives/text_field.rb +10 -22
- data/lib/masterview/exceptions.rb +21 -0
- data/lib/masterview/extras/app/controllers/masterview_controller.rb +102 -75
- data/lib/masterview/extras/app/views/layouts/masterview_admin.rhtml +24 -23
- data/lib/masterview/extras/app/views/layouts/masterview_admin_config.rhtml +81 -0
- data/lib/masterview/extras/app/views/masterview/admin/configuration.rhtml +5 -1
- data/lib/masterview/extras/app/views/masterview/admin/create.rhtml +2 -2
- data/lib/masterview/extras/app/views/masterview/admin/directives.rhtml +5 -0
- data/lib/masterview/extras/app/views/masterview/admin/features.rhtml +5 -79
- data/lib/masterview/extras/app/views/masterview/admin/interact.rhtml +5 -0
- data/lib/masterview/extras/app/views/masterview/admin/list.rhtml +3 -71
- data/lib/masterview/extras/init_mv_admin_pages.rb +42 -23
- data/lib/masterview/filter_helpers.rb +26 -0
- data/lib/masterview/initializer.rb +99 -53
- data/lib/masterview/io.rb +19 -15
- data/lib/masterview/keyword_expander.rb +7 -2
- data/lib/masterview/masterview_info.rb +229 -23
- data/lib/masterview/masterview_version.rb +2 -2
- data/lib/masterview/parser.rb +275 -105
- data/lib/masterview/parser_helpers.rb +54 -0
- data/lib/masterview/rails_ext/action_controller_erb_direct.rb +29 -0
- data/lib/masterview/rails_ext/action_controller_reparse_checking.rb +27 -0
- data/lib/masterview/{extras/init_rails_erb_mv_direct.rb → rails_ext/action_view_erb_direct.rb} +12 -59
- data/lib/masterview/template_spec.rb +3 -2
- data/lib/masterview.rb +21 -12
- data/lib/rexml/parsers/baseparser_with_doctype_fix.rb +473 -0
- data/lib/rexml/parsers/sax2parser_with_doctype_fix.rb +243 -0
- data/test/directive_test_helper.rb +135 -0
- data/test/fixtures/directives/id_check.rb +18 -0
- data/test/fixtures/directives/test_directive_events.rb +70 -0
- data/test/test_helper.rb +18 -5
- data/test/tmp/views/layouts/product.rhtml +10 -10
- data/test/tmp/views/product/_form.rhtml +4 -4
- data/test/tmp/views/product/_product.rhtml +3 -3
- data/test/tmp/views/product/destroy.rhtml +5 -5
- data/test/tmp/views/product/edit.rhtml +4 -4
- data/test/tmp/views/product/list.rhtml +3 -3
- data/test/tmp/views/product/new.rhtml +4 -4
- data/test/tmp/views/product/show.rhtml +2 -2
- data/test/unit/attr_string_parser_test.rb +105 -0
- data/test/unit/case_insensitive_hash_mod_test.rb +104 -0
- data/test/unit/config_settings_test.rb +13 -1
- data/test/unit/default_generate_mio_filter_test.rb +3 -3
- data/test/unit/deprecated_directive_base_test.rb +30 -0
- data/test/unit/directive_attr_test.rb +111 -35
- data/test/unit/directive_base_test.rb +520 -1
- data/test/unit/directive_block_test.rb +30 -22
- data/test/unit/directive_content_test.rb +24 -11
- data/test/unit/directive_else_test.rb +18 -15
- data/test/unit/directive_elsif_test.rb +17 -15
- data/test/unit/directive_form_remote_test.rb +59 -0
- data/test/unit/directive_form_test.rb +31 -39
- data/test/unit/directive_global_inline_erb_test.rb +28 -17
- data/test/unit/directive_grid_test_notready.rb +38 -0
- data/test/unit/directive_helpers_test.rb +39 -0
- data/test/unit/directive_hidden_field_test.rb +44 -29
- data/test/unit/directive_if_test.rb +10 -7
- data/test/unit/directive_image_tag_test.rb +69 -61
- data/test/unit/directive_import_render_test.rb +28 -38
- data/test/unit/directive_import_test.rb +16 -14
- data/test/unit/directive_insert_generated_comment_test.rb +32 -0
- data/test/unit/directive_javascript_include_test.rb +40 -43
- data/test/unit/directive_link_to_function_test.rb +40 -0
- data/test/unit/directive_link_to_if_test.rb +52 -12
- data/test/unit/directive_link_to_remote_test.rb +58 -0
- data/test/unit/directive_link_to_test.rb +46 -31
- data/test/unit/directive_load_path_test.rb +257 -0
- data/test/unit/directive_metadata_test.rb +313 -0
- data/test/unit/directive_omit_tag_test.rb +73 -21
- data/test/unit/directive_password_field_test.rb +44 -38
- data/test/unit/directive_registry_test.rb +44 -0
- data/test/unit/directive_replace_test.rb +28 -12
- data/test/unit/directive_stylesheet_link_test.rb +43 -36
- data/test/unit/directive_submit_test.rb +29 -30
- data/test/unit/directive_text_area_test.rb +40 -36
- data/test/unit/directive_text_field_test.rb +44 -38
- data/test/unit/example_directive_child_events_test.rb +41 -0
- data/test/unit/example_test.rb +31 -4
- data/test/unit/file_mio_test.rb +18 -13
- data/test/unit/filter_helpers_test.rb +10 -8
- data/test/unit/find_directive_parent_test.rb +174 -0
- data/test/unit/keyword_expander_test.rb +4 -2
- data/test/unit/mio_test.rb +18 -11
- data/test/unit/mtime_string_hash_mio_tree_test.rb +5 -1
- data/test/unit/parser_test.rb +41 -29
- data/test/unit/pathname_extensions_test.rb +1 -1
- data/test/unit/run_parser_test.rb +2 -2
- data/test/unit/simplified_directive_base_test.rb +256 -0
- data/test/unit/string_hash_mio_test.rb +5 -1
- data/test/unit/template_file_watcher_test.rb +2 -2
- data/test/unit/template_test.rb +221 -46
- metadata +86 -45
- data/lib/masterview/directives/testfilter.rb +0 -55
- data/lib/masterview/extras/init_rails_reparse_checking.rb +0 -62
@@ -0,0 +1,377 @@
|
|
1
|
+
module MasterView
|
2
|
+
|
3
|
+
# Mixin for directives to provide metadata specifications
|
4
|
+
#
|
5
|
+
# All directives have a standard set of metadata properties:
|
6
|
+
# :attribute_name - the (unqualified) directive attribute name
|
7
|
+
# :namespace - the namespace name for the qualified directive name
|
8
|
+
# :attribute_qname - the fully-qualified directive name (ns:attribute)
|
9
|
+
# :priority - the DirectivePriority for processing
|
10
|
+
#
|
11
|
+
# Additional properties can be set to provide documentation and usage
|
12
|
+
# information (:summary, :description) or to record custom settings.
|
13
|
+
#
|
14
|
+
#--
|
15
|
+
#TBD: How can we automatically extract directive rdoc from its class??
|
16
|
+
#++
|
17
|
+
#
|
18
|
+
module DirectiveMetadata
|
19
|
+
|
20
|
+
DEBUG_MD_INSTALLATION = false #:nodoc:
|
21
|
+
DEBUG_MD_PROPS = false #:nodoc:
|
22
|
+
|
23
|
+
# well-known metadata properties
|
24
|
+
MARKUP_PROPERTY_NAMES = [ :namespace, :namespace_prefix, :attribute_name, :attribute_qname ] #:nodoc:
|
25
|
+
PROCESSING_PROPERTY_NAMES = [ :priority ] #:nodoc:
|
26
|
+
DOC_PROPERTY_NAMES = [ :summary, :description ] #:nodoc:
|
27
|
+
STANDARD_PROPERTY_NAMES = MARKUP_PROPERTY_NAMES + PROCESSING_PROPERTY_NAMES + DOC_PROPERTY_NAMES #:nodoc:
|
28
|
+
HARDENED_PROPERTY_NAMES = MARKUP_PROPERTY_NAMES + PROCESSING_PROPERTY_NAMES #:nodoc:
|
29
|
+
|
30
|
+
# implementation hack for DirectiveMetadata class var
|
31
|
+
# putting class var @@metadata_values got muddled by subclassing, punt to this scheme
|
32
|
+
DirectiveMetadataRegistry = {} #:nodoc:
|
33
|
+
|
34
|
+
#convenience constants defined to allow priority to directives
|
35
|
+
#higher priority (lower value) will be executed first in chain
|
36
|
+
module DirectivePriorities
|
37
|
+
Highest = 0
|
38
|
+
UltraHigh = 0x3FFFFFFF/16
|
39
|
+
VeryHigh = 0x3FFFFFFF/8
|
40
|
+
High = 0x3FFFFFFF/4
|
41
|
+
MediumHigh = 0x3FFFFFFF/3
|
42
|
+
Medium = 0x3FFFFFFF/2
|
43
|
+
MediumLow = (0x3FFFFFFF/3)*2
|
44
|
+
Low = (0x3FFFFFFF/4)*3
|
45
|
+
VeryLow = (0x3FFFFFFF/8)*7
|
46
|
+
UltraLow = (0x3FFFFFFF/16)*15
|
47
|
+
Lowest = 0x3FFFFFFF
|
48
|
+
# convenience
|
49
|
+
Default = Medium
|
50
|
+
end
|
51
|
+
|
52
|
+
PriorityNames = [] #:nodoc:
|
53
|
+
PrioritiesMap = {} #:nodoc:
|
54
|
+
DirectivePriorities.constants.each { | const_name |
|
55
|
+
level_name = const_name.to_s #???
|
56
|
+
next if level_name == 'Default' # only record real names
|
57
|
+
PriorityNames << level_name
|
58
|
+
PrioritiesMap[DirectivePriorities.const_get(const_name)] = level_name
|
59
|
+
}
|
60
|
+
# Answer the name of a priority level
|
61
|
+
def self.get_priority_name(priority) #:nodoc:
|
62
|
+
PrioritiesMap.fetch( priority, priority.to_s ) #?? "%08x" % priority
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.get_priority_label(priority) #:nodoc:
|
66
|
+
name = get_priority_name(priority)
|
67
|
+
# 'default (Med)' was nicer, but admin page doesn't format width properly
|
68
|
+
name = 'default' if priority == DirectivePriorities::Default
|
69
|
+
name
|
70
|
+
end
|
71
|
+
|
72
|
+
# Answer whether a name is a legal XML markup identifier.
|
73
|
+
# Used to validate attribute and namespace names for directives.
|
74
|
+
#
|
75
|
+
def self.validate_xml_identifier(name)
|
76
|
+
#todo: add re defn to verify syntactically legal xml id
|
77
|
+
# XML 1.0 spec: A Name is a token beginning with a letter or one of a few
|
78
|
+
# punctuation characters, and continuing with letters, digits, hyphens,
|
79
|
+
# underscores, colons, or full stops, together known as name characters.
|
80
|
+
#TODO: name =~ /^[a-zA-Z](\w|-|_)*$/
|
81
|
+
true
|
82
|
+
end
|
83
|
+
|
84
|
+
# Ensure that a set of metadata values are valid and consistent.
|
85
|
+
# This is a banger because it takes liberties normalizing the properties.
|
86
|
+
def self.validate_metadata_props!(md_props)
|
87
|
+
|
88
|
+
md_prop_name = :attribute_name
|
89
|
+
if md_props.has_key?( md_prop_name )
|
90
|
+
attr_name = md_props[md_prop_name]
|
91
|
+
raise ArgumentError, "Invalid #{md_prop_name.inspect} '#{attr_name}'" if ! DirectiveMetadata.validate_xml_identifier(attr_name)
|
92
|
+
end
|
93
|
+
|
94
|
+
# allow :namespace_name as a synonym for :namespace
|
95
|
+
md_prop_name = :namespace_name
|
96
|
+
if md_props.has_key?( md_prop_name )
|
97
|
+
ns_name = md_props[md_prop_name]
|
98
|
+
if md_props.has_key?(:namespace)
|
99
|
+
# we actually ought to just unconditionally complain, it's silly and redundant to do both of these
|
100
|
+
other_ns_name = md_props[:namespace]
|
101
|
+
raise ArgumentError, "Inconsistent namespace settigs (:namespace='#{other_ns_name}', :namespace_name='#{ns_name}')" if other_ns_name != ns_name
|
102
|
+
else
|
103
|
+
md_props[:namespace] = ns_name
|
104
|
+
end
|
105
|
+
# always get rid of :namespace_name, we just want to record :namespace
|
106
|
+
md_props.delete(md_prop_name)
|
107
|
+
end
|
108
|
+
|
109
|
+
md_prop_name = :namespace
|
110
|
+
if md_props.has_key?( md_prop_name )
|
111
|
+
ns_name = md_props[md_prop_name]
|
112
|
+
raise ArgumentError, "Invalid #{md_prop_name.inspect} '#{ns_name}'" if ns_name[-1..-1] == ':'
|
113
|
+
raise ArgumentError, "Invalid #{md_prop_name.inspect} '#{ns_name}'" if ! DirectiveMetadata.validate_xml_identifier(ns_name)
|
114
|
+
# ensure both namespace props we use are present and consistent
|
115
|
+
ns_prefix = "#{ns_name}:"
|
116
|
+
if md_props.has_key?( :namespace_prefix )
|
117
|
+
ns_prefix_prop = md_props[:namespace_prefix]
|
118
|
+
raise ArgumentError, "Inconsistent namespace settings (:namespace='#{ns_name}', :namespace_prefix='#{ns_prefix_prop}')" if ns_prefix_prop != ns_prefix
|
119
|
+
else
|
120
|
+
md_props[:namespace_prefix] = ns_prefix
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
md_prop_name = :namespace_prefix
|
125
|
+
if md_props.has_key?( md_prop_name )
|
126
|
+
ns_prefix = md_props[md_prop_name]
|
127
|
+
raise ArgumentError, "Invalid #{md_prop_name.inspect} '#{ns_prefix}'" if ns_prefix[-1..-1] != ':'
|
128
|
+
ns_name = ns_prefix[0...-1]
|
129
|
+
raise ArgumentError, "Invalid #{md_prop_name.inspect} '#{ns_prefix}'" if ! DirectiveMetadata.validate_xml_identifier(ns_name)
|
130
|
+
# ensure namespace settings are both present and consistent
|
131
|
+
if md_props.has_key?( :namespace )
|
132
|
+
ns_name_prop = md_props[:namespace]
|
133
|
+
raise ArgumentError, "Inconsistent namespace settings (:namespace='#{ns_name_prop}', :namespace_prefix='#{ns_prefix}')" if ns_name_prop != ns_name
|
134
|
+
else
|
135
|
+
md_props[:namespace] = ns_name
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
md_prop_name = :priority
|
140
|
+
if md_props.has_key?( md_prop_name )
|
141
|
+
priority = md_props[md_prop_name]
|
142
|
+
if priority.is_a?( String ) || priority.is_a?( Symbol )
|
143
|
+
begin
|
144
|
+
priority = 'Default' if [ 'default', :default ].include?(priority) #synonyms
|
145
|
+
priority = DirectiveMetadata::DirectivePriorities.const_get(priority)
|
146
|
+
md_props[md_prop_name] = priority
|
147
|
+
rescue NameError
|
148
|
+
#invalid priority name - fall through to error code below
|
149
|
+
end
|
150
|
+
end
|
151
|
+
priority_range = (DirectiveMetadata::DirectivePriorities::Highest..DirectiveMetadata::DirectivePriorities::Lowest)
|
152
|
+
raise ArgumentError, "Invalid #{md_prop_name.inspect}: #{md_props[md_prop_name].inspect}" if ! (priority_range.include? priority)
|
153
|
+
end
|
154
|
+
|
155
|
+
if DEBUG_MD_PROPS
|
156
|
+
err_msg = "BAD DIRECTIVE MD PROPS: #{md_props.inspect}"
|
157
|
+
raise RuntimeError, err_msg if md_props.has_key?(:namespace_name) # temp check on internal impl rework cutover
|
158
|
+
raise RuntimeError, err_msg if (md_props.has_key?(:namespace) && ! md_props.has_key?(:namespace_prefix))
|
159
|
+
raise RuntimeError, err_msg if (md_props.has_key?(:namespace_prefix) && ! md_props.has_key?(:namespace))
|
160
|
+
#??raise RuntimeError, err_msg if md_props.has_key?(:attribute_qname)???
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
164
|
+
|
165
|
+
module ClassMethods
|
166
|
+
|
167
|
+
# the metadata values for the directive class
|
168
|
+
def metadata_values #:nodoc:
|
169
|
+
return DirectiveMetadataRegistry[self.name] || {}
|
170
|
+
end
|
171
|
+
def self.extended(base) #:nodoc:
|
172
|
+
STDOUT.puts "...adding #{self} into #{base} (id=#{base.object_id})" if DEBUG_MD_INSTALLATION
|
173
|
+
#base.class_eval '@@metadata_values = {}'
|
174
|
+
#md_accessor_code = <<-END
|
175
|
+
# def #{base}.metadata_values
|
176
|
+
# @@metadata_values ||= {}
|
177
|
+
# end
|
178
|
+
#END
|
179
|
+
#base.class_eval md_accessor_code
|
180
|
+
DirectiveMetadataRegistry[base.name] = {}
|
181
|
+
STDOUT.puts "...#{base}.@@metadata_values=#{base.metadata_values.object_id}" if DEBUG_MD_INSTALLATION
|
182
|
+
end
|
183
|
+
def self.inherited(directive_class) #:nodoc:
|
184
|
+
STDOUT.puts "\n###inherited #{self} in #{directive_class} (id=#{directive_class.object_id})" if DEBUG_MD_INSTALLATION
|
185
|
+
#directive_class.class_eval '@@metadata_values = {}'
|
186
|
+
#md_accessor_code = <<-END
|
187
|
+
# def #{directive_class}.metadata_values
|
188
|
+
# @@metadata_values ||= {}
|
189
|
+
# end
|
190
|
+
#END
|
191
|
+
#directive_class.class_eval md_accessor_code
|
192
|
+
DirectiveMetadataRegistry[directive_class.name] = {}
|
193
|
+
STDOUT.puts "...#{directive_class}.@@metadata_values=#{directive_class.metadata_values.object_id}" if DEBUG_MD_INSTALLATION
|
194
|
+
end
|
195
|
+
|
196
|
+
# Answer the (unqualified) attribute name of the directive
|
197
|
+
def attribute_name
|
198
|
+
metadata_values[:attribute_name] || default_directive_name
|
199
|
+
end
|
200
|
+
|
201
|
+
def namespace
|
202
|
+
metadata_values[:namespace] || default_namespace_prefix[0...-1]
|
203
|
+
end
|
204
|
+
|
205
|
+
##ISSUE: deprecate this??
|
206
|
+
def namespace_name
|
207
|
+
namespace
|
208
|
+
end
|
209
|
+
|
210
|
+
def namespace_prefix
|
211
|
+
metadata_values[:namespace_prefix] || default_namespace_prefix
|
212
|
+
end
|
213
|
+
|
214
|
+
# Answer the fully-qualified attribute name of the directive
|
215
|
+
def attribute_qname
|
216
|
+
metadata_values[:attribute_qname] || "#{namespace}:#{attribute_name}"
|
217
|
+
end
|
218
|
+
|
219
|
+
def priority
|
220
|
+
metadata_values[:priority] || DirectivePriorities::Default
|
221
|
+
end
|
222
|
+
|
223
|
+
# Answer the default directive attribute name for a directive class.
|
224
|
+
#
|
225
|
+
# If not explicitly specified, lowercased name of the class is
|
226
|
+
# assumed to be the attribute name used in template markup.
|
227
|
+
#
|
228
|
+
def default_directive_name #:nodoc:
|
229
|
+
simple_name = self.name.split(':').last # strip off module qualifiers
|
230
|
+
simple_name = simple_name.downcase_first_letter
|
231
|
+
# convert camel-case class name FooBar to snake-case foo_bar
|
232
|
+
simple_name.gsub( /[A-Z]/ ) { |letter| "_#{letter.downcase}" }
|
233
|
+
end
|
234
|
+
|
235
|
+
# Answer the default namespace prefix for a directive class.
|
236
|
+
#
|
237
|
+
def default_namespace_prefix #:nodoc:
|
238
|
+
# this is a bit squirrelly to rely on module namespace convention
|
239
|
+
# masterview brings in String#starts_with? from facets, thank you
|
240
|
+
if self.name.starts_with?('MasterView::Directives::')
|
241
|
+
MasterView::ConfigSettings.namespace_prefix
|
242
|
+
else
|
243
|
+
MasterView::ConfigSettings.namespace_prefix_extensions
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
# Declare metadata properties of the directive
|
248
|
+
# Specify one more prop_name => value entries
|
249
|
+
# :attibute_name, :namespace, :summary, :description
|
250
|
+
def metadata(md_props)
|
251
|
+
md_props = md_props.clone
|
252
|
+
DirectiveMetadata.validate_metadata_props!(md_props)
|
253
|
+
if ! DirectiveMetadataRegistry.has_key?( self.name )
|
254
|
+
DirectiveMetadataRegistry[self.name] = {}
|
255
|
+
STDOUT.puts "...#{self}.@@metadata_values=#{self.metadata_values.object_id} <metadata decl>" if DEBUG_MD_INSTALLATION
|
256
|
+
else
|
257
|
+
# ISSUE: not clear why we need to do this, but something's getting initialized
|
258
|
+
# by initial class load/include/extend magic that I can't figure out.
|
259
|
+
# This probably is safe, there should be exactly one metadata decl in
|
260
|
+
# a directive implementation and it should probably always have a clean
|
261
|
+
# point of view.
|
262
|
+
# [DJL 06-Oct-2006]
|
263
|
+
DirectiveMetadataRegistry[self.name].clear()
|
264
|
+
end
|
265
|
+
metadata_values.merge! md_props
|
266
|
+
end
|
267
|
+
|
268
|
+
# Fill in any defaults and ensure that all required metadata properties are defined.
|
269
|
+
#
|
270
|
+
# Ordinarily done exactly once by the directive loading mechanisms.
|
271
|
+
#
|
272
|
+
def harden_metadata(defaults={})
|
273
|
+
trace_enabled = DEBUG_MD_PROPS || DEBUG_MD_INSTALLATION
|
274
|
+
if ! DirectiveMetadataRegistry.has_key?( self.name )
|
275
|
+
DirectiveMetadataRegistry[self.name] = {}
|
276
|
+
STDOUT.puts "...#{self}.@@metadata_values=#{self.metadata_values.inspect} (id=#{self.metadata_values.object_id}) <harden_metadata>" if trace_enabled
|
277
|
+
STDOUT.puts "...DirectiveMetadataRegistry=#{DirectiveMetadataRegistry.inspect}" if trace_enabled
|
278
|
+
end
|
279
|
+
dc_md = metadata_values
|
280
|
+
STDOUT.puts "\n****HARDENING: #{self}.metadata_values=#{dc_md.inspect} (id=#{dc_md.object_id})" if trace_enabled
|
281
|
+
# install any defaults for properties which aren't explicitly set
|
282
|
+
md_to_add = defaults.reject { |key, value| dc_md.has_key?( key ) }
|
283
|
+
#assert ! md_to_add.equal?(defaults), 'safe to mess with our own copy now'
|
284
|
+
DirectiveMetadata.validate_metadata_props!( md_to_add ) # this should check and normalize any namespace-related entries
|
285
|
+
raise RuntimeError, "BAD: attr naming inappropriate in md defaults #{md_to_add.inspect}" if md_to_add.has_key?(:attribute_name) || md_to_add.has_key?(:attribute_qname)
|
286
|
+
# ensure that required properties are set
|
287
|
+
if ! dc_md.has_key?( :attribute_name )
|
288
|
+
md_to_add[:attribute_name] = default_directive_name
|
289
|
+
end
|
290
|
+
if ! dc_md.has_key?( :priority )
|
291
|
+
md_to_add[:priority] = DirectivePriorities::Default
|
292
|
+
end
|
293
|
+
if ! dc_md.has_key?( :namespace )
|
294
|
+
raise RuntimeError, "BUG: inconsistent #{self.name}.metadata_values ns entries: #{dc_md.inspect}" if dc_md.has_key?(:namespace_prefix) || dc_md.has_key?(:attribute_qname)
|
295
|
+
if md_to_add.has_key?( :namespace )
|
296
|
+
#ok, we'll fill in namespace from defaults
|
297
|
+
# quadruple-check programming errors in this mess until this stuff stabilizes [DJL 06-Oct-2006]
|
298
|
+
raise RuntimeError, 'BUG: validate_metadata_props! did not handle defaults normalization: #{md_to_add.inspect}' if ! md_to_add.has_key?(:namespace_prefix)
|
299
|
+
elsif md_to_add.has_key?( :namespace_prefix )
|
300
|
+
# quadruple-check programming errors in this mess until this stuff stabilizes [DJL 06-Oct-2006]
|
301
|
+
raise RuntimeError, 'BUG: validate_metadata_props! did not handle defaults normalization: #{md_to_add.inspect}'
|
302
|
+
else
|
303
|
+
default_prefix = default_namespace_prefix
|
304
|
+
md_to_add[:namespace] = default_prefix[0...-1]
|
305
|
+
md_to_add[:namespace_prefix] = default_prefix
|
306
|
+
end
|
307
|
+
end
|
308
|
+
if ! dc_md.has_key?( :namespace_prefix )
|
309
|
+
# we should have just taken care of this
|
310
|
+
raise RuntimeError, "BUG: inconsistent #{self.name}.metadata_values ns entries: #{dc_md.inspect}" if dc_md.has_key?(:namespace) || dc_md.has_key?(:attribute_qname)
|
311
|
+
raise RuntimeError, "BUG: incorrect construction of #{self.name} md_to_add: #{md_to_add}" if ! (md_to_add.has_key?(:namespace) && md_to_add.has_key?(:namespace_prefix))
|
312
|
+
end
|
313
|
+
dc_md.merge! md_to_add
|
314
|
+
#assert dc_md.has_key?( :namespace) && dc_md.has_key?( :namespace_prefix)
|
315
|
+
if true # ! dc_md.has_key?( :attribute_qname )
|
316
|
+
# just always do this, there's something funky about load/include/extend
|
317
|
+
# somehow we're getting backstop defaults in ahead of even the first class load
|
318
|
+
# I do not understand something subtle, so giving up and just hammering here [DJL 06-Oct-2006]
|
319
|
+
dc_md[:attribute_qname] = "#{dc_md[:namespace]}:#{dc_md[:attribute_name]}"
|
320
|
+
end
|
321
|
+
#???dc_md[:hardened] = true???
|
322
|
+
#??dc_md.freeze
|
323
|
+
if DEBUG_MD_PROPS
|
324
|
+
# quadruple-check programming errors in this mess until this stuff stabilizes [DJL 06-Oct-2006]
|
325
|
+
oops = false
|
326
|
+
HARDENED_PROPERTY_NAMES.each { |md_prop_name| oops = true if ! metadata_values.has_key?(md_prop_name) }
|
327
|
+
if oops
|
328
|
+
raise RuntimeError, "BAD MD HARDENING IN #{self.name}: #{metadata_values.inspect}"
|
329
|
+
end
|
330
|
+
if metadata_values[:namespace_prefix] != "#{metadata_values[:namespace]}:"
|
331
|
+
raise RuntimeError, "BAD MD HARDENING IN #{self.name}: #{metadata_values.inspect}"
|
332
|
+
end
|
333
|
+
if metadata_values[:attribute_qname] != "#{metadata_values[:namespace]}:#{metadata_values[:attribute_name]}"
|
334
|
+
raise RuntimeError, "BAD MD HARDENING IN #{self.name}: #{metadata_values.inspect}"
|
335
|
+
end
|
336
|
+
end
|
337
|
+
STDOUT.puts "...HARDENED MD: #{self.metadata_values.inspect}\n" if DEBUG_MD_PROPS
|
338
|
+
end
|
339
|
+
|
340
|
+
end #ClassMethods
|
341
|
+
|
342
|
+
# add class methods for DSL declarations to class which is mixing in DirectiveMetadata
|
343
|
+
def self.included(base) #:nodoc:
|
344
|
+
STDOUT.puts "\n####Mixing #{self} into #{base} (id=#{base.object_id})" if DEBUG_MD_INSTALLATION
|
345
|
+
base.extend(ClassMethods)
|
346
|
+
end
|
347
|
+
|
348
|
+
# Answer the (unqualified) attribute name used in template document markup
|
349
|
+
# for this directive.
|
350
|
+
def attribute_name
|
351
|
+
self.class.attribute_name
|
352
|
+
end
|
353
|
+
|
354
|
+
def namespace
|
355
|
+
self.class.namespace
|
356
|
+
end
|
357
|
+
|
358
|
+
def namespace_name
|
359
|
+
self.class.namespace_name
|
360
|
+
end
|
361
|
+
|
362
|
+
def namespace_prefix
|
363
|
+
self.class.namespace_prefix
|
364
|
+
end
|
365
|
+
|
366
|
+
# Answer the fully-qualified attribute name of the directive
|
367
|
+
def attribute_qname
|
368
|
+
self.class.attribute_qname
|
369
|
+
end
|
370
|
+
|
371
|
+
def priority
|
372
|
+
return self.class.priority
|
373
|
+
end
|
374
|
+
|
375
|
+
end
|
376
|
+
|
377
|
+
end
|