dtk-dsl 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/lib/dsl/aux.rb +31 -0
  3. data/lib/dsl/directory_parser.rb +3 -7
  4. data/lib/dsl/dsl_version.rb +1 -0
  5. data/lib/dsl/file_generator/content_input/mixin.rb +2 -5
  6. data/lib/dsl/file_generator/content_input/tag/assignment.rb +32 -0
  7. data/lib/dsl/file_generator/content_input/tag/simple.rb +26 -0
  8. data/lib/dsl/file_generator/content_input/{tags.rb → tag.rb} +61 -23
  9. data/lib/dsl/file_generator/content_input.rb +1 -1
  10. data/lib/dsl/file_generator.rb +7 -0
  11. data/lib/dsl/file_parser.rb +1 -0
  12. data/lib/dsl/file_type/match.rb +68 -0
  13. data/lib/dsl/file_type/matching_files.rb +57 -0
  14. data/lib/dsl/file_type/subclasses.rb +71 -0
  15. data/lib/dsl/file_type.rb +120 -51
  16. data/lib/dsl/input_output_common/canonical/hash.rb +7 -1
  17. data/lib/dsl/input_output_common/canonical/hash_key.rb +20 -1
  18. data/lib/dsl/qualified_key.rb +2 -0
  19. data/lib/dsl/template/constant_class_mixin.rb +8 -9
  20. data/lib/dsl/template/generation/class_mixin.rb +6 -2
  21. data/lib/dsl/template/generation/mixin.rb +35 -20
  22. data/lib/dsl/template/loader.rb +1 -1
  23. data/lib/dsl/template/nested_dsl_file/mixin.rb +77 -0
  24. data/lib/dsl/template/nested_dsl_file.rb +25 -0
  25. data/lib/dsl/template/parsing/class_mixin.rb +8 -9
  26. data/lib/dsl/template/parsing/mixin.rb +31 -8
  27. data/lib/dsl/template/v1/assembly.rb +13 -16
  28. data/lib/dsl/template/v1/common_module_summary.rb +1 -1
  29. data/lib/dsl/template/v1/component.rb +12 -8
  30. data/lib/dsl/template/v1/service_instance.rb +5 -3
  31. data/lib/dsl/template/v1/workflow.rb +108 -38
  32. data/lib/dsl/template/v1.rb +4 -0
  33. data/lib/dsl/template.rb +3 -0
  34. data/lib/dsl/version.rb +1 -1
  35. data/lib/dtk_dsl.rb +1 -0
  36. metadata +11 -4
  37. data/lib/dsl/directory_parser/path_info.rb +0 -62
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e6850c2038d1af4481513a9d06fdf9391d589241
4
- data.tar.gz: 8ff25444f0f40e76ebcdab8672ead6a2d71e06b8
3
+ metadata.gz: 80e593bfb3fdafca2ec5659cb23d027021b12646
4
+ data.tar.gz: 719da019d2d90879ae54fb0cd5862644eef253fc
5
5
  SHA512:
6
- metadata.gz: aa6414e6bc8f983c86f4416ce750c4d2754311e48bd6beabe22eab121e013a8326b1d487237f4c1baed66f46a00487a2c2a20aed3b7ad9e982a8336628c15b77
7
- data.tar.gz: c843fe596c4c9d9ecd5f53d06eb5c612c374b736d1af3ddf2d76094a83c3821dcb68e439580ef22d8cfd8a34ab38d7db465e81f3b21a6d9e7c678d1fa804af5a
6
+ metadata.gz: 5180a6a6ff23dff2c813d535b04885164bef6d45e397843c06cab7f5907cea83681846f62fae3025b4800074f2b5968d1e864f5e804261cdaa5013d37be14013
7
+ data.tar.gz: af53ec0c65ce2625bcc8bd2548e7c3e8a66e1748697565952eb9755d99cb4f24aba8cd0a5e42f7d6d6d90537064f2461ccddbe262dc893819dae12da02881eee
data/lib/dsl/aux.rb ADDED
@@ -0,0 +1,31 @@
1
+ #
2
+ # Copyright (C) 2010-2016 dtk contributors
3
+ #
4
+ # This file is part of the dtk project.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+ module DTK
19
+ module DSL
20
+ module Aux
21
+ def self.snake_to_camel_case(string)
22
+ ::DTK::Common::Aux.snake_to_camel_case(string)
23
+ end
24
+
25
+ def self.camel_case_to_snake(string)
26
+ string.gsub(/(.)([A-Z])/,'\1_\2').downcase
27
+ end
28
+
29
+ end
30
+ end
31
+ end
@@ -19,14 +19,10 @@
19
19
  module DTK::DSL
20
20
  # Abstract class; application that uses this library must provide a concrete class that inherits from this
21
21
  class DirectoryParser
22
- require_relative('directory_parser/path_info')
23
- # file_types - a single or array of FileObj objects
24
- # opts can have keys
25
- # :file_path - string
26
- # :dir_path - string
27
- # Returns FileObj that matches a file_typeo bject that matches a file_type in file_types
22
+ # file_types - a single or array of FileType
23
+ # Returns a FileObj that matches a file_type object that matches a file_type in file_types
28
24
  # or returns nil if no match found
29
- def self.matching_file_obj?(file_types, opts = {})
25
+ def self.matching_file_obj?(_file_types, *_args)
30
26
  raise Error::NoMethodForConcreteClass.new(self.class)
31
27
  end
32
28
  end
@@ -19,6 +19,7 @@
19
19
  module DTK::DSL
20
20
  # This refers to semnatic dsl version
21
21
  class DSLVersion < ::String
22
+ #versions in DSL_VERIONS are ordered so that most recent versions are last
22
23
  DSL_VERSIONS = ['1.0.0']
23
24
 
24
25
  def self.legal?(str)
@@ -34,10 +34,7 @@ module DTK::DSL
34
34
  end
35
35
 
36
36
  def add_tags!(new_tags)
37
- Tags.raise_error_if_invalid(new_tags)
38
- new_tags = [new_tags] unless new_tags.kind_of?(::Array)
39
- @tags += new_tags
40
- @tags.uniq!
37
+ Tag.add_tags!(@tags, new_tags)
41
38
  self
42
39
  end
43
40
 
@@ -46,7 +43,7 @@ module DTK::DSL
46
43
  end
47
44
 
48
45
  def matches_tag_type?(tag_type)
49
- !! @tags.find { |tag| Tags.matches_tag_type?(tag_type, tag) }
46
+ !! @tags.find { |tag| Tag.matches_tag_type?(tag_type, tag) }
50
47
  end
51
48
 
52
49
  def add_tags_to_obj?(obj, new_tags)
@@ -0,0 +1,32 @@
1
+ #
2
+ # Copyright (C) 2010-2016 dtk contributors
3
+ #
4
+ # This file is part of the dtk project.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+ module DTK::DSL
19
+ class FileGenerator::ContentInput
20
+ class Tag
21
+ class Assignment < self
22
+ attr_reader :value
23
+ def initialize(tag_name, tag_value)
24
+ super(tag_name)
25
+ @value = tag_value
26
+ end
27
+
28
+ end
29
+ end
30
+ end
31
+ end
32
+
@@ -0,0 +1,26 @@
1
+ #
2
+ # Copyright (C) 2010-2016 dtk contributors
3
+ #
4
+ # This file is part of the dtk project.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+ module DTK::DSL
19
+ class FileGenerator::ContentInput
20
+ class Tag
21
+ class Simple < self
22
+ end
23
+ end
24
+ end
25
+ end
26
+
@@ -17,7 +17,57 @@
17
17
  #
18
18
  module DTK::DSL
19
19
  class FileGenerator::ContentInput
20
- module Tags
20
+ class Tag
21
+ require_relative('tag/simple')
22
+ require_relative('tag/assignment')
23
+
24
+ attr_reader :name
25
+ def initialize(tag_name)
26
+ @name = tag_name
27
+ end
28
+ private :initialize
29
+
30
+ def self.create(tag_input)
31
+ tag =
32
+ if tag_input.kind_of?(::String) or tag_input.kind_of?(::Symbol)
33
+ Simple.new(tag_input.to_sym)
34
+ elsif tag_input.kind_of?(::Hash) and tag_input.size == 1
35
+ tag_name = tag_input.keys.first
36
+ if tag_name.kind_of?(::String) or tag_name.kind_of?(::Symbol)
37
+ tag_value = tag_input.values.first
38
+ Assignment.new(tag_name.to_sym, tag_value)
39
+ end
40
+ end
41
+ raise Error, "Invalid form for a tag: #{tag_input.inspect}" unless tag
42
+ raise Error, "Invalid tag name '#{tag.name}'" unless tag.valid_tag_name?
43
+ tag
44
+ end
45
+ private_class_method :create
46
+
47
+ def self.add_tags!(tags, new_tags_input)
48
+ new_tags_input.each do |new_tag_input|
49
+ new_tag = create(new_tag_input)
50
+ new_tag_name = new_tag.name
51
+ unless match = tags.find { |tag| tag.name == new_tag_name }
52
+ tags << new_tag
53
+ else
54
+ raise_error_if_conflicting_tags(match, new_tag)
55
+ end
56
+ end
57
+ tags
58
+ end
59
+
60
+ def self.matches_tag_type?(tag_type, tag)
61
+ tag_type_split = split(tag_type)
62
+ tag_split = split(tag.name)
63
+ if tag_split.size >= tag_type_split.size
64
+ tag_type_split.each_with_index do |tag_type_part, i|
65
+ return nil unless tag_type_part == tag_split[i]
66
+ end
67
+ true
68
+ end
69
+ end
70
+
21
71
  #####
22
72
  # In this module a 'tag_type' subsumes a tag and consitutes an element in BASE_LEVEL_TAGS or one its prefixes
23
73
  #
@@ -27,35 +77,23 @@ module DTK::DSL
27
77
  :desired__derived__default,
28
78
  :desired__derived__propagated,
29
79
  :actual,
30
- :hidden
80
+ :hidden,
81
+ :dsl_location
31
82
  ]
32
83
 
33
- def self.matches_tag_type?(tag_type, tag)
34
- tag_type_split = split(tag_type)
35
- tag_split = split(tag)
36
- if tag_split.size >= tag_type_split.size
37
- tag_type_split.each_with_index do |tag_type_part, i|
38
- return nil unless tag_type_part == tag_split[i]
39
- end
40
- true
41
- end
84
+ def valid_tag_name?
85
+ self.class.valid_tag_types.include?(name)
42
86
  end
43
87
 
44
- def self.valid?(tag_type)
45
- valid_tag_types.include?(tag_type)
46
- end
88
+ private
47
89
 
48
- def self.raise_error_if_invalid(tag_types)
49
- tag_types = [tag_types] unless tag_types.kind_of?(::Array)
50
- bad_tag_types = tag_types.select { |tag| !valid?(tag)}
51
- unless bad_tag_types.empty?
52
- err_msg = bad_tag_types.size == 1 ? "Invalid tag '#{bad_tag_types.first}'" : "Invalid tag_types: #{bad_tag_types.join(', ')}"
53
- raise Error, err_msg
90
+ def raise_error_if_conflicting_tags(existing_tag, new_tag)
91
+ if (existing_tag.class != new_tag.class) or
92
+ (existing_tag.kind_of?(Assignment) and existing_tag.value != new_tag.value)
93
+ raise Error, "The tags (#{existing_tag.inspect}) and (#{new_tag.inspect}) are conflicting"
54
94
  end
55
95
  end
56
-
57
- private
58
-
96
+
59
97
  def self.valid_tag_types
60
98
  @valid_tag_tag_types ||= compute_valid_tag_types
61
99
  end
@@ -18,7 +18,7 @@
18
18
  module DTK::DSL
19
19
  class FileGenerator
20
20
  class ContentInput < InputOutputCommon::Canonical
21
- require_relative('content_input/tags')
21
+ require_relative('content_input/tag')
22
22
  require_relative('content_input/mixin')
23
23
  # mixin must go before the files below
24
24
  require_relative('content_input/hash')
@@ -34,6 +34,13 @@ module DTK::DSL
34
34
  template_class = Template.template_class(parse_template_type, dsl_version)
35
35
  template_class.create_for_generation(content_input, opts).generate_yaml_text
36
36
  end
37
+
38
+ # opts can have keys
39
+ # :filter
40
+ def self.generate_yaml_file_path__content_array(parse_template_type, top_file_path, content_input, dsl_version, opts = {})
41
+ template_class = Template.template_class(parse_template_type, dsl_version)
42
+ template_class.create_for_generation(content_input, opts).generate_yaml_file_path__content_array(top_file_path)
43
+ end
37
44
  end
38
45
  end
39
46
 
@@ -57,6 +57,7 @@ module DTK::DSL
57
57
 
58
58
  DSL_VERSION_KEY = 'dsl_version'
59
59
  def self.dsl_version__raise_error_if_illegal(input_hash, file_obj)
60
+ raise Error::Usage, "Ill-formed DSL#{file_ref_in_error(file_obj)}" unless input_hash.kind_of?(::Hash)
60
61
  if dsl_version = input_hash[DSL_VERSION_KEY]
61
62
  unless DSLVersion.legal?(dsl_version)
62
63
  raise Error::Usage, "Illegal DSL version '#{dsl_version}'#{file_ref_in_error(file_obj)}"
@@ -0,0 +1,68 @@
1
+ #
2
+ # Copyright (C) 2010-2016 dtk contributors
3
+ #
4
+ # This file is part of the dtk project.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ module DTK::DSL
20
+ class FileType
21
+ class Match
22
+ def initialize(file_type)
23
+ @file_type = file_type
24
+ end
25
+ private :initialize
26
+
27
+ # opts can have keys:
28
+ # :exact (Booelan) - meaning regexp completely matches file_path; otherwise it means jsut match the end
29
+ def self.matches?(file_type, file_path, opts = {})
30
+ new(file_type).matches?(file_path, opts = {})
31
+ end
32
+
33
+ def matches?(file_path, opts = {})
34
+ file_path = remove_multiple_slashes(file_path)
35
+ if opts[:exact]
36
+ file_path =~ regexp_exact
37
+ else
38
+ # extra check to see if regexp is just for file part or has '/' seperators
39
+ # if just for file then we can have more restrictive match
40
+ if regexp.source =~ Regexp.new('/')
41
+ file_path =~ regexp_match_end
42
+ else
43
+ file_path.split('/').last =~ regexp_exact
44
+ end
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def remove_multiple_slashes(string)
51
+ string.split('/').reject { |el| el.empty?}.join('/')
52
+ end
53
+
54
+ def regexp
55
+ @regexp ||= @file_type.regexp
56
+ end
57
+
58
+ def regexp_exact
59
+ @regexp_exact ||= Regexp.new("^#{regexp.source}$")
60
+ end
61
+
62
+ def regexp_match_end
63
+ @regexp_match_end ||= Regexp.new("#{regexp.source}$")
64
+ end
65
+
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,57 @@
1
+ #
2
+ # Copyright (C) 2010-2016 dtk contributors
3
+ #
4
+ # This file is part of the dtk project.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ module DTK::DSL
20
+ class FileType
21
+ class MatchingFiles
22
+ attr_reader :file_type_instance, :file_paths
23
+ def initialize(file_type_instance)
24
+ @file_type_instance = file_type_instance
25
+ @file_paths = []
26
+ end
27
+ private :initialize
28
+
29
+ def add_file_path!(file_path)
30
+ @file_paths << file_path
31
+ self
32
+ end
33
+
34
+ # Returns array of MatchingFiles
35
+ def self.matching_files_array(file_type_classes, file_paths)
36
+ ndx_ret = {}
37
+ file_type_classes = [file_type_classes] unless file_type_classes.kind_of?(Array)
38
+ file_type_classes.each do |file_type_class|
39
+ file_paths.each do |file_path|
40
+ if file_type_instance = file_type_class.file_type_instance_if_match?(file_path)
41
+ file_type_instance_index = file_type_instance.index
42
+ if matching_index = ndx_ret.keys.find { |index| index == file_type_instance_index }
43
+ ndx_ret[matching_index].add_file_path!(file_path)
44
+ else
45
+ ndx_ret[file_type_instance_index] = new(file_type_instance).add_file_path!(file_path)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ ndx_ret.values
51
+ end
52
+
53
+ end
54
+ end
55
+ end
56
+
57
+
@@ -0,0 +1,71 @@
1
+ #
2
+ # Copyright (C) 2010-2016 dtk contributors
3
+ #
4
+ # This file is part of the dtk project.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+
19
+ module DTK::DSL
20
+ class FileType
21
+ class CommonModule < self
22
+ def self.top_level_type
23
+ :common_module
24
+ end
25
+
26
+ class DSLFile < self
27
+ class Top < self
28
+ end
29
+ end
30
+ end
31
+
32
+ class ServiceInstance < self
33
+ def self.top_level_type
34
+ :service_instance
35
+ end
36
+
37
+ class DSLFile < self
38
+ class Top < self
39
+ end
40
+ end
41
+
42
+ class NestedModule < self
43
+ attr_reader :module_name
44
+ # params can have keys:
45
+ # :module_name (required)
46
+ def initialize(params = {})
47
+ unless @module_name = params[:module_name]
48
+ raise Error, "Unexpected that opts[:module_name] is nil"
49
+ end
50
+ end
51
+
52
+ def index
53
+ "#{super}--#{@module_name}"
54
+ end
55
+
56
+ def canonical_path
57
+ self.class.canonical_path_lambda.call(:module_name => @module_name)
58
+ end
59
+
60
+ def base_dir
61
+ matching_type_def(:base_dir_lambda).call(:module_name => @module_name)
62
+ end
63
+
64
+ class DSLFile < self
65
+ class Top < self
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
data/lib/dsl/file_type.rb CHANGED
@@ -17,62 +17,131 @@
17
17
  #
18
18
 
19
19
  module DTK::DSL
20
- # This has specific file type meta info
21
20
  class FileType
22
- Types =
23
- [
24
- {
25
- :type => :common_module,
26
- :regexp => "/dtk\.module\.(yml|yaml)/",
27
- :canonical_path => 'dtk.module.yaml',
28
- :backup_path => 'dtk.module.bak.yaml',
29
- :print_name => 'module DSL file'
30
- },
31
- {
32
- :type => :service_instance,
33
- :regexp => "/dtk\.service\.(yml|yaml)/",
34
- :canonical_path => 'dtk.service.yaml',
35
- :backup_path => 'dtk.service.bak.yaml',
36
- :print_name => 'service DSL file'
37
- }
38
- ]
39
- # regexps purposely do not have ^ or $ so calling function can insert these depending on context
40
-
41
- Types.each do |type_info|
42
- # convert to camel case
43
- class_name = type_info[:type].to_s.gsub(/(?<=_|^)(\w)/){$1.upcase}.gsub(/(?:_)(\w)/,'\1')
44
- class_eval("
45
- class #{class_name} < self
46
- def self.type
47
- :#{type_info[:type]}
48
- end
49
- def self.print_name
50
- '#{type_info[:print_name]}'
51
- end
52
- def self.canonical_path
53
- '#{type_info[:canonical_path]}'
54
- end
55
- def self.backup_path
56
- '#{type_info[:backup_path]}'
57
- end
58
-
59
- private
60
-
61
- def self.regexp
62
- #{type_info[:regexp]}
63
- end
64
- end")
65
- end
66
-
67
- def self.create_path_info
68
- DirectoryParser::PathInfo.new(regexp)
69
- end
70
-
21
+ require_relative('file_type/subclasses')
22
+ require_relative('file_type/match')
23
+ require_relative('file_type/matching_files')
24
+
71
25
  # opts can have keys:
72
26
  # :exact - Booelan (default: false) - meaning regexp completely matches file_path
73
27
  def self.matches?(file_path, opts = {})
74
- DirectoryParser::PathInfo.matches?(file_path, regexp, opts)
28
+ Match.matches?(self, file_path, opts)
29
+ end
30
+ def matches?(file_path, opts = {})
31
+ Match.matches?(self, file_path, opts)
32
+ end
33
+
34
+ # Returns array of MatchingFiles or nil
35
+ def self.matching_files_array?(file_type_classes, file_paths)
36
+ MatchingFiles.matching_files_array?(file_type_classes, file_paths)
37
+ end
38
+
39
+ SERVICE_INSTANCE_NESTED_MODULE_DIR = 'modules'
40
+ TYPES = {
41
+ CommonModule::DSLFile::Top => {
42
+ :regexp => Regexp.new("dtk\.module\.(yml|yaml)"),
43
+ :canonical_path_lambda => lambda { |_params| 'dtk.module.yaml' },
44
+ :print_name => 'module DSL file'
45
+ },
46
+ ServiceInstance::DSLFile::Top => {
47
+ :regexp => Regexp.new("dtk\.service\.(yml|yaml)"),
48
+ :canonical_path_lambda => lambda { |_params| 'dtk.service.yaml' },
49
+ :print_name => 'service DSL file'
50
+ },
51
+ ServiceInstance::NestedModule => {
52
+ :instance_match_lambda => lambda { |path| path =~ Regexp.new("^#{SERVICE_INSTANCE_NESTED_MODULE_DIR}/([^/]+)/.+$") && { :module_name => $1 } },
53
+ :base_dir_lambda => lambda { |params| "#{SERVICE_INSTANCE_NESTED_MODULE_DIR}/#{params[:module_name]}" },
54
+ :print_name => 'nested module file'
55
+ },
56
+ ServiceInstance::NestedModule::DSLFile::Top => {
57
+ :regexp => Regexp.new("#{SERVICE_INSTANCE_NESTED_MODULE_DIR}/[^/]+/dtk\.nested_module\.(yml|yaml)"),
58
+ :canonical_path_lambda => lambda { |params| "#{SERVICE_INSTANCE_NESTED_MODULE_DIR}/#{params[:module_name]}/dtk.nested_module.yaml" },
59
+ :print_name => 'nested module DSL file'
60
+ }
61
+ }
62
+ # regexps, except for one in :instance_match_lambda, purposely do not have ^ or $ so calling function can insert these depending on context
63
+
64
+ def self.print_name
65
+ matching_type_def(:print_name)
66
+ end
67
+
68
+ def self.regexp
69
+ matching_type_def(:regexp)
70
+ end
71
+
72
+ def self.canonical_path
73
+ canonical_path_lambda.call({})
74
+ end
75
+ # This can be over-written
76
+ def canonical_path
77
+ self.class.canonical_path
78
+ end
79
+
80
+ def self.backup_path
81
+ backup_path_from_canonical_path(canonical_path)
82
+ end
83
+ def backup_path
84
+ self.class.backup_path_from_canonical_path(canonical_path)
85
+ end
86
+
87
+ def self.base_dir
88
+ nil
75
89
  end
90
+ # This can be over-written
91
+ def base_dir
92
+ self.class.base_dir
93
+ end
94
+
95
+
96
+ # If match it retuns a hash with params that can be used to create a File Type instance
97
+ def self.file_type_instance_if_match?(file_path)
98
+ # just want to match 'this' and dont want to match parent so not using matching_type_def
99
+ if instance_match_lambda = TYPES[self][:instance_match_lambda]
100
+ if hash_params_for_new = instance_match_lambda.call(file_path)
101
+ new(hash_params_for_new)
102
+ end
103
+ end
104
+ end
105
+
106
+ def self.type_level_type
107
+ raise Error::NoMethodForConcreteClass.new(self)
108
+ end
109
+
110
+ # This can be over-written
111
+ def index
112
+ self.class.to_s
113
+ end
114
+
115
+ private
116
+
117
+ BASE_CLASS = FileType
118
+ # The method matching_type_def starts at tpe and looks to see if or recursive parents have definition
119
+ def self.matching_type_def(key, klass = nil, orig_klass = nil)
120
+ klass ||= self
121
+ orig_klass ||= self
122
+ fail Error, "Type '#{orig_klass}' is not in TYPES" if klass == BASE_CLASS
123
+ if type_def_hash = TYPES[klass]
124
+ type_def_hash[key]
125
+ else
126
+ matching_type_def(key, klass.superclass, orig_klass)
127
+ end
128
+ end
129
+ def matching_type_def(key)
130
+ self.class.matching_type_def(key)
131
+ end
132
+
133
+ def self.canonical_path_lambda
134
+ matching_type_def(:canonical_path_lambda)
135
+ end
136
+
137
+ FILE_PREFIX = 'bak'
138
+ def self.backup_path_from_canonical_path(canonical_path)
139
+ split_path = canonical_path.split('/')
140
+ file_path = split_path.pop
141
+ backup_file_path = "#{FILE_PREFIX}.#{file_path}"
142
+ split_path.empty? ? backup_file_path : "#{split_path.join('/')}/#{backup_file_path}"
143
+ end
144
+
76
145
  end
77
146
  end
78
147