dataMetaPii 1.0.1
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.
- checksums.yaml +7 -0
- data/.yardopts +1 -0
- data/History.md +10 -0
- data/PostInstall.txt +2 -0
- data/README.md +77 -0
- data/Rakefile +13 -0
- data/bin/dmPiiGenCode.rb +65 -0
- data/grammar/appLink.treetop +214 -0
- data/grammar/piiCommons.treetop +46 -0
- data/grammar/registry.treetop +66 -0
- data/lib/dataMetaPii.rb +577 -0
- data/test/appLinkFull.dmPii +71 -0
- data/test/appLinkNoReusables.dmPii +35 -0
- data/test/appLinkShowcase.dmPii +73 -0
- data/test/registryShowcase.dmPii +28 -0
- data/test/test_dataMetaPii.rb +42 -0
- data/test/test_grammars.rb +152 -0
- data/test/test_helper.rb +24 -0
- data/tpl/java/master.erb +64 -0
- data/tpl/json/master.erb +7 -0
- data/tpl/python/master.erb +25 -0
- data/tpl/scala/master.erb +31 -0
- metadata +106 -0
@@ -0,0 +1,71 @@
|
|
1
|
+
# DSL describing Connection between the PII abstract definition and application concretics
|
2
|
+
# This is full definition that can be parsed and structured.
|
3
|
+
|
4
|
+
ver "12.489.2.alpha"
|
5
|
+
|
6
|
+
# Reusable Attributes Division
|
7
|
+
attributes {
|
8
|
+
universalConstants {
|
9
|
+
piPositive: 3.14, # numers and decimal point: Float
|
10
|
+
piNegative: -3.14, # check the negative case
|
11
|
+
universe: "Forty-two",
|
12
|
+
@sam# reference to the reusable, see further down
|
13
|
+
}
|
14
|
+
ints {
|
15
|
+
maxInstanceCount: 0012, # numbers only, no decimal point: perceived/rendered as an Integer
|
16
|
+
foo: -019 # check the negative case; note that octal conversion does not apply like with literals in Ruby code
|
17
|
+
}
|
18
|
+
sam { # Can the parser handle strings with C-like backslash escapes?
|
19
|
+
says: "Sam \t says, \"You kidding me, right?\"",
|
20
|
+
@donald # should be able to handle cycles in the inclusion tree
|
21
|
+
}
|
22
|
+
donald {
|
23
|
+
quacks: "Quack!",
|
24
|
+
@sam # should be able to handle cycles in the inclusion tree
|
25
|
+
}
|
26
|
+
# see if the parser can handle a one-liner
|
27
|
+
noise { @donald, spectrum: "white", @sam, @ints }
|
28
|
+
}
|
29
|
+
|
30
|
+
# Application Division
|
31
|
+
apps {
|
32
|
+
pollingServices { # Unique application ID; should be unique throughout the config, each app responsible for its own def
|
33
|
+
# or make it centralized, standard??
|
34
|
+
Name_Full { # the PII key from the abstract definition
|
35
|
+
# Application-specific attributes for this field (need to standardize them?):
|
36
|
+
|
37
|
+
# DataMeta DOM record's name, without the version let alone the package: the application
|
38
|
+
# should be aware of those details and be flexible. From this, can infer the InOutable and migration calls
|
39
|
+
voClass: Name,
|
40
|
+
# list of database fields that store this value
|
41
|
+
bigTableFields: "users:name, clients:fullName",
|
42
|
+
@ints # reference to the reusables
|
43
|
+
}
|
44
|
+
|
45
|
+
TwoFA_Token_Serial_Number {
|
46
|
+
voClass: TwoFaSerialNumber,
|
47
|
+
bigTableFields: "security:twoFa",
|
48
|
+
@universalConstants,@ints
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
bcastingServices {
|
53
|
+
Name_First {
|
54
|
+
voClass: Name,
|
55
|
+
oracleFields: "USERS:FIRST_NAME",
|
56
|
+
lapseCount: 0123,
|
57
|
+
median: -123.4567,
|
58
|
+
weight: 987.65432
|
59
|
+
}
|
60
|
+
Name_Last {
|
61
|
+
voClass: Name,
|
62
|
+
oracleFields: "USERS:LAST_NAME"
|
63
|
+
}
|
64
|
+
Date_Of_Birth {
|
65
|
+
voClass: BirthDate, # plain symbol, no enclosure: perceived/rendered as a string
|
66
|
+
logFormat: "yyyy-MM-dd HH:mm:SS", # enclosured in a string: perceived/rendered as a string
|
67
|
+
@universalConstants,
|
68
|
+
bigTableFields: "users:dob,clients:birthDate" # enclosured in a string: perceived/rendered as a string
|
69
|
+
}
|
70
|
+
}
|
71
|
+
}
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# DSL describing Connection between the PII abstract definition and application concretics
|
2
|
+
# This is full definition that can be parsed and structured.
|
3
|
+
# For testing/structuring purposes, the attributes division is missing and
|
4
|
+
# no reusables are referred to.
|
5
|
+
|
6
|
+
ver "3.423.11.19"
|
7
|
+
|
8
|
+
# Application Division
|
9
|
+
apps {
|
10
|
+
pollingServices { # Unique application ID; should be unique throughout the config, each app responsible for its own def
|
11
|
+
# or make it centralized, standard??
|
12
|
+
Name_Full { # the PII key from the abstract definition
|
13
|
+
# Application-specific attributes for this field (need to standardize them?):
|
14
|
+
|
15
|
+
# DataMeta DOM record's name, without the version let alone the package: the application
|
16
|
+
# should be aware of those details and be flexible. From this, can infer the InOutable and migration calls
|
17
|
+
voClass: Name,
|
18
|
+
# list of database fields that store this value
|
19
|
+
oracleFields: "users:name, clients:fullName"
|
20
|
+
}
|
21
|
+
|
22
|
+
TwoFA_Token_Serial_Number {
|
23
|
+
voClass: TwoFaSerialNumber,
|
24
|
+
oracleFields: "security:twoFa"
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
bcastingServices {
|
29
|
+
Date_Of_Birth {
|
30
|
+
voClass: BirthDate, # plain symbol, no enclosure: perceived/rendered as a string
|
31
|
+
logFormat: "yyyy-MM-dd HH:mm:SS", # enclosured in a string: perceived/rendered as a string
|
32
|
+
oracleFields: "users:dob,clients:birthDate" # enclosured in a string: perceived/rendered as a string
|
33
|
+
}
|
34
|
+
}
|
35
|
+
}
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# This definition is for grammar testing/debugging only.
|
2
|
+
# An attempt to pass it through structuring should fail because there are intentional violations
|
3
|
+
# of a exogrammatical structure: for example, multiple VO definitions are allowed by the grammar
|
4
|
+
# but the CST builder rejects those with an error.
|
5
|
+
|
6
|
+
ver "1.2.3.4.beta" # Full version presented here
|
7
|
+
|
8
|
+
# Reusable Attributes Division
|
9
|
+
attributes {
|
10
|
+
universalConstants {
|
11
|
+
piPositive: 3.14, # numers and decimal point: Float
|
12
|
+
piNegative: -3.14, # check the negative case
|
13
|
+
universe: "Forty-two",
|
14
|
+
@sam, # reference to the reusable, see further down
|
15
|
+
@symbolSoloOnLine,
|
16
|
+
boo: 1.23, foo:-35.36,
|
17
|
+
@symbolLeadinWsAndTrailingComment, # endline comment for this
|
18
|
+
@symbolWithTrailingComment, # endline comment
|
19
|
+
@symbolWithLeadingWhitespace, str:"Some \n string"
|
20
|
+
}
|
21
|
+
ints {
|
22
|
+
maxInstanceCount: 4, # numbers only, no decimal point: perceived/rendered as an Integer
|
23
|
+
foo: -4 # check the negative case
|
24
|
+
}
|
25
|
+
sam { # Can the parser handle strings with C-like backslash escapes?
|
26
|
+
says: "Sam \t says, \"You kidding me, right?\""
|
27
|
+
}
|
28
|
+
donald {
|
29
|
+
quacks: "Quack!"
|
30
|
+
}
|
31
|
+
# see if the parser can handle a one-liner
|
32
|
+
noise { @donald, spectrum: "white", @sam }
|
33
|
+
}
|
34
|
+
|
35
|
+
# Application Division
|
36
|
+
apps {
|
37
|
+
pollingServices { # Unique application ID; should be unique throughout the config, each app responsible for its own def
|
38
|
+
# or make it centralized, standard??
|
39
|
+
Name_Full { # the PII key from the abstract definition
|
40
|
+
# Application-specific attributes for this field (need to standardize them?):
|
41
|
+
|
42
|
+
# DataMeta DOM record's name, without the version let alone the package: the application
|
43
|
+
# should be aware of those details and be flexible. From this, can infer the InOutable and migration calls
|
44
|
+
voClass: Name,
|
45
|
+
# list of database fields that store this value
|
46
|
+
mySqlFields: "users:name, clients:fullName",
|
47
|
+
@ints # reference to the reusables
|
48
|
+
}
|
49
|
+
|
50
|
+
TwoFA_Token_Serial_Number {
|
51
|
+
voClass: TwoFaSerialNumber,
|
52
|
+
db2Fields: "security:twoFa",
|
53
|
+
@universalConstants,@ints
|
54
|
+
}
|
55
|
+
} # try this
|
56
|
+
bcastingServices {
|
57
|
+
Date_Of_Birth {
|
58
|
+
voClass:FirstClass,
|
59
|
+
voClass: SecondClass,
|
60
|
+
voClass : ThirdClass,
|
61
|
+
voClass :FourthClass,
|
62
|
+
# Leading space
|
63
|
+
voClass: FifthClass,
|
64
|
+
voClass: SixthClass, # tail comment
|
65
|
+
voClass :SeventhClass # tail with no leading whitespace
|
66
|
+
}
|
67
|
+
TwoFA_Token_Serial_Number {
|
68
|
+
voClass: TwoFaSerialNumber,
|
69
|
+
bigTableFields: "security:twoFa",
|
70
|
+
@universalConstants,@ints
|
71
|
+
}
|
72
|
+
}
|
73
|
+
}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# Master Definition Of the PII fields
|
2
|
+
# the "taboo" level means that under no circumstances the value should be stored.
|
3
|
+
|
4
|
+
# PII field definition format:
|
5
|
+
# PII-Field-UniqueKey {PROFILE-KEY {level=IMPACT_LEVEL}}
|
6
|
+
|
7
|
+
# These impact levels are picked at random for testing, check with your company's policies
|
8
|
+
# for real impact levels.
|
9
|
+
|
10
|
+
ver "1.0.0"
|
11
|
+
|
12
|
+
Corp_User_Name { # PII field unique key
|
13
|
+
level=taboo # "taboo" : in this profile, under no circumstances this field can be stored or rendered in the logs
|
14
|
+
}
|
15
|
+
|
16
|
+
Date_Of_Birth { level=restricted }
|
17
|
+
|
18
|
+
TwoFA_Token {level=confidential, dataType=access}
|
19
|
+
|
20
|
+
Home_City {level=confidential, dataType=location}
|
21
|
+
Home_Country {level=confidential}
|
22
|
+
Home_State {level=confidential} # State or Province
|
23
|
+
Home_Zip {level=confidential} # U.S. ZIP code
|
24
|
+
Name_First {level=confidential}
|
25
|
+
Name_Last {level=internal}
|
26
|
+
Name_Middle {level=public}
|
27
|
+
Name_Full {level=confidential,enabled=true, owner=nameKeeper}
|
28
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# keep this underscore naming in the test subdir, it's easier to append files names to test
|
2
|
+
require './test/test_helper.rb'
|
3
|
+
|
4
|
+
=begin rdoc
|
5
|
+
Unit test cases for the DataMetaPii
|
6
|
+
=end
|
7
|
+
class TestNewGem < Test::Unit::TestCase
|
8
|
+
include DataMetaPiiTests
|
9
|
+
|
10
|
+
# an empty stub for now
|
11
|
+
def setup;
|
12
|
+
@impactConstVals = DataMetaPii::Impact.constants.map{|c| ":#{DataMetaPii::Impact.const_get(c)}"}
|
13
|
+
end
|
14
|
+
|
15
|
+
=begin rdoc
|
16
|
+
Test obtaining a constant list from a module
|
17
|
+
=end
|
18
|
+
def test_constantList
|
19
|
+
v = DataMetaPii::RegKeyVo.new('A_PII_field',
|
20
|
+
{DataMetaPii::RegKeyVo::LEVEL => DataMetaPii::Impact::CONFIDENTIAL, "foo" => "bar", "val" => 123.456})
|
21
|
+
|
22
|
+
L.info(%<Impact constants: #{DataMetaPii::Impact.constants.map{|c| "#{c}=#{DataMetaPii::Impact.const_get(c)}"}.join('; ')}
|
23
|
+
first PII VO created: #{v.to_tree_image(DataMetaPii::INDENT)}
|
24
|
+
>)
|
25
|
+
xcp = assert_raise(ArgumentError) { DataMetaPii::RegKeyVo.new('A_PII_field', {DataMetaPii::RegKeyVo::LEVEL => ''}) }
|
26
|
+
assert(xcp.message.start_with?('Impact level missing or empty in'))
|
27
|
+
|
28
|
+
xcp = assert_raise(ArgumentError) { DataMetaPii::RegKeyVo.new('A_PII_field', {'foo' => 'bar'}) }
|
29
|
+
assert(xcp.message.start_with?('Impact level missing or empty in'))
|
30
|
+
|
31
|
+
xcp = assert_raise(ArgumentError) { DataMetaPii::RegKeyVo.new('A PII field',
|
32
|
+
{DataMetaPii::RegKeyVo::LEVEL => DataMetaPii::Impact::CONFIDENTIAL}) }
|
33
|
+
|
34
|
+
assert(xcp.message.start_with?('Invalid PII key: '))
|
35
|
+
|
36
|
+
xcp = assert_raise(ArgumentError) { DataMetaPii::RegKeyVo.new('A_PII_field',
|
37
|
+
{DataMetaPii::RegKeyVo::LEVEL => :bad_impact_level}) }
|
38
|
+
|
39
|
+
L.info(%<Testing #{:bad_impact_level}: #{xcp.message}\n#{xcp.backtrace.join("\n\t")}\n>)
|
40
|
+
assert(xcp.message.start_with?('Unsupported Impact Level '))
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require './test/test_helper.rb'
|
2
|
+
|
3
|
+
=begin rdoc
|
4
|
+
Test for the DataMetaPii grammars and parsing.
|
5
|
+
|
6
|
+
Assertions: http://ruby-doc.org/stdlib-1.9.3/libdoc/test/unit/rdoc/Test/Unit/Assertions.html
|
7
|
+
=end
|
8
|
+
class TestPiiFmts < Test::Unit::TestCase
|
9
|
+
|
10
|
+
include DataMetaPiiTests
|
11
|
+
|
12
|
+
# loads the fmt grammar and creates the parser instance
|
13
|
+
def setup
|
14
|
+
|
15
|
+
@registryParser = PiiRegistryParser.new
|
16
|
+
@piiAppLinkParser = PiiAppLinkParser.new
|
17
|
+
L.info %<DataMeta PII Registry parser: #{@registryParser.inspect}
|
18
|
+
DataMeta PII App Link parser: #{@piiAppLinkParser.inspect}
|
19
|
+
>
|
20
|
+
end
|
21
|
+
|
22
|
+
=begin rdoc
|
23
|
+
Test Pii Registry DML parsing
|
24
|
+
=end
|
25
|
+
def test_registry_parse
|
26
|
+
ast = DataMetaParse.parse(@registryParser, IO.read('./test/registryShowcase.dmPii'))
|
27
|
+
L.info 'Registry parse start'
|
28
|
+
raise 'Registry File Format parse unsuccessful' unless ast
|
29
|
+
raise ast if ast.is_a?(DataMetaParse::Err)
|
30
|
+
#L.info "AST:\n#{ast.fields.inspect}"
|
31
|
+
#L.info "----------AST:\n#{ast.inspect}"
|
32
|
+
#elems = [ast.items.elements]
|
33
|
+
#elems = [ast.fields]
|
34
|
+
#L.info "===========AST Fields:\n#{elems.inspect}\n==================="
|
35
|
+
ast.fields.elements.each { |f|
|
36
|
+
L.info("PII Key: #{f.pk}: #{f.attrbLst.attrbs.map{|e| "#{e.k}::#{e.v}"}.join('; ')}")
|
37
|
+
}
|
38
|
+
L.info(%<PII Registry:
|
39
|
+
#{DataMetaPii.buildRegCst(ast).to_tree_image(DataMetaPii::INDENT)}>)
|
40
|
+
end
|
41
|
+
|
42
|
+
=begin rdoc
|
43
|
+
Test Pii Registry DML parsing and structuring - full version
|
44
|
+
=end
|
45
|
+
def test_app_link_parse_full
|
46
|
+
L.info 'Full applink parse start'
|
47
|
+
ast = DataMetaParse.parse(@piiAppLinkParser, IO.read('./test/appLinkFull.dmPii'))
|
48
|
+
raise 'Full AppLink parse unsuccessful' unless ast
|
49
|
+
if ast.is_a?(DataMetaParse::Err)
|
50
|
+
raise %<#{ast.parser.failure_line}
|
51
|
+
#{ast.parser.failure_reason}>
|
52
|
+
end
|
53
|
+
#L.info "AST:\n#{ast.fields.inspect}"
|
54
|
+
#L.info "----------AST:\n#{ast.inspect}"
|
55
|
+
#elems = [ast.items.elements]
|
56
|
+
#elems = [ast.fields]
|
57
|
+
#L.info "===========AST Fields:\n#{elems.inspect}\n==================="
|
58
|
+
ast.elements[1].elements.each { |f|
|
59
|
+
if f.respond_to?(:type) && f.type == 'refVal'
|
60
|
+
L.info(%<refVal: #{f.sym}>)
|
61
|
+
else
|
62
|
+
L.info(%<AppLink Elem: #{f.inspect}>)
|
63
|
+
end
|
64
|
+
}
|
65
|
+
ast.elements[3].elements.each { |f|
|
66
|
+
if f.respond_to?(:type) && f.type == 'refVal'
|
67
|
+
L.info(%<refVal: #{f.sym}>)
|
68
|
+
else
|
69
|
+
L.info(%<AppLink Elem: #{f.inspect}>)
|
70
|
+
end
|
71
|
+
}
|
72
|
+
log = ''
|
73
|
+
appLinkObj = DataMetaPii.buildAlCst(ast, log)
|
74
|
+
|
75
|
+
L.info(%<AppLink Full:
|
76
|
+
#{appLinkObj}
|
77
|
+
Building log:
|
78
|
+
#{log}
|
79
|
+
>)#.to_tree_image(DataMetaPii::INDENT_STEP)}>)
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_app_link_parse_method
|
84
|
+
appLinkModel = DataMetaPii.parseAppLink(IO.read('./test/appLinkFull.dmPii'))
|
85
|
+
L.info(%<AppLink Model - full:
|
86
|
+
#{appLinkModel.inspect}>)
|
87
|
+
end
|
88
|
+
|
89
|
+
=begin rdoc
|
90
|
+
Test Pii Registry DML parsing - showcase version, do not run this tree through CST builder!
|
91
|
+
=end
|
92
|
+
def test_app_link_parse_showcase
|
93
|
+
L.info 'Showcase applink parse start'
|
94
|
+
ast = DataMetaParse.parse(@piiAppLinkParser, IO.read('./test/appLinkShowcase.dmPii'))
|
95
|
+
raise 'Showcase File Format parse unsuccessful' unless ast
|
96
|
+
if ast.is_a?(DataMetaParse::Err)
|
97
|
+
raise %<#{ast.parser.failure_line}
|
98
|
+
#{ast.parser.failure_reason}>
|
99
|
+
end
|
100
|
+
#L.info "AST:\n#{ast.fields.inspect}"
|
101
|
+
#L.info "----------AST:\n#{ast.inspect}"
|
102
|
+
#elems = [ast.items.elements]
|
103
|
+
#elems = [ast.fields]
|
104
|
+
#L.info "===========AST Fields:\n#{elems.inspect}\n==================="
|
105
|
+
ast.elements[1].elements.each { |f|
|
106
|
+
if f.respond_to?(:type) && f.type == 'refVal'
|
107
|
+
L.info(%<refVal: #{f.sym}>)
|
108
|
+
else
|
109
|
+
L.info(%<AppLink Elem: #{f.inspect}>)
|
110
|
+
end
|
111
|
+
}
|
112
|
+
ast.elements[3].elements.each { |f|
|
113
|
+
if f.respond_to?(:type) && f.type == 'refVal'
|
114
|
+
L.info(%<refVal: #{f.sym}>)
|
115
|
+
else
|
116
|
+
L.info(%<AppLink Elem: #{f.inspect}>)
|
117
|
+
end
|
118
|
+
}
|
119
|
+
end
|
120
|
+
|
121
|
+
=begin rdoc
|
122
|
+
Test Pii Registry DML parsing - version with no reusables, must be successfully processed by the CST builder
|
123
|
+
=end
|
124
|
+
def test_app_link_parse_no_reusables
|
125
|
+
L.info 'No-reusables applink parse start'
|
126
|
+
ast = DataMetaParse.parse(@piiAppLinkParser, IO.read('./test/appLinkNoReusables.dmPii'))
|
127
|
+
raise 'No-reusables File Format parse unsuccessful' unless ast
|
128
|
+
if ast.is_a?(DataMetaParse::Err)
|
129
|
+
raise %<#{ast.parser.failure_line}
|
130
|
+
#{ast.parser.failure_reason}>
|
131
|
+
end
|
132
|
+
#L.info "AST:\n#{ast.fields.inspect}"
|
133
|
+
#L.info "----------AST:\n#{ast.inspect}"
|
134
|
+
#elems = [ast.items.elements]
|
135
|
+
#elems = [ast.fields]
|
136
|
+
#L.info "===========AST Fields:\n#{elems.inspect}\n==================="
|
137
|
+
ast.elements[0].elements.each { |f|
|
138
|
+
if f.respond_to?(:type) && f.type == 'refVal'
|
139
|
+
L.info(%<refVal: #{f.sym}>)
|
140
|
+
else
|
141
|
+
L.info(%<AppLink Elem: #{f.inspect}>)
|
142
|
+
end
|
143
|
+
}
|
144
|
+
log = ''
|
145
|
+
applinkObj = DataMetaPii.buildAlCst(ast, log)
|
146
|
+
L.info(%<AppLink No Reusables:
|
147
|
+
#{applinkObj.inspect}
|
148
|
+
Building log:
|
149
|
+
#{log}
|
150
|
+
>)#.to_tree_image(DataMetaPii::INDENT_STEP)}>)
|
151
|
+
end
|
152
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
## keep this underscore naming in the test subdir, it's easier to append files names to test
|
2
|
+
%w(stringio test/unit).each { |r| require r }
|
3
|
+
# this is expected to run from the project root, normally by the rake file
|
4
|
+
|
5
|
+
$VERBOSE = false # turn off noisy for the 1st release
|
6
|
+
|
7
|
+
require './lib/dataMetaPii'
|
8
|
+
require 'logger'
|
9
|
+
require 'dataMetaParse'
|
10
|
+
|
11
|
+
module DataMetaPiiTests
|
12
|
+
|
13
|
+
L = Logger.new('piiTests.log', 0, 10_000_000)
|
14
|
+
L.level = Logger::DEBUG
|
15
|
+
L.datetime_format = '%Y-%m-%d %H:%M:%S'
|
16
|
+
|
17
|
+
# By the way, inspecting a parser does not make any difference compared to just to_s:
|
18
|
+
L.info(%<Loaded base rules: #{DataMetaPii::BASE_RULES}
|
19
|
+
|
20
|
+
Loaded PII Commons Rules: #{DataMetaPii::PII_COMMONS.inspect}
|
21
|
+
Loaded Regstry Rules: #{DataMetaPii::REGISTRY}
|
22
|
+
Loaded AppLink Rules: #{DataMetaPii::APP_LINK}
|
23
|
+
>)
|
24
|
+
end
|
data/tpl/java/master.erb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
package <%= namespace %>;
|
2
|
+
|
3
|
+
/*
|
4
|
+
**************** This file is generated by DataMeta; do not edit manually!!
|
5
|
+
*/
|
6
|
+
|
7
|
+
import java.util.HashMap;
|
8
|
+
import java.util.Map;
|
9
|
+
|
10
|
+
import static java.util.Collections.unmodifiableMap;
|
11
|
+
|
12
|
+
/**
|
13
|
+
* The encapsulation of the version <%= reg.ver %> of the Abstract PII definition.
|
14
|
+
*/
|
15
|
+
public class <%= className %> {
|
16
|
+
<% reg.keyVos.keys.sort.each { |k| fldName = k.to_s.inspect; %>
|
17
|
+
public final static String <%= k.to_s %> = <%=fldName%>;
|
18
|
+
<%}%>
|
19
|
+
|
20
|
+
/**
|
21
|
+
* Impact Levels:
|
22
|
+
*/
|
23
|
+
public static enum Level {
|
24
|
+
<%= (codeIndent * 3)[0..-2] %><%= ALL_IMPACTS.map{|i| i.to_s.upcase}.join(",\n#{(codeIndent * 3)[0..-2]}") %>
|
25
|
+
|
26
|
+
}
|
27
|
+
|
28
|
+
/**
|
29
|
+
* One abstract key definition encapsulation.
|
30
|
+
*/
|
31
|
+
public static class Def {
|
32
|
+
private final String key;
|
33
|
+
private final Level level;
|
34
|
+
private final Map<String, String> props;
|
35
|
+
|
36
|
+
public Def(String key, final Level level, final Map<String, String> props) {
|
37
|
+
this.key = key;
|
38
|
+
this.level = level;
|
39
|
+
this.props = props;
|
40
|
+
}
|
41
|
+
|
42
|
+
public Level getLevel() { return level; }
|
43
|
+
|
44
|
+
public Map<String, String> getProps() { return props; }
|
45
|
+
|
46
|
+
public String getKey() { return key; }
|
47
|
+
}
|
48
|
+
|
49
|
+
/**
|
50
|
+
* The map keyed by field name pointing to the matching instance of the {@link Def} class.
|
51
|
+
*/
|
52
|
+
public static final Map<String, Def> DEFS = unmodifiableMap(new HashMap<String, Def>() {
|
53
|
+
{
|
54
|
+
<% reg.keyVos.keys.sort.each { |k| fldName = k.to_s; fldDef = reg.keyVos[k] %>
|
55
|
+
put(<%= fldName %>, new Def(<%= fldName %>, Level.<%= fldDef.level.to_s.upcase %>, unmodifiableMap(new HashMap<String, String>() {
|
56
|
+
{<% fldDef.attrs.keys.sort.each {|k| keyStr = k.to_s.inspect; valStr = fldDef.attrs[k].inspect %>
|
57
|
+
put(<%=keyStr%>, <%=valStr%>); <% } %>
|
58
|
+
}
|
59
|
+
})));
|
60
|
+
<% } %>
|
61
|
+
}
|
62
|
+
});
|
63
|
+
}
|
64
|
+
|