dtk-dsl 1.0.0 → 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.
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