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
@@ -49,7 +49,13 @@ module DTK::DSL
49
49
  ret
50
50
  end
51
51
  end
52
-
52
+
53
+ def remove_all_except!(*output_keys)
54
+ matching_internal_indexes = output_keys.inject([]) { |a, k| a + possible_key_forms_from_output_key(k) }
55
+ keys.each { |internal_index| delete(internal_index) unless matching_internal_indexes.include?(internal_index) }
56
+ self
57
+ end
58
+
53
59
  private
54
60
 
55
61
  def canonical_key_form_from_output_key(output_key)
@@ -28,9 +28,22 @@ module DTK::DSL
28
28
  Assembly = :asssembly
29
29
 
30
30
  # Used in assembly
31
- Components = :components
32
31
  Workflows = :workflows
33
32
 
33
+ # Used in nested module
34
+ Module = :module
35
+ Version = :version
36
+
37
+ # Used in workflows
38
+ Subtasks = :subtasks
39
+ SubtaskOrder = :subtask_order
40
+ Node = :node
41
+ ExecutionBlocks = :exec_blocks
42
+ Flatten = :flatten
43
+ Action = :action
44
+ Actions = :actions
45
+ OrderedComponents = :ordered_components
46
+
34
47
  # Used at multiple levels
35
48
  Name = :name
36
49
  Description = :description
@@ -40,6 +53,12 @@ module DTK::DSL
40
53
  Attributes = :attributes
41
54
  Value = :value
42
55
  Nodes = :nodes
56
+ Target = :target
57
+ Components = :components
58
+
59
+ # meta info
60
+ Import = :import
61
+ HiddenImportStatement = :hidden_import_statement
43
62
 
44
63
  def self.index(output_key)
45
64
  begin
@@ -18,6 +18,8 @@
18
18
  module DTK
19
19
  module DSL
20
20
  class QualifiedKey
21
+ attr_reader :key_elements
22
+
21
23
  Element = Struct.new(:type, :key)
22
24
  def initialize(elements_to_copy = [])
23
25
  @key_elements = copy(elements_to_copy)
@@ -20,13 +20,18 @@ module DTK::DSL
20
20
  # assumption is that where this included could have a Variations module
21
21
  module ClassMixin
22
22
  module Constant
23
- def matches?(object, constant)
23
+ # opts can have keys:
24
+ # :set_matching_key - if specified this wil be an empty array to add matching_key to
25
+ def matches?(object, constant, opts = {})
24
26
  unless object.nil?
25
27
  variations = variations(constant)
26
28
  if object.is_a?(Hash)
27
- hash_value_of_matching_key?(object, variations)
29
+ if matching_key = hash_key_if_match?(object, variations)
30
+ opts[:set_matching_key] << matching_key if opts[:set_matching_key]
31
+ object[matching_key]
32
+ end
28
33
  elsif object.is_a?(String) || object.is_a?(Symbol)
29
- variations.include?(object.to_s)
34
+ variations.include?(object.to_s)
30
35
  else
31
36
  fail Error.new("Unexpected object class (#{object.class})")
32
37
  end
@@ -79,12 +84,6 @@ module DTK::DSL
79
84
  variations.find { |key| hash.key?(key) }
80
85
  end
81
86
 
82
- def hash_value_of_matching_key?(hash, variations)
83
- if matching_key = hash_key_if_match?(hash, variations)
84
- hash[matching_key]
85
- end
86
- end
87
-
88
87
  end
89
88
  end
90
89
  end
@@ -27,11 +27,15 @@ module DTK::DSL
27
27
  private
28
28
 
29
29
  def generate_element(content, parent)
30
- create_for_generation(content, :filter => parent.filter).generate_yaml_object
30
+ create_for_generation(content, generation_opts(parent)).generate_yaml_object
31
31
  end
32
32
 
33
33
  def generate_element?(content, parent)
34
- create_for_generation(content, :filter => parent.filter).generate_yaml_object?
34
+ create_for_generation(content, generation_opts(parent)).generate_yaml_object?
35
+ end
36
+
37
+ def generation_opts(parent)
38
+ { :filter => parent.filter, :top => parent.top }
35
39
  end
36
40
 
37
41
  end
@@ -29,18 +29,21 @@ module DTK::DSL
29
29
  generate!
30
30
  end
31
31
 
32
- attr_reader :filter
32
+ attr_reader :filter, :top
33
33
 
34
34
  # opts can have keys
35
35
  # :content (required)
36
36
  # :filter
37
+ # :top
37
38
  def generation_initialize(opts = {})
38
39
  unless content = opts[:content]
39
40
  raise Error, "Unexpected that opts[:content] is nil"
40
41
  end
41
42
  @content = content
42
43
  @filter = opts[:filter]
43
- @yaml_object = empty_yaml_object(content)
44
+ @yaml_object = empty_yaml_object(content_input: content)
45
+ @top = opts[:top] || self
46
+ generation_initialize_nested_dsl_files
44
47
  end
45
48
  private :generation_initialize
46
49
 
@@ -60,6 +63,13 @@ module DTK::DSL
60
63
  YamlHelper.generate(@yaml_object)
61
64
  end
62
65
 
66
+ # Array where each element has keys :path and :content
67
+ def generate_yaml_file_path__content_array(top_file_path)
68
+ self.generate!
69
+ [{ :path => top_file_path, :content => YamlHelper.generate(@yaml_object) }] + generate_nested_dsl_file_path__content_array
70
+ end
71
+
72
+
63
73
  # The methods yaml_object_type can be set on concrete class; it wil be set if input and output types are different
64
74
  def yaml_object_type
65
75
  nil
@@ -71,7 +81,7 @@ module DTK::DSL
71
81
  if content.nil?
72
82
  nil
73
83
  else
74
- template_class(parse_template_type).create_for_generation(content, :filter => @filter).generate_yaml_object
84
+ template_class(parse_template_type).create_for_generation(content, :filter => @filter, :top => @top).generate_yaml_object
75
85
  end
76
86
  end
77
87
 
@@ -81,11 +91,16 @@ module DTK::DSL
81
91
  end
82
92
  end
83
93
 
84
- def empty_yaml_object(content_input)
85
- if self.yaml_object_type
86
- FileGenerator::YamlObject.create(:output_type => yaml_object_type)
87
- else
94
+ # opts can have keys
95
+ # :content_input
96
+ # :output_type
97
+ def empty_yaml_object(opts = {})
98
+ if output_type = opts[:output_type] || self.yaml_object_type
99
+ FileGenerator::YamlObject.create(:output_type => output_type)
100
+ elsif content_input = opts[:content_input]
88
101
  FileGenerator::YamlObject.create(:input => content_input)
102
+ else
103
+ raise Error, "If opts[:content_input] is nil, self.yaml_object_type or opts[:output_type] must have a value"
89
104
  end
90
105
  end
91
106
 
@@ -99,32 +114,32 @@ module DTK::DSL
99
114
  obj.respond_to?(:empty?) and obj.empty?
100
115
  end
101
116
 
117
+ def generation_val(key)
118
+ @content.val(key)
119
+ end
120
+
121
+ def generation_req(key)
122
+ @content.req(key)
123
+ end
124
+
102
125
  def skip_for_generation?
103
126
  @content.skip_for_generation?
104
127
  end
105
128
 
106
129
  def generation_set(constant, val)
107
- set_generation_hash(@yaml_object, constant, val)
108
- end
109
-
110
- def generation_set_scalar(scalar)
111
- @yaml_object = scalar
130
+ set_generation_hash(select_yaml_object_or_nested_dsl_file, constant, val)
112
131
  end
113
132
 
114
133
  def generation_merge(hash)
115
- @yaml_object.merge!(hash)
134
+ select_yaml_object_or_nested_dsl_file.merge!(hash)
116
135
  end
117
136
 
118
137
  def generation_add(array_element)
119
- @yaml_object << array_element
138
+ select_yaml_object_or_nested_dsl_file << array_element
120
139
  end
121
140
 
122
- def generation_val(key)
123
- @content.val(key)
124
- end
125
-
126
- def generation_req(key)
127
- @content.req(key)
141
+ def generation_set_scalar(scalar)
142
+ @yaml_object = scalar
128
143
  end
129
144
 
130
145
  end
@@ -52,7 +52,7 @@ module DTK::DSL
52
52
  def self.template_class_aux(template_type, template_version)
53
53
  base_class = Template.const_get("V#{template_version}")
54
54
  begin
55
- base_class.const_get(::DTK::Common::Aux.snake_to_camel_case(template_type.to_s))
55
+ base_class.const_get(Aux.snake_to_camel_case(template_type.to_s))
56
56
  rescue
57
57
  raise Error, "Invalid template_type '#{template_type}'"
58
58
  end
@@ -0,0 +1,77 @@
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 Template
20
+ module NestedDSLFile
21
+ module Mixin
22
+ attr_reader :nested_file_content
23
+
24
+ private
25
+ def generation_initialize_nested_dsl_files
26
+ # If there iis any nested dsl in conetnt being generated then tese wil go on @nested_file_content
27
+ # which has keys that are relative paths and values being
28
+ @nested_file_content = {}
29
+ end
30
+
31
+ def generate_nested_dsl_file_path__content_array
32
+ @nested_file_content.inject([]) do |a, (path, content)|
33
+ a + [{ :path => path, :content => YamlHelper.generate(content) }]
34
+ end
35
+ end
36
+
37
+ # returns the path of a file if @yaml_object should be written to a nested dsl file
38
+ def nested_dsl_file?
39
+ val(:Import)
40
+ end
41
+
42
+ def add_nested_dsl_file_import?(nested_dsl_file)
43
+ unless val(:HiddenImportStatement)
44
+ if @yaml_object.kind_of?(::Hash)
45
+ add_import_statement!(nested_dsl_file, @yaml_object)
46
+ elsif @yaml_object.kind_of?(::Array)
47
+ @yaml_object << add_import_statement!(nested_dsl_file)
48
+ else
49
+ raise Error, "Unexpected that @yaml_object is not a hash or array"
50
+ end
51
+ end
52
+ end
53
+
54
+ def add_import_statement!(nested_dsl_file, yaml_object = nil)
55
+ yaml_object ||= empty_yaml_object(:output_type => :hash)
56
+ set_generation_hash(yaml_object, :Import, nested_dsl_file)
57
+ yaml_object
58
+ end
59
+
60
+ def select_yaml_object_or_nested_dsl_file
61
+ if nested_dsl_file = nested_dsl_file?
62
+ add_nested_dsl_file_import?(nested_dsl_file)
63
+ empty_nested_dsl_file_hash(nested_dsl_file, InputOutputCommon.obj_type(@yaml_object))
64
+ else
65
+ @yaml_object
66
+ end
67
+ end
68
+
69
+ def empty_nested_dsl_file_hash(nested_dsl_file, output_type)
70
+ @top.nested_file_content[nested_dsl_file] ||= empty_yaml_object(output_type: output_type)
71
+ end
72
+
73
+ end
74
+ end
75
+ end
76
+ end
77
+
@@ -0,0 +1,25 @@
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 Template
20
+ module NestedDSLFile
21
+ require_relative('nested_dsl_file/mixin')
22
+ end
23
+ end
24
+ end
25
+
@@ -29,9 +29,14 @@ module DTK::DSL
29
29
  def elements_collection_type
30
30
  nil
31
31
  end
32
-
33
- private
34
32
 
33
+ def file_parser_output_array
34
+ FileParser::Output.create(:output_type => :array)
35
+ end
36
+
37
+ def file_parser_output_hash
38
+ FileParser::Output.create(:output_type => :hash)
39
+ end
35
40
 
36
41
  # opts can have keys
37
42
  # :index
@@ -45,13 +50,7 @@ module DTK::DSL
45
50
  end
46
51
  end
47
52
 
48
- def file_parser_output_array
49
- FileParser::Output.create(:output_type => :array)
50
- end
51
-
52
- def file_parser_output_hash
53
- FileParser::Output.create(:output_type => :hash)
54
- end
53
+ private
55
54
 
56
55
  def input_hash?(input)
57
56
  input.kind_of?(FileParser::Input::Hash)
@@ -54,6 +54,13 @@ module DTK::DSL
54
54
  nil
55
55
  end
56
56
 
57
+ # args can have form
58
+ # (:ParsingErrorName,*parsing_error_params) or
59
+ # (*parsing_error_params)
60
+ def parsing_error(*args)
61
+ parsing_error_with_opts(args)
62
+ end
63
+
57
64
  private
58
65
 
59
66
  def empty_parser_output(input, parent_key)
@@ -67,6 +74,20 @@ module DTK::DSL
67
74
  end
68
75
  end
69
76
 
77
+ def remove_processed_keys_from_input_hash!(&body)
78
+ @found_keys = []
79
+ body.call
80
+ @found_keys.each { |key| input_hash.delete(key) }
81
+ end
82
+
83
+ def add_found_key?(key)
84
+ @found_keys << key if @found_keys
85
+ end
86
+
87
+ def file_parser_output_array
88
+ self.class.file_parser_output_array
89
+ end
90
+
70
91
  # opts can have key
71
92
  # :key_type
72
93
  def parse_child_elements(parse_template_type, key_constant, opts = {})
@@ -105,7 +126,12 @@ module DTK::DSL
105
126
  end
106
127
  def input_key_value?(constant, opts = {})
107
128
  input_hash = opts[:input_hash] || input_hash()
108
- constant_class.matches?(input_hash, constant)
129
+ set_matching_key = []
130
+ ret = constant_class.matches?(input_hash, constant, :set_matching_key => set_matching_key)
131
+ if matching_key = set_matching_key.first
132
+ add_found_key?(matching_key)
133
+ end
134
+ ret
109
135
  end
110
136
 
111
137
  # returns nil or {key => value}
@@ -114,6 +140,10 @@ module DTK::DSL
114
140
  def input_key_and_value?(constant, opts = {})
115
141
  input_hash = opts[:input_hash] || input_hash()
116
142
  constant_class.matching_key_and_value?(input_hash, constant)
143
+ if ret = constant_class.matching_key_and_value?(input_hash, constant)
144
+ add_found_key?(ret.keys.first)
145
+ end
146
+ ret
117
147
  end
118
148
 
119
149
  def parsing_set(constant, val)
@@ -179,13 +209,6 @@ module DTK::DSL
179
209
  raise parsing_error(:MissingKeyValue, key)
180
210
  end
181
211
 
182
- # args can have form
183
- # (:ParsingErrorName,*parsing_error_params) or
184
- # (*parsing_error_params)
185
- def parsing_error(*args)
186
- parsing_error_with_opts(args)
187
- end
188
-
189
212
  # opts can have keys
190
213
  # :key
191
214
  def parsing_error_with_opts(args, opts = {})
@@ -28,6 +28,7 @@ class DTK::DSL::Template
28
28
  Attributes = 'attributes'
29
29
  Nodes = 'nodes'
30
30
  Components = 'components'
31
+ Target = 'target'
31
32
 
32
33
  Workflows = 'workflows'
33
34
  Variations::Workflows = ['workflows', 'workflow']
@@ -49,28 +50,24 @@ class DTK::DSL::Template
49
50
  end
50
51
 
51
52
  def parse!
52
- set :Name, input_key_value(:Name)
53
- set? :Description, input_key_value?(:Description)
54
- set? :Attributes, parse_child_elements?(:attribute, :Attributes)
55
- set? :Nodes, parse_child_elements?(:node, :Nodes)
56
- set? :Components, parse_child_elements?(:component, :Components)
57
- set? :Workflows, parse_child_elements?(:workflow, :Workflows)
58
-
59
- # TODO: This is a catchall that removes ones we so far are parsing and then has catch all
60
- input_hash.delete('name')
61
- input_hash.delete('description')
62
- input_hash.delete('attributes')
63
- input_hash.delete('nodes')
64
- input_hash.delete('components')
65
- input_hash.delete('workflow')
66
- input_hash.delete('workflows')
67
- merge input_hash
53
+ remove_processed_keys_from_input_hash! do
54
+ set :Name, input_key_value(:Name)
55
+ set? :Description, input_key_value?(:Description)
56
+ set? :Target, input_key_value?(:Target)
57
+ set? :Attributes, parse_child_elements?(:attribute, :Attributes)
58
+ set? :Nodes, parse_child_elements?(:node, :Nodes)
59
+ set? :Components, parse_child_elements?(:component, :Components)
60
+ set? :Workflows, parse_child_elements?(:workflow, :Workflows)
61
+ end
62
+ # handle keys not processed
63
+ merge input_hash unless input_hash.empty?
68
64
  end
69
65
 
70
66
  ### For generation
71
67
  def generate!
72
68
  # TODO: add attributes
73
69
  set :Description, val(:Description)
70
+ set :Target, val(:Target)
74
71
  set :Components, generate_child_elements(:component, val(:Components))
75
72
  set :Nodes, generate_child_elements(:node, val(:Nodes))
76
73
  set :Workflows, generate_child_elements(:workflow, val(:Workflows))
@@ -32,7 +32,7 @@ class DTK::DSL::Template
32
32
  end
33
33
 
34
34
  def parse!
35
- set :DSLVersion, input_key_value(:DSLVersion)
35
+ set :DSLVersion, input_key_value?(:DSLVersion) || dsl_version
36
36
  set :ModuleVersion, input_key_value(:ModuleVersion)
37
37
  merge parse_child(:module_ref, input_key_value(:Module), :parent_key => Constant::Module)
38
38
  set? :DependentModules, parse_child_elements?(:dependency, :DependentModules)
@@ -42,7 +42,7 @@ module DTK::DSL
42
42
 
43
43
  def self.parse_elements(input_array, parent_info)
44
44
  input_array.inject(file_parser_output_hash) do |h, component|
45
- name = name(component)
45
+ name = name(component, :parent => parent_info.parent)
46
46
  h.merge(name => parse_element(component, parent_info, :index => name))
47
47
  end
48
48
  end
@@ -85,18 +85,22 @@ module DTK::DSL
85
85
  ret
86
86
  end
87
87
 
88
- def self.name(input)
88
+ # opts can have keys:
89
+ # :parent
90
+ # :this
91
+ # Will not have both keys
92
+ def self.name(input, opts = {})
89
93
  if input.kind_of?(::String)
90
94
  input
91
95
  elsif input.kind_of?(::Hash) and input.size > 0
92
96
  input.keys.first
93
97
  else
94
- raise parsing_error(:WrongObjectType, input, [::String, ::Hash])
98
+ raise (opts[:this] || opts[:parent]).parsing_error([:WrongObjectType, input, [::String, ::Hash]])
95
99
  end
96
100
  end
97
101
 
98
102
  def name
99
- self.class.name(@input)
103
+ self.class.name(@input, :this => self)
100
104
  end
101
105
 
102
106
  def parse_when_string!
@@ -104,14 +108,14 @@ module DTK::DSL
104
108
 
105
109
  def parse_when_hash!
106
110
  unless input_hash.size == 1 and input_hash.values.first.kind_of?(::Hash)
107
- raise parsing_error("Component is ill-formed; it must be string or hash with has value")
111
+ raise parsing_error("Component is ill-formed; it must be string or hash")
108
112
  end
109
113
  properties = input_hash.values.first
110
114
  set? :Attributes, parse_child_elements?(:attribute, :Attributes, :input_hash => properties)
111
115
 
112
- # TODO: This is a catchall that removes ones we so far are parsing and then has catch all
113
- properties.delete('attributes')
114
- merge properties
116
+ # handle keys not processed
117
+ properties.delete(Constant::Attributes)
118
+ merge properties unless properties.empty?
115
119
  end
116
120
 
117
121
  end
@@ -31,9 +31,11 @@ class DTK::DSL::Template
31
31
 
32
32
  ### For parsing
33
33
  def parse!
34
- set :DSLVersion, input_key_value(:DSLVersion)
35
- set :Name, input_key_value(:DSLVersion)
36
- set? :DependentModules, input_key_value?(:DependentModules)
34
+ remove_processed_keys_from_input_hash! do
35
+ set :DSLVersion, input_key_value(:DSLVersion)
36
+ set :Name, input_key_value(:DSLVersion)
37
+ set? :DependentModules, input_key_value?(:DependentModules)
38
+ end
37
39
  merge parse_child(:assembly, input_hash)
38
40
  end
39
41