Module: MasterView::DirectiveMetadata

Included in:
DirectiveBaseOld
Defined in:
lib/masterview/directive_metadata.rb

Overview

Mixin for directives to provide metadata specifications

All directives have a standard set of metadata properties:

:attribute_name - the (unqualified) directive attribute name
:namespace - the namespace name for the qualified directive name
:attribute_qname - the fully-qualified directive name (ns:attribute)
:priority - the DirectivePriority for processing

Additional properties can be set to provide documentation and usage information (:summary, :description) or to record custom settings.

– TBD: How can we automatically extract directive rdoc from its class?? ++

Defined Under Namespace

Modules: ClassMethods, DirectivePriorities

Constant Summary collapse

DEBUG_MD_INSTALLATION =

:nodoc:

false
DEBUG_MD_PROPS =

:nodoc:

false
MARKUP_PROPERTY_NAMES =

well-known metadata properties

[ :namespace, :namespace_prefix, :attribute_name, :attribute_qname ]
PROCESSING_PROPERTY_NAMES =

:nodoc:

[ :priority ]
DOC_PROPERTY_NAMES =

:nodoc:

[ :summary, :description ]
STANDARD_PROPERTY_NAMES =

:nodoc:

MARKUP_PROPERTY_NAMES + PROCESSING_PROPERTY_NAMES + DOC_PROPERTY_NAMES
HARDENED_PROPERTY_NAMES =

:nodoc:

MARKUP_PROPERTY_NAMES + PROCESSING_PROPERTY_NAMES
DirectiveMetadataRegistry =

implementation hack for DirectiveMetadata class var putting class var @@metadata_values got muddled by subclassing, punt to this scheme

{}
PriorityNames =

:nodoc:

[]
PrioritiesMap =

:nodoc:

{}

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.get_priority_label(priority) ⇒ Object

:nodoc:



65
66
67
68
69
70
# File 'lib/masterview/directive_metadata.rb', line 65

def self.get_priority_label(priority) #:nodoc:
  name = get_priority_name(priority)
  # 'default (Med)' was  nicer, but admin page doesn't format width properly
  name = 'default' if priority == DirectivePriorities::Default
  name
end

.get_priority_name(priority) ⇒ Object

Answer the name of a priority level



61
62
63
# File 'lib/masterview/directive_metadata.rb', line 61

def self.get_priority_name(priority) #:nodoc:
  PrioritiesMap.fetch( priority, priority.to_s )  #?? "%08x" % priority
end

.included(base) ⇒ Object

add class methods for DSL declarations to class which is mixing in DirectiveMetadata



343
344
345
346
# File 'lib/masterview/directive_metadata.rb', line 343

def self.included(base)  #:nodoc:
  STDOUT.puts "\n####Mixing #{self} into #{base} (id=#{base.object_id})" if DEBUG_MD_INSTALLATION
  base.extend(ClassMethods)
end

.validate_metadata_props!(md_props) ⇒ Object

Ensure that a set of metadata values are valid and consistent. This is a banger because it takes liberties normalizing the properties.



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/masterview/directive_metadata.rb', line 86

def self.(md_props)

  md_prop_name = :attribute_name
  if md_props.has_key?( md_prop_name )
    attr_name = md_props[md_prop_name]
    raise ArgumentError, "Invalid #{md_prop_name.inspect} '#{attr_name}'" if ! DirectiveMetadata.validate_xml_identifier(attr_name)
  end

  # allow :namespace_name as a synonym for :namespace
  md_prop_name = :namespace_name
  if md_props.has_key?( md_prop_name )
    ns_name = md_props[md_prop_name]
    if md_props.has_key?(:namespace)
      # we actually ought to just unconditionally complain, it's silly and redundant to do both of these
      other_ns_name = md_props[:namespace]
      raise ArgumentError, "Inconsistent namespace settigs (:namespace='#{other_ns_name}', :namespace_name='#{ns_name}')" if other_ns_name != ns_name
    else
      md_props[:namespace] = ns_name
    end
    # always get rid of :namespace_name, we just want to record :namespace
    md_props.delete(md_prop_name)
  end

  md_prop_name = :namespace
  if md_props.has_key?( md_prop_name )
    ns_name = md_props[md_prop_name]
    raise ArgumentError, "Invalid #{md_prop_name.inspect} '#{ns_name}'" if ns_name[-1..-1] == ':'
    raise ArgumentError, "Invalid #{md_prop_name.inspect} '#{ns_name}'" if ! DirectiveMetadata.validate_xml_identifier(ns_name)
    # ensure both namespace props we use are present and consistent
    ns_prefix = "#{ns_name}:"
    if md_props.has_key?( :namespace_prefix )
      ns_prefix_prop = md_props[:namespace_prefix]
      raise ArgumentError, "Inconsistent namespace settings (:namespace='#{ns_name}', :namespace_prefix='#{ns_prefix_prop}')" if ns_prefix_prop != ns_prefix
    else
      md_props[:namespace_prefix] = ns_prefix
    end
  end
  
  md_prop_name = :namespace_prefix
  if md_props.has_key?( md_prop_name )
    ns_prefix = md_props[md_prop_name]
    raise ArgumentError, "Invalid #{md_prop_name.inspect} '#{ns_prefix}'" if ns_prefix[-1..-1] != ':'
    ns_name = ns_prefix[0...-1]
    raise ArgumentError, "Invalid #{md_prop_name.inspect} '#{ns_prefix}'" if ! DirectiveMetadata.validate_xml_identifier(ns_name)        
    # ensure namespace settings are both present and consistent
    if md_props.has_key?( :namespace )
      ns_name_prop = md_props[:namespace]
      raise ArgumentError, "Inconsistent namespace settings (:namespace='#{ns_name_prop}', :namespace_prefix='#{ns_prefix}')" if ns_name_prop != ns_name
    else
      md_props[:namespace] = ns_name
    end
  end

  md_prop_name = :priority
  if md_props.has_key?( md_prop_name )
    priority = md_props[md_prop_name]
    if priority.is_a?( String ) || priority.is_a?( Symbol )
      begin
        priority = 'Default' if [ 'default', :default ].include?(priority)  #synonyms
        priority = DirectiveMetadata::DirectivePriorities.const_get(priority)
        md_props[md_prop_name] = priority
      rescue NameError
        #invalid priority name - fall through to error code below
      end
    end
    priority_range = (DirectiveMetadata::DirectivePriorities::Highest..DirectiveMetadata::DirectivePriorities::Lowest)
    raise ArgumentError, "Invalid #{md_prop_name.inspect}: #{md_props[md_prop_name].inspect}" if ! (priority_range.include? priority)
  end

  if DEBUG_MD_PROPS
    err_msg = "BAD DIRECTIVE MD PROPS: #{md_props.inspect}"
    raise RuntimeError, err_msg if md_props.has_key?(:namespace_name)  # temp check on internal impl rework cutover
    raise RuntimeError, err_msg if (md_props.has_key?(:namespace) && ! md_props.has_key?(:namespace_prefix))
    raise RuntimeError, err_msg if (md_props.has_key?(:namespace_prefix) && ! md_props.has_key?(:namespace))
    #??raise RuntimeError, err_msg if md_props.has_key?(:attribute_qname)???
  end

end

.validate_xml_identifier(name) ⇒ Object

Answer whether a name is a legal XML markup identifier. Used to validate attribute and namespace names for directives.



75
76
77
78
79
80
81
82
# File 'lib/masterview/directive_metadata.rb', line 75

def self.validate_xml_identifier(name)
  #todo: add re defn to verify syntactically legal xml id
  # XML 1.0 spec: A Name is a token beginning with a letter or one of a few
  # punctuation characters, and continuing with letters, digits, hyphens, 
  # underscores, colons, or full stops, together known as name characters.
  #TODO: name =~ /^[a-zA-Z](\w|-|_)*$/
  true
end

Instance Method Details

#attribute_nameObject

Answer the (unqualified) attribute name used in template document markup for this directive.



350
351
352
# File 'lib/masterview/directive_metadata.rb', line 350

def attribute_name
  self.class.attribute_name
end

#attribute_qnameObject

Answer the fully-qualified attribute name of the directive



367
368
369
# File 'lib/masterview/directive_metadata.rb', line 367

def attribute_qname
  self.class.attribute_qname
end

#namespaceObject



354
355
356
# File 'lib/masterview/directive_metadata.rb', line 354

def namespace
  self.class.namespace
end

#namespace_nameObject



358
359
360
# File 'lib/masterview/directive_metadata.rb', line 358

def namespace_name
  self.class.namespace_name
end

#namespace_prefixObject



362
363
364
# File 'lib/masterview/directive_metadata.rb', line 362

def namespace_prefix
  self.class.namespace_prefix
end

#priorityObject



371
372
373
# File 'lib/masterview/directive_metadata.rb', line 371

def priority
  return self.class.priority
end