Class: DataMetaDom::Model

Inherits:
Object
  • Object
show all
Includes:
DataMetaDom
Defined in:
lib/dataMetaDom/model.rb

Overview

Metadata Model, including parsing.

For command line details either check the new method’s source or the README.rdoc file, the usage section.

Constant Summary

Constants included from DataMetaDom

BITSET, BOOL, BOOL_CONV, CANNED_RX, CHAR, CONVS, DATAMETA_LIB, DATETIME, DIMMED_TYPES, DOC, DOC_TARGETS, DTTM_CONV, DTTM_TYPE, END_KW, ENUM, FLOAT, FLOAT4, FLOAT8, FRACT_CONV, FULL_COMPARE, IDENTITY, ID_ONLY_COMPARE, ID_START, INCLUDE, INDENT, INDEX, INT, INT1, INT2, INT4, INT8, INTEGRAL_CONV, JAVA_DOC_TARGET, L, MAPPING, MATCHES, MODEL_LEVEL_TOKENS, NAMESPACE, NO_NAMESPACE, NUMERIC, OPTIONAL_PFX, OPT_DIMMABLE, PACK_SEPARATOR, PLAIN_DOC_TARGET, RAW, RECORD, RECORD_LEVEL_TOKENS, REC_ATTR_KEYWORDS, REQUIRED_PFX, SAME_FULL_SFX, SAME_ID_SFX, SCALE_TYPES, SOURCE_INDENT, STANDARD_TYPES, STRING, TEXT_CONV, TYPE_START, UNIQUE, URL, URL_TYPE, VERSION, VER_KW, WIKI, WIKI_REF_HTML

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from DataMetaDom

combineNsBase, condenseType, fullTypeName, getParenDimInfo, getterName, help, helpAndVerFirstArg, helpMySqlDdl, #helpOracleDdl, helpPojoGen, helpScalaGen, #migrClass, nsAdjustment, #qualName, setterName, splitNameSpace, uniPath, validNs?

Constructor Details

#initializeModel

Creates a blank model.



54
55
56
57
58
# 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

Instance Attribute Details

#currentSourceObject (readonly)

The instance of SourceFile currently being parsed.



22
23
24
# File 'lib/dataMetaDom/model.rb', line 22

def currentSource
  @currentSource
end

#enumsObject (readonly)

Instances of Enum, Map and BitSet on this model, keyed by the full name including the namespace if any.



31
32
33
# File 'lib/dataMetaDom/model.rb', line 31

def enums
  @enums
end

#optionsObject

Documentation for all options is in this section.

  • autoVerNs - if set to True, advises a generator to append a vN where N is a version number to the namespace.



47
48
49
# File 'lib/dataMetaDom/model.rb', line 47

def options
  @options
end

#recordsObject (readonly)

Instances of Record on this model, keyed by the full name including the namespace if any.



36
37
38
# File 'lib/dataMetaDom/model.rb', line 36

def records
  @records
end

#reRefsObject (readonly)

Reverse references keyed by reference target names



41
42
43
# File 'lib/dataMetaDom/model.rb', line 41

def reRefs
  @reRefs
end

#sourcesObject (readonly)

All sources, including the includes.



27
28
29
# File 'lib/dataMetaDom/model.rb', line 27

def sources
  @sources
end

#verObject

Version on the model level



49
50
51
# File 'lib/dataMetaDom/model.rb', line 49

def ver
  @ver
end

Instance Method Details

#addEnum(newEnum) ⇒ Object

Adds the given enum to the model

  • Parameter

    • rec - instance of a Enum or a BitSet or a Map



117
# File 'lib/dataMetaDom/model.rb', line 117

def addEnum(newEnum); @enums[newEnum.name] = newEnum end

#addEnums(enums) ⇒ Object

Adds the given enums to the model

  • Parameter

    • rec - an array of instances of a Enum or a BitSet or a Map



124
# File 'lib/dataMetaDom/model.rb', line 124

def addEnums(enums); enums.each { |e| addEnum e } end

#addRecord(rec) ⇒ Object

Adds the given record to the model

  • Parameter

    • rec - instance of a Record



103
# File 'lib/dataMetaDom/model.rb', line 103

def addRecord(rec); @records[rec.key] = rec end

#addRecords(recs) ⇒ Object

Adds the given records to the model

  • Parameter

    • recs - an array of instances of a Record



110
# File 'lib/dataMetaDom/model.rb', line 110

def addRecords(recs); recs.each { |r| addRecord r } end

#diagnObject

Builds diagnostics string, including the source info.



85
# File 'lib/dataMetaDom/model.rb', line 85

def diagn; "; Src: #{@currentSource ? @currentSource : '<no source>'}" end

#genDocs(docs) ⇒ Object

Renders the source for the docs property of Documentable.



168
169
170
171
172
173
174
175
# 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

#genSource {|'# model definition exported into the source code by DataMeta DOM'| ... } ⇒ Object

Generates the source lines for the given model, yields the lines to the caller’s block, use as:

genSource{|line| ... }

Yields:

  • ('# model definition exported into the source code by DataMeta DOM')


249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# 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

#genSourceEnum(e, baseName) {|''| ... } ⇒ Object

Generates DataMeta DOM source for the given Enum, yielding the lines to the caller’s block.

  • Parameters

    • e - instance of a Enum or a BitSet or a Map to generate the DataMeta DOM source for

    • baseName - the base name excluding the namespace if any, usually available on the caller’s side.

Yields:

  • ('')


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/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

#genSourceRec(r, namespace, baseName) {|''| ... } ⇒ Object

Generates DataMeta DOM source for the given Record, yielding the lines to the caller’s block.

  • Parameters

    • r - instance of a Record 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.

Yields:

  • ('')


195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# 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

#genVer(e) {|"#{VER_KW} #{v.full}"| ... } ⇒ Object

Renders the source for the docs property of Ver.

Yields:



180
181
182
183
184
185
# 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

#parse(fileName, options = {autoVerNs: false}) ⇒ Object

master parse, initializes process queue and seeds it with the master file



88
89
90
91
92
93
94
95
96
# 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

#resolveVerifyObject

Resolves references after parsing all the sources to the types that were used before than they were defined. Verifies integrity.

Raises:

  • (RuntimeError)


64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# 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