class DataMetaDom::Model
Metadata Model
, including parsing.
For command line details either check the new method's source or the README.rdoc file, the usage section.
Attributes
The instance of SourceFile
currently being parsed.
Documentation for all options is in this section.
-
autoVerNs
- if set to True, advises a generator to append avN
whereN
is a version number to the namespace.
Reverse references keyed by reference target names
Instances of Record
on this model, keyed by the full name including the namespace if any.
All sources, including the includes.
Version on the model level
Public Class Methods
Creates a blank model.
# File lib/dataMetaDom/model.rb, line 54 def initialize() # no file name if want to build model manually @reRefs = Hash.new(*[]) # references to the entity, hash keyed by entity @enums={}; @records = {} @ver = nil end
Public Instance Methods
Adds the given record to the model
-
Parameter
-
rec
- instance of aRecord
-
# File lib/dataMetaDom/model.rb, line 103 def addRecord(rec); @records[rec.key] = rec end
Adds the given records to the model
-
Parameter
-
recs
- an array of instances of aRecord
-
# File lib/dataMetaDom/model.rb, line 110 def addRecords(recs); recs.each { |r| addRecord r } end
Builds diagnostics string, including the source info.
# File lib/dataMetaDom/model.rb, line 85 def diagn; "; Src: #{@currentSource ? @currentSource : '<no source>'}" end
Renders the source for the docs property of Documentable
.
# File lib/dataMetaDom/model.rb, line 168 def genDocs(docs) docs.each_key{ |t| yield "#{DOC} #{t}" d = docs[t] yield d.text yield END_KW } end
Generates the source lines for the given model, yields the lines to the caller's block, use as:
genSource{|line| ... }
# File lib/dataMetaDom/model.rb, line 249 def genSource yield '# model definition exported into the source code by DataMeta DOM' namespace = '' (@enums.keys + @records.keys).sort { |a, b| a.to_s <=> b.to_s }.each { |k| ns, base = DataMetaDom.splitNameSpace(k.to_s) if DataMetaDom.validNs?(ns, base) && ns != namespace namespace = ns yield "#{NAMESPACE} #{namespace}" end raise 'No version on the model' unless @ver raise "Version on the model is wrong type: #{@ver.inspect}" unless @ver.kind_of?(Ver) yield "#{VER_KW} #{@ver.full}" case when @records[k] genSourceRec(@records[k], namespace, base) { |line| yield line } when @enums[k] genSourceEnum(@enums[k], base) { |line| yield line } else raise "Unsupported entity: #{e.inspect}" end } end
Generates DataMeta DOM source for the given Enum
, yielding the lines to the caller's block.
-
Parameters
# File lib/dataMetaDom/model.rb, line 133 def genSourceEnum(e, baseName) yield '' # yield empty line before a type case when e.kind_of?(Enum) if e.docs genDocs(e.docs){|line| yield line} end yield "#{e.sourceKeyWord} #{baseName}" #genVer(e) { |line| yield line } e.values.each { |v| yield "#{SOURCE_INDENT}#{v}" } when e.kind_of?(BitSet), e.kind_of?(Mappings) if e.docs genDocs(e.docs){|line| yield line} end yield "#{e.sourceKeyWord} #{baseName} #{e.kind_of?(BitSet) ? '' : e.fromT.to_s + ' '}#{e.toT}" #genVer(e) { |line| yield line } e.keys.each { |k| fromConv = CONVS[e.fromT.type] toConv = CONVS[e.toT.type] #DataMetaDom::L.debug "k=#{k.inspect}, e=#{e[k].inspect}" raise "Invalid convertor for #{e}: (#{fromConv.inspect} => #{toConv.inspect})" unless fromConv && toConv yield "#{SOURCE_INDENT}#{fromConv.ser.call(k)} => #{toConv.ser.call(e[k])}," } else raise "Enum #{e} - unsupported format" end yield END_KW end
Generates DataMeta DOM source for the given Record
, yielding the lines to the caller's block.
-
Parameters
-
r
- instance of aRecord
to generate the DataMeta DOM source for -
namespace
- the namespace of the record, usually available on the caller's side. -
baseName
- the base name excluding the namespace if any, usually available on the caller's side.
-
# File lib/dataMetaDom/model.rb, line 195 def genSourceRec(r, namespace, baseName) yield '' # yield empty line before a type if r.docs genDocs(r.docs){|line| yield line} end yield "#{RECORD} #{baseName}" #genVer(r) { |line| yield line } r.fields.values.each { |f| if f.docs genDocs(f.docs) { |line| yield line} end t = f.dataType #puts ">>F: #{f}, ns=#{ns}, base=#{base}, bn=#{baseName}" # render names from other namespaces than the current in full renderType = qualName(namespace, t.type) srcLine = if f.map? trgRender = qualName(namespace, f.trgType.type) "#{SOURCE_INDENT}#{f.req_spec}#{Field::MAP}{#{renderType}#{t.length_spec}, #{trgRender}#{ f.trgType.length_spec}} #{f.name}#{f.default_spec}" elsif f.aggr? "#{SOURCE_INDENT}#{f.req_spec}#{f.aggr}{#{renderType}#{t.length_spec}} #{f.name}#{f.default_spec}" else "#{SOURCE_INDENT}#{f.req_spec}#{renderType}#{t.length_spec} #{f.name}#{f.default_spec}#{f.matches_spec}" end yield srcLine } yield "#{SOURCE_INDENT}#{IDENTITY}#{r.identity.hints.empty? ? '' : "(#{r.identity.hints.to_a.join(', ')})"} "\ "#{r.identity.args.join(', ')}" if r.identity if r.uniques r.uniques.each_value { |uq| yield "#{SOURCE_INDENT}#{UNIQUE}#{uq.hints.empty? ? '' : "(#{uq.hints.to_a.join(', ')})"} #{uq.args.join(', ')}" } end if r.indexes r.indexes.each_value { |ix| yield "#{SOURCE_INDENT}#{INDEX}#{ix.hints.empty? ? '' : "(#{ix.hints.to_a.join(', ')})"} #{ix.args.join(', ')}" } end if r.refs r.refs.each { |ref| yield "# #{ref}" } end yield END_KW end
Renders the source for the docs property of Ver
.
# File lib/dataMetaDom/model.rb, line 180 def genVer(e) raise "No version on #{e}" unless e.ver v = e.ver raise "Version on #{e} is wrong type: #{v.inspect}" unless v.kind_of?(Ver) yield "#{VER_KW} #{v.full}" end
master parse, initializes process queue and seeds it with the master file
# File lib/dataMetaDom/model.rb, line 88 def parse(fileName, options={autoVerNs: false}) @options = options @sources = Sources.new(fileName) while (@currentSource=@sources.next) @currentSource.parse self end resolveVerify self end
Resolves references after parsing all the sources to the types that were used before than they were defined. Verifies integrity.
# File lib/dataMetaDom/model.rb, line 64 def resolveVerify duplicateGuard = {} @records.each_key { |recKey| rec = @records[recKey] rec.refs.each { |ref| ref.resolve self preExisting = duplicateGuard[ref.key] raise "Duplicate reference spec: #{r}(#{r.sourceRef}), pre-existing: #{preExisting}(#{preExisting.sourceRef})" if preExisting duplicateGuard[ref.key] = ref reKey = ref.toEntity.name @reRefs[reKey] = [] unless @reRefs[reKey] @reRefs[reKey] << ref } } raise RuntimeError, "No version defined on #{self}" unless ver self end