dataMetaDom 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a5a34ddc40e94ae5a9075a76cd8896a3b3781b76
4
+ data.tar.gz: 80d035936a0991579930f19b6bf4f8262f81c7fe
5
+ SHA512:
6
+ metadata.gz: 529782409a1e9957fba291b94318f96c7bea71f11415340039900be2a7d22d7e80761d4bfef5b5166e1b987d6dde4c5b9ea17e5e1579a9fc8194126b4508e53b
7
+ data.tar.gz: 571cb5dddc02d545731ef0ada7ea573ee033682816a13dc3122dd117229c7ba2b44a357a0e918a8c30c7661b3e71afbdcf487c904d086964c60130e33daef5c2
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --title "DataMeta DOM" -r README.md --charset UTF-8 lib/**/* - README.md
data/History.md ADDED
@@ -0,0 +1,6 @@
1
+
2
+ # `dataMetaDom` Release history:
3
+
4
+ ## `1.0.0` - `2017-01-15`
5
+ * 1 major enhancement:
6
+ * Initial release
data/PostInstall.txt ADDED
@@ -0,0 +1 @@
1
+ No special steps
data/README.md ADDED
@@ -0,0 +1,137 @@
1
+ # dataMetaDom
2
+
3
+ The Core of the DataMeta platform, see the Features section below.
4
+
5
+ ## Description
6
+
7
+ See the [DataMeta home page](https://github.com/eBayDataMeta) and
8
+
9
+ References to this gem's:
10
+
11
+ * [Source](https://github.com/eBayDataMeta/DataMeta-gems)
12
+
13
+ ## Features
14
+
15
+ The following components are included into this gem:
16
+
17
+ * DataMetaDOM DDL parser - parses the DataMetaDOM [DDL](http://en.wikipedia.org/wiki/Data_definition_language) into
18
+ the model in memory.
19
+ * export the DataMetaDOM DDL to [POJO](http://en.wikipedia.org/wiki/Plain_Old_Java_Object) including implementors
20
+ of the `DataMetaSame` Java interface, to provide equality either by the class `identity` or by all of the
21
+ fields.
22
+ * export the DataMetaDOM DDL to MySQL DDL
23
+
24
+ ## Problems
25
+
26
+ None known.
27
+
28
+ ## Synopsis
29
+
30
+ Beside the API, there are the following runnables in this gem:
31
+
32
+ ### DataMetaDOM POJO generator.
33
+
34
+ Use this runnable to parse a DataMetaDOM source and generate Java objects
35
+ ([POJOs](http://en.wikipedia.org/wiki/Plain_Old_Java_Object)) matching the DataMeta model.
36
+
37
+ Usage:
38
+
39
+ dataMetaDomPojo.rb <DataMetaDOM source> <target directory>
40
+
41
+ Example:
42
+
43
+ dataMetaDomPojo.rb /gitrepos/projects/data/schema/showCase.dmDom ./pojos
44
+
45
+ ### DataMetaDOM MySQL DDL generator
46
+
47
+ Use this runnable to parse a DataMetaDOM DDL source and generate matching
48
+ [MySQL DDL](http://dev.mysql.com/doc/refman/5.5/en/sql-syntax-data-definition.html) statements, including
49
+ creates, drops, creating referential integrity links and dropping those.
50
+
51
+ Usage:
52
+
53
+ dataMetaDomMySqlDdl.rb <DataMetaDOM source> <target directory>
54
+
55
+ Example:
56
+
57
+ dataMetaDomMySqlDdl.rb /gitrepos/projects/data/schema/showCase.dmDom ./sql
58
+
59
+ ### DataMetaDOM Full compare DataMetaSame generator for POJOs
60
+
61
+ Use this to generate implementors of the DataMetaSame interface from DataMetaDOM sources performing full compare.
62
+
63
+ Usage:
64
+
65
+ dataMetaDomSameFullJ.rb <DataMetaDOM source> <target directory>
66
+
67
+ ### DataMetaDOM compare by identity DataMetaSame generator for POJOs
68
+
69
+ Use this to generate implementors of the DataMetaSame interface from DataMetaDOM sources performing compare only
70
+ by the `identity` for the class, see DataMetaDom::Record for details.
71
+
72
+ Usage:
73
+
74
+ dataMetaDomSameIdJ.rb <DataMetaDOM source> <target directory>
75
+
76
+ ### Exporting DataMetaDOM source into graphical file showing entity relationships
77
+
78
+ This script generates [GraphViz](http://www.graphviz.org) source for the given DataMetaDOM module
79
+ and attempts to display the resulting jpeg file in the current OS.
80
+
81
+ Usage:
82
+
83
+ dataMetaDomGvExport.rb <DataMetaDOM source> <target base path>
84
+
85
+ The script will append the suffix `.gv` to the `target base path` for the GraphViz source and the suffix `.jpeg`
86
+ to the name of the genrated image file.
87
+
88
+ Example:
89
+
90
+ dataMetaDomGvExport.rb src/main/schema/Model.dmDom target/Model
91
+
92
+ this will generate `target/Model.gv` and `target/Model.jpeg`
93
+
94
+ This requires [GraphViz](http://www.graphviz.org) installation with the `dot` command in the path
95
+ and some kind of a graphic environment. On Windows, [Irfanview](http://www.irfanview.com) is very useful, otherwise
96
+ the script will use default Windows viewers that oftentimes are much slower.
97
+
98
+ ### Reversion all files in path
99
+
100
+ Usage:
101
+
102
+ dataMetaReVersion.rb <Path> <NS> <CSV-globs> <Ver-From> <Ver-To>
103
+
104
+ Where:
105
+
106
+ * Path - starting path to look for the files to re-version
107
+ * NS - Namespace, such as Java/Scala package
108
+ * CVS-globs - comma-separated file patterns, in regular filesystem globbing format
109
+ * Ver-From - Source version or an asterisk for any version. Example: `11.2.1`
110
+ * Ver-To - Target version. Example: `11.2.2`
111
+
112
+ Examples of arguments to this command:
113
+
114
+ * `src/main/com/acme com.acme.svc.obj.dom '*.java,*.scala' '*' 1.2.3` -- starting from the `src/main/com/acme`
115
+ directory, replace on all Scala and Java files, any DataMeta version with `1.2.3`
116
+ * `. com.acme.svc.obj.dom '*.conf,*.scala' 1.2.1 1.2.3` -- starting from the current directory,
117
+ replace on all Scala and config files, DataMeta version `1.2.1` with `1.2.3`.
118
+
119
+ Note the single quotes for the file glob patterns and the "star" specification of the source version: this is to
120
+ prevent the shell to glob before passing the result to the program.
121
+
122
+ Note that there is no relation between the path and the namespace; only Java still enforces such relation therefore
123
+ we do not want to be dependent on it.
124
+
125
+
126
+ ## Requirements
127
+
128
+ * No special requirements
129
+
130
+ ## Install
131
+
132
+ gem install dataMetaDom
133
+
134
+ ## License
135
+
136
+ [Apache v 2.0](https://github.com/eBayDataMeta/DataMeta/blob/master/LICENSE.md)
137
+
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ %w(yard rdoc/task rake/testtask ./lib/dataMetaDom ./lib/dataMetaDom/dataType).each{ |r| require r}
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'test'
5
+ end
6
+
7
+ desc 'Regen RDocs'
8
+ task :default => :docs
9
+
10
+ YARD::Rake::YardocTask.new('docs') {|r|
11
+ r.stats_options = ['--list-undoc']
12
+ }
13
+
@@ -0,0 +1,97 @@
1
+ #!/bin/env ruby
2
+ %w( dataMetaDom dataMetaXtra ).each(&method(:require))
3
+ include DataMetaDom
4
+
5
+ ENTITY_FILL_COLOR='#CCEEFF'
6
+ ENUM_FILL_COLOR='#CCFFCC'
7
+ ENUM_LINE_COLOR='#00CC00'
8
+ ENTITY_LINE_COLOR='#000066'
9
+
10
+ def genGv(parser, outFileName)
11
+ out = File.open(outFileName, 'wb')
12
+ out.puts <<GV_HEADER
13
+ digraph Model {
14
+ ranksep=1.6;
15
+ node [shape=box, fontcolor="black" style="rounded,filled" fontname="Consolas" fillcolor="#AAFFCC" pad=1.5 decorate=true fontsize=15 ];
16
+ edge [arrowhead=vee] ;
17
+ GV_HEADER
18
+ parser.records.each_value.each { |rec|
19
+ ns, base = DataMetaDom::splitNameSpace(rec.name)
20
+ out.puts %{ #{base} [fillcolor = "#{ENTITY_FILL_COLOR}" color="#{ENTITY_LINE_COLOR}"]}
21
+ }
22
+ parser.enums.values.each { |e|
23
+ ns, base = DataMetaDom::splitNameSpace(e.name)
24
+ out.puts %{ #{base} [fillcolor = "#{ENUM_FILL_COLOR}" color="#{ENUM_LINE_COLOR}"]}
25
+ }
26
+
27
+ parser.records.each_value.each { |rec|
28
+ rec.refs.each { |ref|
29
+ # can not use the dotted package notation, GraphViz interprets it differently
30
+ # besides, with full names the graph becomes unreadable.
31
+ ns, fromEntityBareName = splitNameSpace ref.fromEntity.name
32
+ ns, toEntityBareName = splitNameSpace ref.toEntity.name
33
+ case ref.type
34
+ when Reference::RECORD
35
+ out.puts %{ #{fromEntityBareName} -> #{toEntityBareName} } + \
36
+ %{[ label="#{ref.fromField.name}" color="#{ENTITY_LINE_COLOR}"]}
37
+ when Reference::ENUM_REF
38
+ out.puts %{ #{fromEntityBareName} -> #{toEntityBareName} } +\
39
+ %{[ label="#{ref.fromField.name}" color="#{ENUM_LINE_COLOR}"]}
40
+ else
41
+ # skip it
42
+ end
43
+ }
44
+ }
45
+ out.puts '}'
46
+ out.close
47
+ end
48
+
49
+ def viewGv
50
+ puts `dot -o#{@imageFile} -Tjpeg #{@gvFile}`
51
+ if DataMetaXtra::Sys::WINDOWS
52
+ @imageFile.gsub!('/','\\')
53
+ irfanViewExe = %<#{ENV['PROGRAMFILES']}\\IrfanView\\i_view32.exe>
54
+ shimgvwDll = %<#{ENV['SystemRoot']}\\System32\\shimgvw.dll>
55
+ if File.file?(irfanViewExe) # if Irfanview is installed, use it because it works always faster than PhotoViewer
56
+ system(%<start "#{File.basename(@domFile)}" "#{irfanViewExe}" #{@imageFile} /title=#{File.basename(@domFile)}>)
57
+ elsif File.file?(shimgvwDll)
58
+ =begin
59
+ use the standard issue Windows PhotoViewer
60
+ if this runs too slow, run Color Calibration, or move the PhotoViewer window from one monitor to another:
61
+ if the PhotoViewer still is slow, install and use IrfanView 32 bit instead:
62
+ =end
63
+ system(%<start "#{File.basename(@domFile)}" rundll32.exe #{shimgvwDll}, ImageView_Fullscreen #{@imageFile}>)
64
+ else # use default Windows viewer for jpeg if any
65
+ system(%<start "#{File.basename(@domFile)}" #{@imageFile}>)
66
+ end
67
+ elsif DataMetaXtra::Sys::LINUX
68
+ # on Linux, ise ImageMagick, can install it with: sudo yum install php-pecl-imagick
69
+ system("display #{@imageFile} &")
70
+ # can also use "gnome-open" under GDM
71
+ else
72
+ $stderr.puts %|Don't know how to run image view on "#{RUBY_PLATFORM}"|
73
+ end
74
+
75
+ end
76
+
77
+ @domFile, @outPath = $*
78
+ raise %|DataMetaDOM source "#{@domFile}" is not a file| unless @domFile && File.file?(@domFile)
79
+ raise 'Output path is missing' unless @outPath
80
+ @outDir = File.dirname(@outPath)
81
+ raise %|Output directory "#{@outDir}" is not a directory| unless @outDir && File.directory?(@outDir)
82
+ # absolute path works best with viewer utilities and exporters too
83
+ @domBase = File.basename(@domFile, '.dmDom')
84
+ @gvFile = File.absolute_path(File.join(@outPath, @domBase + '.gv'))
85
+ @imageFile = File.absolute_path(File.join(@outPath, @domBase + '.jpeg'))
86
+
87
+
88
+ @parser = Model.new
89
+ begin
90
+ @parser.parse @domFile
91
+ genGv @parser, @gvFile
92
+ viewGv
93
+ rescue Exception => e
94
+ puts "ERROR #{e.message}#{@parser.diagn}"
95
+ puts e.backtrace.inspect
96
+ end
97
+
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # this script generates the SQL DDL for the DataMeta DOM model
3
+ # Example, from gem root:
4
+ # dataMetaMySqlDdl.rb ../../../dataMeta/showCase.dmDom ../../../../../target/sql
5
+
6
+ %w(dataMetaDom dataMetaDom/mySql dataMetaDom/help).each(&method(:require))
7
+
8
+ include DataMetaDom, DataMetaDom::MySqlLexer
9
+
10
+ @source, @target = ARGV
11
+
12
+ DataMetaDom::helpMySqlDdl __FILE__ unless @source && @target
13
+ DataMetaDom::helpMySqlDdl(__FILE__, "DataMeta DOM source #{@source} is not a file") unless File.file?(@source)
14
+ DataMetaDom::helpMySqlDdl(__FILE__, "MySQL DDL destination directory #{@target} is not a dir") unless File.directory?(@target)
15
+
16
+ @parser = Model.new
17
+ begin
18
+ @parser.parse(@source)
19
+ puts @parser.enums.values.join("\n") if $DEBUG
20
+ puts @parser.records.values.join("\n") if $DEBUG
21
+ genDdl(@parser, @target)
22
+ puts "MySQL DDL generated into #{@target}"
23
+ rescue Exception => e
24
+ $stderr.puts "ERROR #{e.message}; #{@parser.diagn}"
25
+ $stderr.puts e.backtrace.inspect
26
+ exit 1
27
+ end
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+ # this script generates the SQL DDL for the DataMeta DOM core model
3
+ # Example, from gem root:
4
+ # dataMetaOracleDdl.rb ../../../dataMeta/showCase.dmDom ../../../../../target/sql
5
+
6
+ %w(dataMetaDom dataMetaDom/ora dataMetaDom/help).each(&method(:require))
7
+
8
+ include DataMetaDom, DataMetaDom::OraLexer
9
+
10
+ @source, @target = ARGV
11
+ DataMetaDom::helpOracleDdl __FILE__ unless @source && @target
12
+ DataMetaDom::helpOracleDdl(__FILE__, "DataMeta DOM source #{@source} is not a file") unless File.file?(@source)
13
+ DataMetaDom::helpOracleDdl(__FILE__, "Oracle DDL destination directory #{@target} is not a dir") unless File.directory?(@target)
14
+
15
+ @parser = Model.new
16
+ begin
17
+ @parser.parse(@source)
18
+ puts @parser.enums.values.join("\n") if $DEBUG
19
+ puts @parser.records.values.join("\n") if $DEBUG
20
+ genDdl(@parser, @target)
21
+ puts "Oracle DDL generated into #{@target}"
22
+ rescue Exception => e
23
+ $stderr.puts "ERROR #{e.message}; #{@parser.diagn}"
24
+ $stderr.puts e.backtrace.inspect
25
+ exit 1
26
+ end
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+ # this script generates Java POJOs and the SQL DDL for the DataMeta DOM model
3
+ # Sample:
4
+ # mkdir ../../../../../target/pojo
5
+ # dataMetaPojo.rb ../../../dataMeta/showCase.dmDom ../../../../../target/pojo
6
+
7
+ %w(dataMetaDom dataMetaDom/pojo dataMetaDom/help).each(&method(:require))
8
+
9
+ include DataMetaDom, DataMetaDom::PojoLexer
10
+
11
+ @source, @target = ARGV
12
+ DataMetaDom::helpPojoGen __FILE__ unless @source && @target
13
+ DataMetaDom::helpPojoGen(__FILE__, "DataMeta DOM source #{@source} is not a file") unless File.file?(@source)
14
+ DataMetaDom::helpPojoGen(__FILE__, "POJO destination directory #{@target} is not a dir") unless File.directory?(@target)
15
+
16
+ @parser = Model.new
17
+ begin
18
+ @parser.parse(@source, options={autoVerNs: true})
19
+ puts @parser.enums.values.join("\n") if $DEBUG
20
+ puts @parser.records.values.join("\n") if $DEBUG
21
+ genPojos(@parser, @target)
22
+ puts "POJOs written to #{@target}. Done."
23
+ rescue Exception => e
24
+ $stderr.puts "ERROR #{e.message}; #{@parser.diagn}"
25
+ $stderr.puts e.backtrace.inspect
26
+ exit 1
27
+ end
@@ -0,0 +1,66 @@
1
+ #!/bin/env ruby
2
+
3
+ # This script replaces references to DataMetaDOM version with a new version
4
+ # In the source files as well as config files.
5
+
6
+ require 'dataMetaDom'
7
+ require 'dataMetaDom/ver'
8
+ require 'dataMetaDom/help'
9
+
10
+ @path, @ns, @globs_def, @ver_from_spec, @ver_to_spec = $*
11
+
12
+ def help(errorText = nil)
13
+ DataMetaDom.help(__FILE__, 'Source reversioner', %q~<Path> <NS> <CSV-globs> <Ver-From> <Ver-To>
14
+
15
+ Where:
16
+ * Path - starting path to look for the files to re-version
17
+ * NS - Namespace, such as Java/Scala package
18
+ * CVS-globs - comma-separated file patterns, in regular filesystem globbing format
19
+ * Ver-From - Source version or an asterisk for any version. Example: 1.2.1
20
+ * Ver-To - Target version. Example: 1.2.2
21
+
22
+ Examples of arguments:
23
+ Replace on all Java and Scala files starting from the src/main/com/acme, any prior DataMeta version with 1.2.3:
24
+ src/main/com/acme com.acme.svc.schema.dom '*.java,*.scala' '*' 1.2.3
25
+
26
+ Starting from the current directory, replace on all Scala and config files, DataMeta version 1.2.1 with 1.2.3:
27
+ . com.acme.svc.schema.dom '*.conf,*.scala' 1.2.1 1.2.3
28
+
29
+ Note the single quotes for the file glob patterns and the "star" specification of the source version: this is to
30
+ prevent the shell to glob before passing the result to the program.
31
+
32
+ Note that there is no relation between the path and the namespace; only Java still enforces such relation therefore
33
+ we do not want to be dependent on it.
34
+
35
+ ~, errorText)
36
+ end
37
+
38
+ help 'Target path is missing' unless @path && !@path.empty?
39
+ help %<"#{@path}" is not a valid path!> unless File.directory?(@path)
40
+ help %<"#{@ns}" is not a valid namespace!> unless @ns.is_a?(String) && @ns =~ /^[\w_\.]+$/
41
+ help 'No file globs specified' unless @globs_def && !@globs_def.empty?
42
+ if @ver_from_spec == '*'
43
+ @ver_from = nil
44
+ else
45
+ begin
46
+ @ver_from = DataMetaDom::SemVer.new(@ver_from_spec)
47
+ rescue Exception => x
48
+ help "Source version: #{x.message}"
49
+ end
50
+ end
51
+
52
+ begin
53
+ @ver_to = DataMetaDom::SemVer.new(@ver_to_spec)
54
+ rescue Exception => x
55
+ help "Target version: #{x.message}"
56
+ end
57
+
58
+ begin
59
+ puts "Reversioning #{@globs_def} files starting from #{@path} to #{@ver_to}"
60
+ DataMetaDom::Ver.reVersion(@path, @ns, @globs_def.split(','), @ver_from, @ver_to)
61
+ puts 'Done.'
62
+ rescue Exception => x
63
+ $stderr.puts %<ERROR #{x.message}
64
+ #{x.backtrace.join("\n\t")}>
65
+ exit 1
66
+ end
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+ # this script generates Full Compare DataMetaSame implementors
3
+ # Sample:
4
+ # mkdir ../../../../../target/pojo
5
+ # dataMetaSameFullJ.rb ../../../dataMeta/showCase.dmDom ../../../../../target/pojo
6
+
7
+ %w(dataMetaDom dataMetaDom/pojo dataMetaDom/help).each(&method(:require))
8
+
9
+ source, target = ARGV
10
+ raise ArgumentError, 'Usage: source DataMeta DOM, target directory' unless source && target
11
+ DataMetaDom::PojoLexer.dataMetaSameRun DataMetaDom::PojoLexer::FULL_COMPARE, __FILE__, source, target
12
+
13
+ puts "All-fields DataMeta-Sames written to #{target}. Done."
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ # this script generates Full Compare DataMetaSame implementors
3
+ # Sample:
4
+ # mkdir ../../../../../target/pojo
5
+ # dataMetaSameIdJ.rb ../../../schema/showCase.dmDom ../../../../../target/pojo
6
+
7
+ %w(dataMetaDom dataMetaDom/pojo dataMetaDom/help).each(&method(:require))
8
+
9
+ source, target = ARGV
10
+ raise ArgumentError, 'Usage: source DataMeta DOM, target directory' unless source && target
11
+ DataMetaDom::PojoLexer.dataMetaSameRun DataMetaDom::PojoLexer::ID_ONLY_COMPARE, __FILE__, source, target
12
+ puts "ID level DataMetaSames written to #{target}. Done."
@@ -0,0 +1,70 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
2
+
3
+ %w(fileutils set).each { |r| require r }
4
+
5
+ module DataMetaDom
6
+
7
+ =begin
8
+ Converter (ser/deser) code common to the DataMeta DOM.
9
+
10
+ For command line details either check the new method's source or the README.rdoc file, the usage section.
11
+ =end
12
+
13
+ =begin rdoc
14
+ Converter class definition, see implementations:
15
+ * INTEGRAL_CONV
16
+ * FRACT_CONV
17
+ * BOOL_CONV
18
+ * DTTM_CONV
19
+ * TEXT_CONV
20
+ =end
21
+ class Converter
22
+
23
+ =begin rdoc
24
+ Lambda converting from a data type to matching textual.
25
+ =end
26
+ attr_reader :ser
27
+
28
+ =begin rdoc
29
+ Lambda converting from a textual to matching data type.
30
+ =end
31
+ attr_reader :deser
32
+
33
+ =begin rdoc
34
+ Creates an instance with the given parameters, two lambdas, see ser and deser properties for details.
35
+ =end
36
+ def initialize(serialize, deserialize); @ser = serialize; @deser = deserialize end
37
+ end
38
+
39
+ =begin rdoc
40
+ Converter for the integral types, meaning no fraction.
41
+ =end
42
+ INTEGRAL_CONV=Converter.new(lambda { |i| i ? i.to_s : nil }, lambda { |s| s ? s.to_i : nil })
43
+
44
+ =begin rdoc
45
+ Numbers with fraction, such as real numbers, aka floating point.
46
+ =end
47
+ FRACT_CONV=Converter.new(lambda { |f| f ? f.to_s : nil }, lambda { |s| s ? s.to_f : nil })
48
+
49
+ =begin rdoc
50
+ Converter for boolean.
51
+ =end
52
+ BOOL_CONV=Converter.new(lambda { |b| b ? b.to_s : nil },
53
+ lambda { |s| s && !s.empty? ? ("TY1ty1".index(s[0]) ? true : false) : nil })
54
+ =begin rdoc
55
+ Converter for datetime.
56
+ =end
57
+ DTTM_CONV=Converter.new(lambda { |d| d ? "DateTime.parse('#{d}')" : nil }, lambda { |s| s ? DateTime.parse(s) : nil })
58
+ # DateTime.to_s does exactly what we need, no more no less
59
+
60
+ =begin rdoc
61
+ Conterter for textual types, such as string or char.
62
+ =end
63
+ TEXT_CONV=Converter.new(lambda { |src| src.inspect }, lambda { |src| eval(src) })
64
+
65
+ # All Converters hash keyed by the type, referencing an instance of the Converter class.
66
+ CONVS={INT => INTEGRAL_CONV, STRING => TEXT_CONV, CHAR => TEXT_CONV, FLOAT => FRACT_CONV, NUMERIC => FRACT_CONV,
67
+ BOOL => BOOL_CONV, DATETIME => DTTM_CONV, URL => TEXT_CONV}
68
+
69
+
70
+ end
@@ -0,0 +1,112 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
2
+
3
+ %w(fileutils set dataMetaDom/util).each { |r| require r }
4
+
5
+ module DataMetaDom
6
+
7
+ =begin rdoc
8
+ DataMeta DOM Data Type, including the base type, length if any and scale if any.
9
+
10
+ For command line details either check the new method's source or the README.rdoc file, the usage section.
11
+ =end
12
+ class DataType
13
+
14
+ =begin rdoc
15
+ Base type; either one of the standard types, see STANDARD_TYPES on the util.rb or fully named custom type
16
+ such as a Record, an Enum, a Map, a BitSet.
17
+
18
+ Use case of changing the type: multiple versions in one VM process.
19
+ =end
20
+ attr_accessor :type
21
+
22
+ =begin rdoc
23
+ For those data types that have a dimension, such as length. See DIMMED_TYPES on the util.rb.
24
+ =end
25
+ attr_reader :length
26
+
27
+ =begin rdoc
28
+ For those data types that have a scale. See SCALE_TYPES on the util.rb.
29
+ =end
30
+ attr_reader :scale
31
+
32
+ class << self
33
+ # The type must not feature a length
34
+ def mustNotDim(type)
35
+ !DIMMED_TYPES.member?(type) && !OPT_DIMMABLE.member?(type)
36
+ end
37
+
38
+ # The type must feature a length > 0
39
+ def mustDim(type)
40
+ DIMMED_TYPES.member?(type)
41
+ end
42
+
43
+ # The type may or may not feature a length
44
+ def canDim(type)
45
+ DIMMED_TYPES.member?(type) || OPT_DIMMABLE.member?(type)
46
+ end
47
+
48
+ =begin rdoc
49
+ Parses type definition from DataMeta DOM source, raising errors if anything is wrong.
50
+ Returns a new instance of the DataType.
51
+ =end
52
+ def parse(src, textual)
53
+ r = textual.scan(/([\w\.]+)(\[[\d\.]+\])?/)
54
+ raise "Invalid data type spec #{textual}" unless r
55
+ typeSpec, dimSpec = r[0]
56
+ type = typeSpec.to_sym
57
+ raise "The type #{type} can not be dimensioned" if DataType.mustNotDim(type) && dimSpec && !dimSpec.empty?
58
+ raise "The type #{type} must be dimensioned" if DataType.mustDim(type) && (!dimSpec || dimSpec.empty?)
59
+ length = nil; scale = nil
60
+ unless !dimSpec || dimSpec.empty?
61
+ raise "Invalid dimension format '#{dimSpec}'" unless dimSpec.scan(/^\[(\d+)\.?(\d+)?\]$/)
62
+ length = $1.to_i
63
+ scale = $2 ? $2.to_i : nil
64
+ end
65
+ @type = DataMetaDom.fullTypeName(src.namespace, type)
66
+ DataType.new @type, length, scale
67
+ end
68
+
69
+ end
70
+
71
+ =begin rdoc
72
+ Creates the instance with the given base type, the length and the scale
73
+ =end
74
+ def initialize(t, len=nil, scale=nil)
75
+ raise ArgumentError, "The type #{t} can not have length" if DataType.mustNotDim(t) && len
76
+
77
+ raise ArgumentError, "The type #{type} must have length > 0, but \"#{len}\" specified" \
78
+ if DataType.mustDim(t) && (!len || len < 1)
79
+
80
+ @type = t.to_sym
81
+ @length = len
82
+ @scale = scale
83
+ end
84
+
85
+ =begin rdoc
86
+ Builds a length (dimension) and scale specification for this type according to the DataMeta DOM syntax.
87
+ If the type does not have a dimension (no length, no scale), returns empty string.
88
+ =end
89
+ def length_spec; @length && @length != 0 ? "[#{@length}" + (@scale ? '.' + @scale.to_s : '') + ']' : '' end
90
+
91
+ # Textual representation of this isntance, includes the type spec with the length spec.
92
+ def to_s; "#{@type}#{length_spec}" end
93
+ end
94
+
95
+ # Reusable type - Integer of the length 1, aka Java's +byte+.
96
+ INT1 = DataType.new(INT, 1)
97
+ # Reusable type - Integer of the length 2, aka Java's +short+.
98
+ INT2 = DataType.new(INT, 2)
99
+ # Reusable type - Integer of the length 4, aka Java's +int+.
100
+ INT4 = DataType.new(INT, 4)
101
+ # Reusable type - Integer of the length 8, aka Java's +long+.
102
+ INT8 = DataType.new(INT, 8)
103
+ # Reusable type - Float (Real number) of the length 4, aka Java's +float+.
104
+ FLOAT4 = DataType.new(FLOAT, 4)
105
+ # Reusable type - Float (Real number) of the length 8, aka Java's +double+.
106
+ FLOAT8 = DataType.new(FLOAT, 8)
107
+ # Reusable type - DATETIME, in Java projected into <tt>java.time.ZonedDateTime</tt>.
108
+ DTTM_TYPE = DataType.new(DATETIME)
109
+ # Reusable type - URL, in Java projected into <tt>java.net.URL</tt>.
110
+ URL_TYPE = DataType.new(URL)
111
+
112
+ end